android7.0多窗口横屏模式下statusbar有条纹

Step1 概述

在最近的学习过程中,遇到了一个android7.0原生的缺陷。是关于android7.0新增的分屏功能,久久难以攻克,还是在主管的帮助下,遂记录之,希望以后能少走弯路,高效学习。

Step2 描述

bug详情

General Description: 
The notification bar will display stripe when tap the back key on multi-window screen. 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Reproducibility: 
7/10 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Precondition: 
Auto-rotate is on. 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Step: 
1.Main Menu->Phone->Rotate to landscape mode->Long press RECENT key->Press BACK key->Check the phone displays. 
2.Main Menu->Calculator->Rotate to landscape mode->Long press RECENT key->Press BACK key->Check the phone displays. 
3.Main Menu->Clock->Rotate to landscape mode->Long press RECENT key->Press BACK key->Check the phone displays. 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Actual result: 
The notification bar will display stripe when tap the back key on multi-window screen. 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Expect result: 
The notification bar shouldn't display stripe when tap the back key on multi-window screen. 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Related Test Case: 
N/A 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -   
SW version: 
36.1.A.0.37 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
HW version: 
AP2 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

运行效果

Step3 查源头

我们打开SystemUI的源代码
SystemUI
这里应该是一个文件夹对应一个模块,比如最近任务,锁屏,电池,截图,状态栏等等。然而我们要关注的是stackdivider,android中会把Activity放到栈中来管理,实际上分屏的话相当于会有一个新的stack,我们看看ActivityManager.java(base/core/java/android/app)文件有个内部类,记录管理着所有的stack

 public static class StackId {
        /** Invalid stack ID. */
        public static final int INVALID_STACK_ID = -1;

        /** First static stack ID. */
        public static final int FIRST_STATIC_STACK_ID = 0;

        /** Home activity stack ID. */
        public static final int HOME_STACK_ID = FIRST_STATIC_STACK_ID;

        /** ID of stack where fullscreen activities are normally launched into. */
        public static final int FULLSCREEN_WORKSPACE_STACK_ID = 1;

        /** ID of stack where freeform/resized activities are normally launched into. */
        public static final int FREEFORM_WORKSPACE_STACK_ID = FULLSCREEN_WORKSPACE_STACK_ID + 1;

        /** ID of stack that occupies a dedicated region of the screen. */
        public static final int DOCKED_STACK_ID = FREEFORM_WORKSPACE_STACK_ID + 1;

        /** ID of stack that always on top (always visible) when it exist. */
        public static final int PINNED_STACK_ID = DOCKED_STACK_ID + 1;

        /** Last static stack stack ID. */
        public static final int LAST_STATIC_STACK_ID = PINNED_STACK_ID;
        。。。。。
        }

知道了这些,我们看看为什么标题栏上会有黑色的条纹,并且是两条,难道是横屏分屏的时候statusbar绘制的时候还有其他的view也被显示了。实际上我们在测试的过程中可以发现
这里写图片描述
在当前应用屏幕和最近任务屏幕之间有个黑色条纹,可能是这个条纹没有被隐藏掉影响了statusbar的状态。那么我们看看这边的代码

/**
 * Controls the docked stack divider.
 */
public class Divider extends SystemUI {
......
 @Override
    protected void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        update(newConfig);
    }
......
private void update(Configuration configuration) {
        removeDivider();
        addDivider(configuration);
        if (mMinimized) {
            mView.setMinimizedDockStack(true);
            updateTouchable();
        }
    }
......
......
}

当config change 后会调用update方法,最终看看DividerView的绘制 mView.setMinimizedDockStack(true);

/**
 * Docked stack divider.
 */
public class DividerView extends FrameLayout implements OnTouchListener,
        OnComputeInternalInsetsListener {
        ......
          public void setMinimizedDockStack(boolean minimized) {
        updateDockSide();
        mHandle.setAlpha(minimized ? 0f : 1f);
        if (!minimized) {
            resetBackground();
        } else if (mDockSide == WindowManager.DOCKED_TOP) {
            mBackground.setPivotY(0);
            mBackground.setScaleY(MINIMIZE_DOCK_SCALE);
        } else if (mDockSide == WindowManager.DOCKED_LEFT
                || mDockSide == WindowManager.DOCKED_RIGHT) {
            mBackground.setPivotX(mDockSide == WindowManager.DOCKED_LEFT
                    ? 0
                    : mBackground.getWidth());
            mBackground.setScaleX(MINIMIZE_DOCK_SCALE);
        }
        mMinimizedShadow.setAlpha(minimized ? 1f : 0f);
        mDockedStackMinimized = minimized;
    }
        ......
         private void updateDockSide() {
        mDockSide = mWindowManagerProxy.getDockSide();
        mMinimizedShadow.setDockSide(mDockSide);
    }
        }

分析上面的code,在最小化分屏界面时会首先执行updateDockSide()方法

public interface WindowManager extends ViewManager {
    ......
    /** @hide */
    int DOCKED_INVALID = -1;
    /** @hide */
    int DOCKED_LEFT = 1;
    /** @hide */
    int DOCKED_TOP = 2;
    /** @hide */
    int DOCKED_RIGHT = 3;
    /** @hide */
    int DOCKED_BOTTOM = 4;
    ......
 }

WindowManageProxy下(SystemUI)

 public int getDockSide() {
        try {
            return WindowManagerGlobal.getWindowManagerService().getDockedStackSide();
        } catch (RemoteException e) {
            Log.w(TAG, "Failed to get dock side: " + e);
        }
        return DOCKED_INVALID;
    }

Z:\frameworks\base\services\core\java\com\android\server\wm\WindowManagerService.java下

 public int getDockedStackSide() {
        synchronized (mWindowMap) {
            final TaskStack dockedStack = getDefaultDisplayContentLocked()
                    .getDockedStackVisibleForUserLocked();
            return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide();
        }
    }

最终是TaskStack getDockSide
回到setMinimizedDockStack方法,会判断dockside,有些情况dockside的值不满足,而这是确实要求隐藏
mMinimizedShadow被異常畫出,
mBackground沒有被隱藏:
(mMinimizedShadow: 阴影view,
mBackground:分割線View )。所以在updatedockside里当是无效的,给他赋值

if(mDockSide == WindowManager.DOCKED_INVALID){
            mDockSide = WindowManager.DOCKED_TOP;
            android.util.Log.d("DividerView", "updateDockSide() mDockSide is DOCKED_INVALID change to DOCKED_TOP!");
        }

Step4总结

搞清楚

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值