日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

【RK3288 Android 7.1 / KEN】双屏异显流程

發布時間:2023/12/14 Android 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【RK3288 Android 7.1 / KEN】双屏异显流程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

RK3288_Android 7.1 雙屏異顯流程

  • 異顯功能使能
        • 控制代碼位置:
  • 觸發異顯
        • 控制代碼位置:
            • 方法 1 主要流程:
            • 方法 2 關鍵步驟:
  • 異顯流程
        • 控制代碼位置:
        • setOnlyShowInExtendDisplay() 主要流程:
          • 1
          • 2
          • 3
          • 4
        • moveTransitionToSecondDisplay() 主要流程:
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14


異顯功能使能

—— 即控制 異顯功能 能否 使用,以及異顯功能是否 啟用

控制代碼位置:

packages/apps/Settings/src/com/android/settings/HdmiSettings.java

  • 屬性 1:
    android.provider.Settings.DUAL_SCREEN_MODE
    異顯功能全局開關 —— 0 表示 關閉1 表示 打開

  • 屬性 2:
    android.provider.Settings.DUAL_SCREEN_ICON_USED
    異顯功能狀態 —— 0 表示 同顯1 表示 異顯

以上部分并不是雙屏異顯的關鍵


觸發異顯

控制代碼位置:

framework/base/core/java/com/android/internal/policy/DecorView.java

  • 關鍵方法 1:
    initDualScreenConfig()
    進行異顯觸發配置的初始化
方法 1 主要流程:
  • String dualScreenKeyCodes = SystemProperties.get("sys.dual_screen.keycodes");
    獲取 sys.dual_screen.keycodes 屬性值(該屬性值標記 異顯觸發鍵
    該屬性值默認是 24,25,分別對應 音量鍵 +音量鍵 -

  • mDualScreenCodeInterval = SystemProperties.getLong("sys.dual_screen.interval", 2000L);
    獲取 sys.dual_screen_interval 屬性值(該屬性標記 觸發時間間隔

    • 關鍵方法 2:
      trigerDualScreen()
      觸發異顯
    方法 2 關鍵步驟:
  • getRootWindowSession().setOnlyShowInExtendDisplay(getWindow(),-1);
    通過 Session 調用 WMS(WindowManagerService) 的 setOnlyShowInExtendDisplay 方法,進入異顯流程
    • 關鍵方法 3:
      trigerSyncScreen()
      觸發同顯
      (暫時不展開)

    異顯流程

    主要就是上一環節中調用的 WMS 的 setOnlyShowInExtendDisplay

    控制代碼位置:

    frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java

    setOnlyShowInExtendDisplay() 主要流程:

    1
    if (mDisplayContents == null || mDisplayContents.size() <= 1) {return; }
    • 如果展示內容為 null 或小于等于 1 時,退出函數
    • 通常為副屏不存在時才會發生上述情況(即只有一個屏)
    2
    final int displayCount = mDisplayContents.size(); DisplayContent defaultContent = getDefaultDisplayContentLocked(); int displayId = 0; DisplayContent secondDisplayContent = null; for (int i = 0; i < displayCount;i++) {final DisplayContent content = mDisplayContents.valueAt(i);if (content != defaultContent) {secondDisplayContent = content;displayId = secondDisplayContent.getDisplayId();break;} }
    3
    if(secondDisplayContent == null){return; } if(!okToDisplay()){return; } WindowState current = windowForClientLocked(session, client, false); if(isHomeWindow(current)){return; } AppWindowToken wtoken = current.mAppToken; if(wtoken == null){return; }
    • 如果存在副屏需要顯示的內容為 null,副屏未就緒(包括副屏未開啟、處于 Frozen 狀態等)或主屏窗口處于 Home 等情況時,return 退出方法,結束異顯流程
    4
    int groupId = wtoken.mTask.mTaskId; mH.sendMessage(mH.obtainMessage(H.DO_TASK_DISPLAY_CHANGED, groupId, -1));
    • 獲取主屏當前應用的 taskId
    • 發送 “DO_TASK_DISPLAY_CHANGED” Message
    • 隨后 handlerMessage 方法接收到 Message 之后,調用 moveTransitionToSecondDisplay() 方法

    moveTransitionToSecondDisplay() 主要流程:

    1
    if (!isShowDualScreen()) {mSecondTaskIds.clear(); } else {if (mSecondDisplayTaskId != -1) {return;} }
    • if 語句判斷是否處于異顯狀態
    • 當不處于異顯狀態時,先清空副屏的 mSecondTaskIds 列表,準備接收副屏需要顯示的內容
    • 當處于異顯狀態時,執行 else 語句,若判斷副屏的 taskId 不等于 -1,即任務棧正常,則 return 退出方法,保持異顯的狀態
    2
    Settings.System.putInt(mContext.getContentResolver(), Settings.DUAL_SCREEN_ICON_USED, 0);
    • 先將 DUAL_SCREEN_ICON_USED 屬性值設置為同顯狀態
    3
    List<Integer> allTaskIds = null; try {allTaskIds = mActivityManager.getAllTaskIds(); } catch (Exception e) {if(DEBUG) Log.i(TAG_DUALSCREEN, "WindowManagerService->getAllTaskIds->e:" + e); }if (allTaskIds == null || allTaskIds.size() < 2)return;
    • 通過 ActivityManager 獲取所有任務的 taskId
    • if 語句判斷 allTaskIds 為 null 或者 allTaskIds 任務 Id 數小于 2 時,return 退出方法
    4
    if(mDisplayContents == null || mDisplayContents.size() <= 1){return; } final int displayCount = mDisplayContents.size(); DisplayContent defaultContent = getDefaultDisplayContentLocked(); int displayId = 0; DisplayContent secondDisplayContent = null; for(int i = 0; i < displayCount;i++){final DisplayContent content = mDisplayContents.valueAt(i);if(content != defaultContent){secondDisplayContent = content;displayId = secondDisplayContent.getDisplayId();if(DEBUG) Log.d(TAG_DUALSCREEN, "moveTransitionToSecondDisplay->secondDisplayId:" + displayId);break;} } if(secondDisplayContent == null){return; } if(!okToDisplay()){return; }
    • 這部分跟 setOnlyShowInExtendDisplay() 方法的內容類似
    5
    SurfaceControl.openTransaction(); WindowState win = null; WindowList defaultWindows = defaultContent.getWindowList();
    • openTransaction() 和 endTransaction() 之間是對 Surface 的操作
    • 獲取主屏的 windows 列表(主屏所有的 windows)
    6
    int topTaskId = -1; if (allTaskIds != null && allTaskIds.size() > 0) {topTaskId = allTaskIds.get(0);mSecondTaskIds.add(topTaskId); }
    • 獲取頂層應用的 taskId,添加到 mSecondTaskIds 列表中
    7
    for(int i= defaultWindows.size()-1;i>=0;i--){win = defaultWindows.get(i);if(win == null){continue;}if (win.mAppToken == null){continue;}boolean isSurface=false;int windowTaskId=-1;if(win.taskId==-1&&win.mAttachedWindow!=null && win.mAttachedWindow.mAppToken.mTask.mTaskId==topTaskId){isSurface=true;Log.i("DualScreenIs","isSurface = "+isSurface);} else if(win.mAppToken.mTask == null){continue;}else{windowTaskId = win.mAppToken.mTask.mTaskId;}if(windowTaskId == topTaskId||isSurface){if(DEBUG) Log.i(TAG_DUALSCREEN, "moveTransitionToSecondDisplay->add win:" + win);defaultWindows.remove(win);mTempWindowList.add(win);win.mDisplayContent = secondDisplayContent;if(DEBUG) Log.i(TAG_DUALSCREEN,"win.mDisplayContent = "+win.mDisplayContent+ " secondDisplayContent = "+secondDisplayContent);if(win.mWinAnimator != null){int layerStack = secondDisplayContent.getDisplay().getLayerStack();if(win.mWinAnimator.mSurfaceController!= null){win.mWinAnimator.mSurfaceController.mSurfaceControl.setLayerStack(layerStack);}}secondDisplayAddList.add(0,win);mSecondTopPackageName = win.getOwningPackage();} }
    • 該 for 循環會對主屏的所有 windows 都遍歷一遍
    • 首先獲取 windows,若 win 為 null,或者 mAppToken 為 null,則跳出該次循環,直接進入下一次循環
    • 判斷 win 是否處于頂層,如果是,將標志位 isSurface 賦值為 true
    • 若 win 不是處于頂層,且 win.mAppToken.mTask 是空,則跳出該次循環,直接進入下一次循環
    • 如果不是上述兩種情況,則將 windowTaskId 賦值為 win 的 mTaskId
    • 判斷當前 win 是否處于頂層,如果是,則從主屏的 WindowList 中移除該窗口,并將該窗口添加進一個臨時的 WindowList。設置該窗口的 mDisplayContent 為副屏的 secondDisplayContent。設置該窗口的 win.layerStack 為副屏的 display.layerStack。然后將該 win 添加進副屏的 windowlist 中,并獲取到該 win 對應的包名,保存為副屏的頂層包名 mSecondTopPackageName
    8
    DisplayContent displayContent = getDefaultDisplayContentLocked(); if (displayContent != null) {final DisplayInfo displayInfo = displayContent.getDisplayInfo();int rotation = 0;if(displayInfo.logicalWidth > displayInfo.logicalHeight) {rotation = Surface.ROTATION_90;} else {rotation = Surface.ROTATION_0;}Settings.System.putInt(mContext.getContentResolver(), Settings.System.USER_ROTATION, rotation); }
    • 這部分主要是根據設備的長寬比,確定屏幕的方向
    9
    secondDisplayWindows.clear(); secondDisplayWindows.addAll(secondDisplayAddList);
    • 清空副屏的 secondDisplayWindows.clear()
    • 將前面第 7 步 for 循環中,secondDisplayAddList 保存的 windows,全部添加到 secondDisplayWindows(這個才是正式的副屏的 WindowList)
    10
    for (int i = 0; i < displayCount; i++) {final DisplayContent content = mDisplayContents.valueAt(i);mLayersController.assignLayersLocked(content.getWindowList());content.layoutNeeded = true; }
    11
    mSecondDisplayTaskId = topTaskId; misMovingToSecond = true; Settings.System.putInt(mContext.getContentResolver(), Settings.DUAL_SCREEN_ICON_USED, 1);
    • 將副屏的顯示 taskId 設置為頂層應用的 topTaskId
    • 將表示 window 正在移動到副屏的標志位 misMovingToSecond 設置為 true
    • 設置屬性值 DUAL_SCREEN_ICON_USED 為 1,表示處于異顯狀態
    12
    curMoveTaskId = getLaunchTaskId(); if (curMoveTaskId == -1) {curMoveTaskId = allTaskIds.get(1); } if (DEBUG) Log.i(TAG_DUALSCREEN, "WindowManagerService->curMoveTaskId:" + curMoveTaskId ); switchFocusWindow(curMoveTaskId);
    • 獲取當前應用的 taskId,如果該 taskId 等于 -1,獲取第二個 taskId,賦值給 curMoveTaskId
    • 將 Focus 的 window 設置為 curMoveTaskId 所對應的 window
    13
    updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, false); mAppTransition.setReady(); mWindowPlacerLocked.performSurfacePlacement();
    • 調用 performSurfacePlacement(),刷新每個 display 及窗口顯示的大小和位置
    14
    currentTimeout = Settings.System.getLong(mContext.getContentResolver(),Settings.System.SCREEN_OFF_TIMEOUT,3000); Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT,2147483647); Binder.restoreCallingIdentity(origId);
    • 獲取待機時間
    • 設置待機時間

    總結

    以上是生活随笔為你收集整理的【RK3288 Android 7.1 / KEN】双屏异显流程的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。