您的位置:首页 > 移动开发

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

2017-07-11 11:18 507 查看
一、命令如下
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐