公司最近开始搞Android P的项目,有一天在新的代码上出现了一个奇怪的问题。在点完开机向导后,进入到launcher,发现虚拟按键中的recents不见了,点击那个区域也没反应,但是在系统配置发生改变时(比如切换言)recents又出来了。
刚开始只有一个user版的手机,开机向导过程中的log抓不到,怀疑是别人改了SystemUI造成的也没法验证,为了方便分析问题,只能先编一个userdebug版本。编译时间比较长,闲着也是闲着,就先在代码里看下有没有什么头绪吧。
在SystemUI的代码里搜索关键字“recent”,“disable”,“hide”,最终在StatusBar.java里发现了一个“DISABLE_RECENT”进而找到了framework里的StatusBarManager.java中的以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public static final int DISABLE_EXPAND = View.STATUS_BAR_DISABLE_EXPAND;public static final int DISABLE_NOTIFICATION_ICONS = View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS;public static final int DISABLE_NOTIFICATION_ALERTS = View.STATUS_BAR_DISABLE_NOTIFICATION_ALERTS; @Deprecated public static final int DISABLE_NOTIFICATION_TICKER = View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER; public static final int DISABLE_SYSTEM_INFO = View.STATUS_BAR_DISABLE_SYSTEM_INFO;public static final int DISABLE_HOME = View.STATUS_BAR_DISABLE_HOME;public static final int DISABLE_RECENT = View.STATUS_BAR_DISABLE_RECENT;public static final int DISABLE_BACK = View.STATUS_BAR_DISABLE_BACK;public static final int DISABLE_CLOCK = View.STATUS_BAR_DISABLE_CLOCK;public static final int DISABLE_SEARCH = View.STATUS_BAR_DISABLE_SEARCH;@Deprecated public static final int DISABLE_NAVIGATION = View.STATUS_BAR_DISABLE_HOME | View.STATUS_BAR_DISABLE_RECENT; public static final int DISABLE_NONE = 0x00000000 ;public static final int DISABLE_MASK = DISABLE_EXPAND | DISABLE_NOTIFICATION_ICONS | DISABLE_NOTIFICATION_ALERTS | DISABLE_NOTIFICATION_TICKER | DISABLE_SYSTEM_INFO | DISABLE_RECENT | DISABLE_HOME | DISABLE_BACK | DISABLE_CLOCK | DISABLE_SEARCH;
各种各样的disable,而这些disable都在StatusBar的disable()方法中出现了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 @Override public void disable (int state1, int state2, boolean animate) { state2 = mRemoteInputQuickSettingsDisabler.adjustDisableFlags(state2); animate &= mStatusBarWindowState != WINDOW_STATE_HIDDEN; final int old1 = mDisabled1; final int diff1 = state1 ^ old1; mDisabled1 = state1; final int old2 = mDisabled2; final int diff2 = state2 ^ old2; mDisabled2 = state2; if (DEBUG) { Log.d(TAG, String.format("disable1: 0x%08x -> 0x%08x (diff1: 0x%08x)" , old1, state1, diff1)); Log.d(TAG, String.format("disable2: 0x%08x -> 0x%08x (diff2: 0x%08x)" , old2, state2, diff2)); } StringBuilder flagdbg = new StringBuilder (); flagdbg.append("disable<" ); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_EXPAND)) ? 'E' : 'e' ); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_EXPAND)) ? '!' : ' ' ); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS)) ? 'I' : 'i' ); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ICONS)) ? '!' : ' ' ); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS)) ? 'A' : 'a' ); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS)) ? '!' : ' ' ); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_SYSTEM_INFO)) ? 'S' : 's' ); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_SYSTEM_INFO)) ? '!' : ' ' ); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_BACK)) ? 'B' : 'b' ); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_BACK)) ? '!' : ' ' ); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_HOME)) ? 'H' : 'h' ); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_HOME)) ? '!' : ' ' ); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_RECENT)) ? 'R' : 'r' ); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_RECENT)) ? '!' : ' ' ); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_CLOCK)) ? 'C' : 'c' ); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_CLOCK)) ? '!' : ' ' ); flagdbg.append(0 != ((state1 & StatusBarManager.DISABLE_SEARCH)) ? 'S' : 's' ); flagdbg.append(0 != ((diff1 & StatusBarManager.DISABLE_SEARCH)) ? '!' : ' ' ); flagdbg.append("> disable2<" ); flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_QUICK_SETTINGS)) ? 'Q' : 'q' ); flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS)) ? '!' : ' ' ); flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_SYSTEM_ICONS)) ? 'I' : 'i' ); flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_SYSTEM_ICONS)) ? '!' : ' ' ); flagdbg.append(0 != ((state2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE)) ? 'N' : 'n' ); flagdbg.append(0 != ((diff2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE)) ? '!' : ' ' ); flagdbg.append('>' ); Log.d(TAG, flagdbg.toString()); if ((diff1 & StatusBarManager.DISABLE_EXPAND) != 0 ) { if ((state1 & StatusBarManager.DISABLE_EXPAND) != 0 ) { animateCollapsePanels(); } } if ((diff1 & StatusBarManager.DISABLE_RECENT) != 0 ) { if ((state1 & StatusBarManager.DISABLE_RECENT) != 0 ) { mHandler.removeMessages(MSG_HIDE_RECENT_APPS); mHandler.sendEmptyMessage(MSG_HIDE_RECENT_APPS); } } if ((diff1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0 ) { mEntryManager.setDisableNotificationAlerts( (state1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0 ); } if ((diff2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) != 0 ) { updateQsExpansionEnabled(); } if ((diff2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0 ) { updateQsExpansionEnabled(); if ((state1 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0 ) { animateCollapsePanels(); } } }
其中mDisabled1和mDisabled2表示之前的disable状态,state1和state2表示新的状态,diff1和diff2表示发生改变的标志位。状态的改变会记录在flagdbg中从代码中来看,如果新的state中包含某个disable标志位,则log中用一个大写字母表示,否则用小写表示;如果某个标志位发生改变,则字母后面会加上一个“!”。三个虚拟按键分别对应B(b),H(b),R(r).
在刷机后抓取了开机向导过程中的log,从其中找到了以下信息:
1 2 3 09-21 14:21:36.096 1432 1432 D StatusBar: disable1: 0x00000000 -> 0x03a50000 (diff1: 0x03a50000) 09-21 14:21:36.097 1432 1432 D StatusBar: disable2: 0x00000000 -> 0x00000010 (diff2: 0x00000010) 09-21 14:21:36.097 1432 1432 D StatusBar: disable<E!i A!s b H!R!C!S!> disable2<q i n >
该条记录表示E,A,H,R,C,S等标志位发生了变化。这里只关心三个虚拟按键,b表示back按键还是可用的而且没有发生变化;H!表示home键状态从enable变为disable了;R!表示recents按键也从enable变为了disable。
上面这些内容比较好理解,仅作记录。关于最开始提到的问题,最后发现别人添加功能改出来的,这里就不关心了。