Android L使用adb命令获取FocusedApp 包名错误(原生bug)

xiaoxiao2021-02-28  41

一、命令如下

adb shell dumpsys window windows | grep -E "mCurrentFocus | mFocusedApp" | egrep "ActivityRecord.*" | cut -d " " -f7 | cut -d "/" -f1

通过adb shell dumpsys window windows命令可以得知以上命令获取的是什么内容:

  mCurConfiguration={1.0 ?mcc?mnc en_US ?layoutDir sw320dp w320dp h544dp 240dpi nrml long port finger -keyb/v/h -nav/h s.5}   mHasPermanentDpad=false   mCurrentFocus=Window{343a0a2c u0 com.tct.launcher/com.tct.launcher.Launcher}   mFocusedApp=AppWindowToken{158efe19 token=Token{1f33d960 ActivityRecord{3ad78963 u0 com.tct.launcher/.Launcher t56}}}

二、步骤

[plain] view plain copy print ? root@aclgcl-ubnt:~# 桌面执行命令  root@aclgcl-ubnt:~# adb shell dumpsys window windows | grep -E "mCurrentFocus | mFocusedApp" | egrep "ActivityRecord.*" | cut -d " " -f7 | cut -d "/" -f1  com.tct.launcher  root@aclgcl-ubnt:~#   root@aclgcl-ubnt:~# 下面点击mms后执行命令  root@aclgcl-ubnt:~# adb shell dumpsys window windows | grep -E "mCurrentFocus | mFocusedApp" | egrep "ActivityRecord.*" | cut -d " " -f7 | cut -d "/" -f1  com.android.mms  root@aclgcl-ubnt:~#   root@aclgcl-ubnt:~# 按Home键回到桌面执行命令  root@aclgcl-ubnt:~# adb shell dumpsys window windows | grep -E "mCurrentFocus | mFocusedApp" | egrep "ActivityRecord.*" | cut -d " " -f7 | cut -d "/" -f1  com.android.mms      root@aclgcl-ubnt:~# 桌面执行命令 root@aclgcl-ubnt:~# adb shell dumpsys window windows | grep -E "mCurrentFocus | mFocusedApp" | egrep "ActivityRecord.*" | cut -d " " -f7 | cut -d "/" -f1 com.tct.launcher root@aclgcl-ubnt:~# root@aclgcl-ubnt:~# 下面点击mms后执行命令 root@aclgcl-ubnt:~# adb shell dumpsys window windows | grep -E "mCurrentFocus | mFocusedApp" | egrep "ActivityRecord.*" | cut -d " " -f7 | cut -d "/" -f1 com.android.mms root@aclgcl-ubnt:~# root@aclgcl-ubnt:~# 按Home键回到桌面执行命令 root@aclgcl-ubnt:~# adb shell dumpsys window windows | grep -E "mCurrentFocus | mFocusedApp" | egrep "ActivityRecord.*" | cut -d " " -f7 | cut -d "/" -f1 com.android.mms   返回桌面后执行命令得到的结果不正确。

三、分析

从adb shell dumpsys window windows结果来看,即为mFocusedApp获取错误,mFocusedApp的设置在WMS中:

[java] view plain copy print ? @Override  public void setFocusedApp(IBinder token, boolean moveFocusNow) {      if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,              "setFocusedApp()")) {          throw new SecurityException("Requires MANAGE_APP_TOKENS permission");      }        synchronized(mWindowMap) {          final AppWindowToken newFocus;          if (token == null) {              if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp);              newFocus = null;          } else {              newFocus = findAppWindowToken(token);              if (newFocus == null) {                  Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token);              }              if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Set focused app to: " + newFocus                      + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow);          }            final boolean changed = mFocusedApp != newFocus;          if (changed) {              mFocusedApp = newFocus;              mInputMonitor.setFocusedAppLw(newFocus);          }            if (moveFocusNow && changed) {              final long origId = Binder.clearCallingIdentity();              updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);              Binder.restoreCallingIdentity(origId);          }      }  }   @Override public void setFocusedApp(IBinder token, boolean moveFocusNow) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, "setFocusedApp()")) { throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); } synchronized(mWindowMap) { final AppWindowToken newFocus; if (token == null) { if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Clearing focused app, was " + mFocusedApp); newFocus = null; } else { newFocus = findAppWindowToken(token); if (newFocus == null) { Slog.w(TAG, "Attempted to set focus to non-existing app token: " + token); } if (DEBUG_FOCUS_LIGHT) Slog.v(TAG, "Set focused app to: " + newFocus + " old focus=" + mFocusedApp + " moveFocusNow=" + moveFocusNow); } final boolean changed = mFocusedApp != newFocus; if (changed) { mFocusedApp = newFocus; mInputMonitor.setFocusedAppLw(newFocus); } if (moveFocusNow && changed) { final long origId = Binder.clearCallingIdentity(); updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/); Binder.restoreCallingIdentity(origId); } } } setFocusedApp在AMS中调用:

[java] view plain copy print ? final void setFocusedActivityLocked(ActivityRecord r, String reason) {      if (mFocusedActivity != r) {          if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedActivityLocked: r=" + r);          mFocusedActivity = r;          if (r.task != null && r.task.voiceInteractor != null) {              startRunningVoiceLocked();          } else {              finishRunningVoiceLocked();          }          mStackSupervisor.setFocusedStack(r, reason + " setFocusedActivity");          if (r != null) {              <span style="color:#FF0000;"><strong>mWindowManager.setFocusedApp(r.appToken, true);</strong></span>          }          applyUpdateLockStateLocked(r);      }      EventLog.writeEvent(EventLogTags.AM_FOCUSED_ACTIVITY, mCurrentUserId,              mFocusedActivity == null ? "NULL" : mFocusedActivity.shortComponentName);  }   final void setFocusedActivityLocked(ActivityRecord r, String reason) { if (mFocusedActivity != r) { if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedActivityLocked: r=" + r); mFocusedActivity = r; if (r.task != null && r.task.voiceInteractor != null) { startRunningVoiceLocked(); } else { finishRunningVoiceLocked(); } mStackSupervisor.setFocusedStack(r, reason + " setFocusedActivity"); if (r != null) { mWindowManager.setFocusedApp(r.appToken, true); } applyUpdateLockStateLocked(r); } EventLog.writeEvent(EventLogTags.AM_FOCUSED_ACTIVITY, mCurrentUserId, mFocusedActivity == null ? "NULL" : mFocusedActivity.shortComponentName); } 继续追踪setFocusedActivityLocked的几处调用,分别打log跟踪,发现当从mms按home键回到桌面的时候setFocusedActivityLocked方法没有被调用到,,,随后翻阅ActivityStack.java中的adjustFocusedActivityLocked方法所调用setFocusedActivityLocked的逻辑,

[java] view plain copy print ? private void adjustFocusedActivityLocked(ActivityRecord r, String reason) {      <span style="color:#FF0000;"><strong>if (mStackSupervisor.isFrontStack(this) && mService.mFocusedActivity == r) {</strong></span>          ActivityRecord next = topRunningActivityLocked(null);          if (next != r) {              final TaskRecord task = r.task;              if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) {                  mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(),                          reason + " adjustFocus");              }          }          ActivityRecord top = mStackSupervisor.topRunningActivityLocked();          if (top != null) {              <span style="color:#FF0000;"><strong>mService.setFocusedActivityLocked(top, reason + " adjustTopFocus");</strong></span>          }      }  }   private void adjustFocusedActivityLocked(ActivityRecord r, String reason) { if (mStackSupervisor.isFrontStack(this) && mService.mFocusedActivity == r) { ActivityRecord next = topRunningActivityLocked(null); if (next != r) { final TaskRecord task = r.task; if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) { mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo(), reason + " adjustFocus"); } } ActivityRecord top = mStackSupervisor.topRunningActivityLocked(); if (top != null) { mService.setFocusedActivityLocked(top, reason + " adjustTopFocus"); } } } [java] view plain copy print ? final void stopActivityLocked(ActivityRecord r) {      if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);      if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0              || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {          if (!r.finishing) {              if (!mService.isSleeping()) {                  if (DEBUG_STATES) {                      Slog.d(TAG, "no-history finish of " + r);                  }                  requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,                          "no-history"false);              } else {                  if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r                          + " on stop because we're just sleeping");              }          }      }        if (r.app != null && r.app.thread != null) {          <span style="color:#FF0000;"><strong>adjustFocusedActivityLocked(r, "stopActivity");</strong></span>          r.resumeKeyDispatchingLocked();   final void stopActivityLocked(ActivityRecord r) { if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r); if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) { if (!r.finishing) { if (!mService.isSleeping()) { if (DEBUG_STATES) { Slog.d(TAG, "no-history finish of " + r); } requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, "no-history", false); } else { if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r + " on stop because we're just sleeping"); } } } if (r.app != null && r.app.thread != null) { adjustFocusedActivityLocked(r, "stopActivity"); r.resumeKeyDispatchingLocked(); 在从mms回到launcher的时候,mms的activity被stop,所以应当是从adjustFocusedActivityLocked调用的setFocusedActivityLocked,所以是上面加红加粗的条件没有走进去,继续跟踪,查看isFrontStack()方法,

[java] view plain copy print ? boolean isFrontStack(ActivityStack stack) {      final ActivityRecord parent = stack.mActivityContainer.mParentActivity;      if (parent != null) {          stack = parent.task.stack;      }      ArrayList<ActivityStack> stacks = stack.mStacks;      if (stacks != null && !stacks.isEmpty()) {          return stack == stacks.get(stacks.size() - 1);      }      return false;  }   boolean isFrontStack(ActivityStack stack) { final ActivityRecord parent = stack.mActivityContainer.mParentActivity; if (parent != null) { stack = parent.task.stack; } ArrayList<ActivityStack> stacks = stack.mStacks; if (stacks != null && !stacks.isEmpty()) { return stack == stacks.get(stacks.size() - 1); } return false; }

通过log发现mStackSupervisor.isFrontStack(this)总是不成立,this是切换之前的stack,即MMS所在的stack,继续查看Android M中的代码,发现moveTaskToFrontLocked方法中也调用了mService.setFocusedActivityLocked(r, reason);,

[java] view plain copy print ?     final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, Bundle options,              AppTimeTracker timeTracker, String reason) {          System.out.println("ran.zhou-AS-L3721-moveTaskToFrontLocked");          if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);            final int numTasks = mTaskHistory.size();          final int index = mTaskHistory.indexOf(tr);  。。。  。。。          // Shift all activities with this task up to the top          // of the stack, keeping them in the same internal order.          insertTaskAtTop(tr, null);            // Set focus to the top running activity of this stack.          ActivityRecord r = topRunningActivityLocked(null);          <span style="color:#FF0000;"><strong>mService.setFocusedActivityLocked(r, reason);</strong></span>            if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);          if (noAnimation) {              mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);              if (r != null) {                  mNoAnimActivities.add(r);              }              ActivityOptions.abort(options);          } else {              updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);          }   final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, Bundle options, AppTimeTracker timeTracker, String reason) { System.out.println("ran.zhou-AS-L3721-moveTaskToFrontLocked"); if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr); final int numTasks = mTaskHistory.size(); final int index = mTaskHistory.indexOf(tr); 。。。 。。。 // Shift all activities with this task up to the top // of the stack, keeping them in the same internal order. insertTaskAtTop(tr, null); // Set focus to the top running activity of this stack. ActivityRecord r = topRunningActivityLocked(null); mService.setFocusedActivityLocked(r, reason); if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr); if (noAnimation) { mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false); if (r != null) { mNoAnimActivities.add(r); } ActivityOptions.abort(options); } else { updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options); } 此处调用setFocusedActivityLocked方法走的不是stopActivity那条路了,而是ActivityStackSupervisor.java中的startActivityUncheckedLocked方法中,

[java] view plain copy print ?     final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord,              IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,              boolean doResume, Bundle options, TaskRecord inTask) {          final Intent intent = r.intent;          final int callingUid = r.launchedFromUid;  。。。。。。。  。。。。。。。                              targetStack.<span style="color:#FF0000;"><strong>moveTaskToFrontLocked</strong></span>(intentActivity.task, noAnimation,                                      options, r.appTimeTracker, "bringingFoundTaskToFront");   final int startActivityUncheckedLocked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, boolean doResume, Bundle options, TaskRecord inTask) { final Intent intent = r.intent; final int callingUid = r.launchedFromUid; 。。。。。。。 。。。。。。。 targetStack.moveTaskToFrontLocked(intentActivity.task, noAnimation, options, r.appTimeTracker, "bringingFoundTaskToFront"); 所以M中的处理是在moveTaskToFrontLocked加一个调用setFocusedActivityLocked。

android M中对stopActivity的逻辑也是和Android L中一样,那个if条件走不进去,个人认为这里依然是Google的代码缺陷。

四、解决方案

仿照M中的处理,在moveTaskToFrontLocked加一个调用setFocusedActivityLocked。

[java] view plain copy print ? //Added by xxx for PR-1150738 Begin  // Set focus to the top running activity of this stack.  ActivityRecord r = topRunningActivityLocked(null);  mService.setFocusedActivityLocked(r, reason);  //Added by xxx for PR-1150738 End   //Added by xxx for PR-1150738 Begin // Set focus to the top running activity of this stack. ActivityRecord r = topRunningActivityLocked(null); mService.setFocusedActivityLocked(r, reason); //Added by xxx for PR-1150738 End

转载请注明原文地址: https://www.6miu.com/read-57125.html

最新回复(0)