Android 7-多窗口加载显示流程

(1)RecentsButton(虚拟键)触发事件

长按RecentsButton(虚拟键)会触发KeyButtonView.java的onTouchEvent()方法
按下(ACTION_DOWN)后开始计时,如果一段时间ViewConfiguration.getLongPressTimeout()后,没有释放(ACTION_UP)
说明用户想长按,于是我们的postDelayed扔出了一个Runnable来进行长按处理。如果在ViewConfiguration.getLongPressTimeout()之内,用户释放(ACTION_UP)了,那就是个短按事件了,就会进入Recents Task 加载显示流程。
/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java

  1. private final Runnable mCheckLongPress = new Runnable() {

  2. public void run() {

  3. if (isPressed()) {

  4. // Log.d("KeyButtonView", "longpressed: " + this);

  5. if (isLongClickable()) {

  6. // Just an old-fashioned ImageView

  7. performLongClick();

  8. mLongClicked = true;

  9. }

  10. ......

  11. };

  12. public boolean onTouchEvent(MotionEvent ev) {

  13. ......

  14. switch (action) {

  15. case MotionEvent.ACTION_DOWN:

  16. ......

  17. //postDelayed长按事件

  18. postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());

  19. break;

  20. ......

  21. case MotionEvent.ACTION_UP:

  22. ......

  23. }

进入performLongClick()->performLongClickInternal()方法

 
  1. /frameworks/base/core/java/android/view/View.java

  2. private boolean performLongClickInternal(float x, float y) {

  3. ......

  4. final ListenerInfo li = mListenerInfo;

  5. if (li != null && li.mOnLongClickListener != null) {

  6. handled = li.mOnLongClickListener.onLongClick(View.this);

  7. }

  8. ......

  9. }

SystemUI启动的SystemBars的时候会注册RecentsButton长按事件(由于是分析多窗口显示加载流程,这里暂且不分析SystemBars启动流程),recentsButton.setOnLongClickListener(mRecentsLongClickListener)
最终会在PhoneStatusBar.java 里面触发分屏toggleSplitScreenMode()

/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

 
  1. //recentsButton长按事件具体实现

  2. private View.OnLongClickListener mRecentsLongClickListener =

  3. new View.OnLongClickListener() {

  4.  
  5. @Override

  6. public boolean onLongClick(View v) {

  7. if (mRecents == null || !ActivityManager.supportsMultiWindow()

  8. || !getComponent(Divider.class).getView().getSnapAlgorithm()

  9. .isSplitScreenFeasible()) {

  10. return false;

  11. }

  12. //触发多窗口显示

  13. toggleSplitScreenMode(MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS,

  14. MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS);

  15. return true;

  16. }

  17. };

  18. private void prepareNavigationBarView() {

  19. ......

  20. ButtonDispatcher recentsButton = mNavigationBarView.getRecentsButton();

  21. ......

  22. recentsButton.setOnLongClickListener(mRecentsLongClickListener);

  23. ......

  24. }

这里我们看到,长按RecentsButton,代码逻辑为:

mRecents为空

不支持分屏

这里 1、upportsMultiWindow()方法判断了一个系统属性config_supportsMultiWindow为真 以及非低内存版本,则认为系统可以支持分屏 2、isSplitScreenFeasible( )方法判断当前分屏的大小,是否是满足系统要求的最小的分屏像素值。

 
  1. /frameworks/base/core/java/android/app/ActivityManager.java

  2. /**

  3. * Returns true if the system supports at least one form of multi-window.

  4. * E.g. freeform, split-screen, picture-in-picture.

  5. * @hide

  6. */

  7. static public boolean supportsMultiWindow() {

  8. return !isLowRamDeviceStatic()

  9. && Resources.getSystem().getBoolean(

  10. com.android.internal.R.bool.config_supportsMultiWindow);

  11. }

  12.  
  13. //isSplitScreenFeasible 判断当前分屏的大小,是否是满足系统要求的最小的分屏像素值。

  14. /frameworks/base/core/java/com/android/internal/policy/DividerSnapAlgorithm.java

  15.  
  16. //其中mMinimalSizeResizableTask 值为 <dimen name="default_minimal_size_resizable_task">220dp</dimen>

  17. mMinimalSizeResizableTask = res.getDimensionPixelSize(

  18. com.android.internal.R.dimen.default_minimal_size_resizable_task);

  19. /**

  20. * @return whether it's feasible to enable split screen in the current configuration, i.e. when

  21. * snapping in the middle both tasks are larger than the minimal task size.

  22. */

  23. public boolean isSplitScreenFeasible() {

  24. int statusBarSize = mInsets.top;

  25. int navBarSize = mIsHorizontalDivision ? mInsets.bottom : mInsets.right;

  26. int size = mIsHorizontalDivision

  27. ? mDisplayHeight

  28. : mDisplayWidth;

  29. int availableSpace = size - navBarSize - statusBarSize - mDividerSize;

  30. return availableSpace / 2 >= mMinimalSizeResizableTask;

  31. }

来到分屏的代码位置,这里有一个判断

/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java

 
  1. @Override

  2. protected void toggleSplitScreenMode(int metricsDockAction, int metricsUndockAction) {

  3. if (mRecents == null) {

  4. return;

  5. }

  6. int dockSide = WindowManagerProxy.getInstance().getDockSide();

  7. if (dockSide == WindowManager.DOCKED_INVALID) {

  8. mRecents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE,

  9. ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, null, metricsDockAction);

  10. } else {

  11. EventBus.getDefault().send(new UndockingTaskEvent());

  12. if (metricsUndockAction != -1) {

  13. MetricsLogger.action(mContext, metricsUndockAction);

  14. }

  15. }

  16. }

dockSide == WindowManager.DOCKED_INVALID 此状态表示当前没有处在分屏模式下,因此我们需要进入分屏

我们看下这里的WindowManagerProxy.getInstance().getDockSide()如何处理的
这里可以看到,来到了WMS(WindowManagerServer.java)位置,看下getDockedStackSide方法

 
  1. /frameworks/base/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java

  2.  
  3. public int getDockSide() {

  4. try {

  5. return WindowManagerGlobal.getWindowManagerService().getDockedStackSide();

  6. } catch (RemoteException e) {

  7. Log.w(TAG, "Failed to get dock side: " + e);

  8. }

  9. return DOCKED_INVALID;

  10. }

  11. //这里如何判断的呢?找下当前的默认显示屏幕,然后判断下DockStack是否存在,如果存在,则在多窗口模式,如果不存在,则当前不是

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

  13. @Override

  14. public int getDockedStackSide() {

  15. synchronized (mWindowMap) {

  16. final TaskStack dockedStack = getDefaultDisplayContentLocked()

  17. .getDockedStackVisibleForUserLocked();

  18. return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide();

  19. }

  20. }

我们这里在启动分屏,所以此时不在分屏模式模式,于是乎,我们来到代码:千里之行,启程。

 
  1. /frameworks/base/packages/SystemUI/src/com/android/systemui/RecentsComponent.java

  2. public interface RecentsComponent {

  3. ......

  4. /**

  5. * Docks the top-most task and opens recents.

  6. */

  7. boolean dockTopTask(int dragMode, int

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值