视频播放选择悬浮窗播放,按home键回到Launcher,此时悬浮窗视频再切换成全屏播放,需要等待5秒原因分析
问题现象:
视频播放选择悬浮窗播放,按home键回到Launcher,此时悬浮窗视频再切换成全屏播放,需要等待5秒左右。
问题分析:
//按Home进入Launcher
03-05 15:43:58.047 620 840 I ActivityManager: ->startActivity for ActivityRecord{52345cc u0 com.android.launcher3/.Launcher t483} result:2
//从悬浮窗启动全屏播放intent
03-05 15:43:59.782 620 982 I ActivityManager: START u0 {act=android.intent.action.VIEW dat=content://media/external/video/media/1190 flg=0x10000001 cmp=com.android.gallery3d/com.sprd.gallery3d.app.Video (has extras)} from uid 10025, pid 1497
03-05 15:43:59.785 620 982 W ActivityManager: Activity start request from 10025 stopped
//此时AMS返回START_SWITCHES_CANCELED
03-05 15:43:59.786 620 982 I ActivityManager: ->startActivity for Intent { act=android.intent.action.VIEW dat=content://media/external/video/media/1190 flg=0x10000001 cmp=com.android.gallery3d/com.sprd.gallery3d.app.Video (has extras) }, return START_SWITCHES_CANCELED
//5秒后又一次发送全屏播放的intent
03-05 15:44:02.932 620 707 I ActivityManager: ->startActivity for ActivityRecord{136e33d u0 com.android.gallery3d/com.sprd.gallery3d.app.Video t484} result:0
AMS分析为google原生行为:
如果App想马上启动,不被pending 5s,需要在App的AndroidManifest.xml内申请如下permission:
android.permission.STOP_APP_SWITCHES
并且需要在frameworks/base/data/etc/privapp-permissions-platform.xml
申明,不然会导致CTS不过:
代码分析:
ActivityStarter.java startActivityLocked()方法中:
说到如果启动Activity和当前resumed的UID不相同就会检查app switches权限
// If we are starting an activity that is not from the same uid as the currently resumed one, check whether app switches are allowed.
if (voiceSession == null && (stack.getResumedActivity() == null
Launcher主界面从悬浮窗回到全屏播放,此时resumed uid是Launcher,但是realCallingUid却是Gallery,所以会进入checkAppSwitchAllowedLocked流程
|| stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
realCallingPid, realCallingUid, "Activity start")) {
mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
sourceRecord, startFlags, stack, callerApp));
ActivityOptions.abort(checkedOptions);
Slog.i(TAG, "->startActivity for " + intent + ", return START_SWITCHES_CANCELED");
return ActivityManager.START_SWITCHES_CANCELED;
}
}
看看checkAppSwitchAllowedLocked()是如何检查权限的:
boolean checkAppSwitchAllowedLocked(int sourcePid, int sourceUid,
int callingPid, int callingUid, String name) {
mAppSwitchesAllowedTime 表示按HOME键后,在当前系统的时间上加上5秒,这里判断也就表明按home键5s后,再切回全屏播放就不会出现迟
if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
return true;
}
if (mRecentTasks.isCallerRecents(sourceUid)) {
return true;
}
检查应用是否有android.permission.STOP_APP_SWITCHES权限
int perm = checkComponentPermission(STOP_APP_SWITCHES, sourcePid, sourceUid, -1, true);
if (perm == PackageManager.PERMISSION_GRANTED) {
return true;
}
if (checkAllowAppSwitchUid(sourceUid)) {
return true;
}
// If the actual IPC caller is different from the logical source, then
// also see if they are allowed to control app switches.
if (callingUid != -1 && callingUid != sourceUid) {
perm = checkComponentPermission(STOP_APP_SWITCHES, callingPid, callingUid, -1, true);
if (perm == PackageManager.PERMISSION_GRANTED) {
return true;
}
if (checkAllowAppSwitchUid(callingUid)) {
return true;
}
}
Slog.w(TAG, name + " request from " + sourceUid + " stopped");
return false;
}
网友评论