Merge changes I4fdfbe80,Ie2bb56c5,I6ee0e839 into tm-qpr-dev
* changes: Merge "Log BAL and full screen intent to statsd." into tm-qpr-dev Merge "Update BAL Check to return Allow Reason" into tm-qpr-dev Merge "Add ownership for BackgroundActivityStartController" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
f0216079d0
@@ -98,6 +98,8 @@ public class ActivityStartController {
|
||||
/** Whether an {@link ActivityStarter} is currently executing (starting an Activity). */
|
||||
private boolean mInExecution = false;
|
||||
|
||||
private final BackgroundActivityStartController mBalController;
|
||||
|
||||
/**
|
||||
* TODO(b/64750076): Capture information necessary for dump and
|
||||
* {@link #postStartActivityProcessingForLastStarter} rather than keeping the entire object
|
||||
@@ -120,6 +122,7 @@ public class ActivityStartController {
|
||||
mFactory.setController(this);
|
||||
mPendingRemoteAnimationRegistry = new PendingRemoteAnimationRegistry(service.mGlobalLock,
|
||||
service.mH);
|
||||
mBalController = new BackgroundActivityStartController(mService, mSupervisor);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -670,4 +673,8 @@ public class ActivityStartController {
|
||||
pw.println("(nothing)");
|
||||
}
|
||||
}
|
||||
|
||||
BackgroundActivityStartController getBackgroundActivityLaunchController() {
|
||||
return mBalController;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
|
||||
import static android.app.Activity.RESULT_CANCELED;
|
||||
import static android.app.ActivityManager.START_ABORTED;
|
||||
import static android.app.ActivityManager.START_CANCELED;
|
||||
@@ -52,7 +51,6 @@ import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE_PER_TASK;
|
||||
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
|
||||
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
|
||||
import static android.content.pm.ActivityInfo.launchModeToString;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static android.os.Process.INVALID_UID;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.view.WindowManager.TRANSIT_NONE;
|
||||
@@ -63,7 +61,6 @@ import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP
|
||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
|
||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
|
||||
import static com.android.server.wm.ActivityRecord.State.RESUMED;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ACTIVITY_STARTS;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING;
|
||||
@@ -74,11 +71,11 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_USER_
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
|
||||
import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
|
||||
import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_ALLOW;
|
||||
import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_FG_ONLY;
|
||||
import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME;
|
||||
import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
|
||||
import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
|
||||
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_DEFAULT;
|
||||
import static com.android.server.wm.BackgroundActivityStartController.BAL_BLOCK;
|
||||
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS;
|
||||
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_DISPLAY;
|
||||
import static com.android.server.wm.Task.REPARENT_MOVE_ROOT_TASK_TO_FRONT;
|
||||
@@ -99,7 +96,6 @@ import android.app.WaitResult;
|
||||
import android.app.WindowConfiguration;
|
||||
import android.compat.annotation.ChangeId;
|
||||
import android.compat.annotation.EnabledSince;
|
||||
import android.content.ComponentName;
|
||||
import android.content.IIntentSender;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
@@ -115,15 +111,12 @@ import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.Trace;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.service.voice.IVoiceInteractionSession;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArraySet;
|
||||
import android.util.DebugUtils;
|
||||
import android.util.Pools.SynchronizedPool;
|
||||
import android.util.Slog;
|
||||
import android.window.RemoteTransition;
|
||||
@@ -139,6 +132,7 @@ import com.android.server.power.ShutdownCheckPoints;
|
||||
import com.android.server.statusbar.StatusBarManagerInternal;
|
||||
import com.android.server.uri.NeededUriGrants;
|
||||
import com.android.server.wm.ActivityMetricsLogger.LaunchingState;
|
||||
import com.android.server.wm.BackgroundActivityStartController.BalCode;
|
||||
import com.android.server.wm.LaunchParamsController.LaunchParams;
|
||||
import com.android.server.wm.TaskFragment.EmbeddingCheckResult;
|
||||
|
||||
@@ -180,9 +174,10 @@ class ActivityStarter {
|
||||
private int mCallingUid;
|
||||
private ActivityOptions mOptions;
|
||||
|
||||
// If it is true, background activity can only be started in an existing task that contains
|
||||
// If it is BAL_BLOCK, background activity can only be started in an existing task that contains
|
||||
// an activity with same uid, or if activity starts are enabled in developer options.
|
||||
private boolean mRestrictedBgActivity;
|
||||
@BalCode
|
||||
private int mBalCode;
|
||||
|
||||
private int mLaunchMode;
|
||||
private boolean mLaunchTaskBehind;
|
||||
@@ -264,8 +259,6 @@ class ActivityStarter {
|
||||
|
||||
/**
|
||||
* Generates an {@link ActivityStarter} that is ready to handle a new start request.
|
||||
* @param controller The {@link ActivityStartController} which the starter who will own
|
||||
* this instance.
|
||||
* @return an {@link ActivityStarter}
|
||||
*/
|
||||
ActivityStarter obtain();
|
||||
@@ -600,7 +593,7 @@ class ActivityStarter {
|
||||
mIntent = starter.mIntent;
|
||||
mCallingUid = starter.mCallingUid;
|
||||
mOptions = starter.mOptions;
|
||||
mRestrictedBgActivity = starter.mRestrictedBgActivity;
|
||||
mBalCode = starter.mBalCode;
|
||||
|
||||
mLaunchTaskBehind = starter.mLaunchTaskBehind;
|
||||
mLaunchFlags = starter.mLaunchFlags;
|
||||
@@ -1031,15 +1024,25 @@ class ActivityStarter {
|
||||
ActivityOptions checkedOptions = options != null
|
||||
? options.getOptions(intent, aInfo, callerApp, mSupervisor) : null;
|
||||
|
||||
boolean restrictedBgActivity = false;
|
||||
@BalCode int balCode = BAL_ALLOW_DEFAULT;
|
||||
if (!abort) {
|
||||
try {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER,
|
||||
"shouldAbortBackgroundActivityStart");
|
||||
restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,
|
||||
callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
|
||||
request.originatingPendingIntent, request.allowBackgroundActivityStart,
|
||||
intent, checkedOptions);
|
||||
BackgroundActivityStartController balController =
|
||||
mController.getBackgroundActivityLaunchController();
|
||||
balCode =
|
||||
balController.checkBackgroundActivityStart(
|
||||
callingUid,
|
||||
callingPid,
|
||||
callingPackage,
|
||||
realCallingUid,
|
||||
realCallingPid,
|
||||
callerApp,
|
||||
request.originatingPendingIntent,
|
||||
request.allowBackgroundActivityStart,
|
||||
intent,
|
||||
checkedOptions);
|
||||
} finally {
|
||||
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
|
||||
}
|
||||
@@ -1217,13 +1220,13 @@ class ActivityStarter {
|
||||
WindowProcessController homeProcess = mService.mHomeProcess;
|
||||
boolean isHomeProcess = homeProcess != null
|
||||
&& aInfo.applicationInfo.uid == homeProcess.mUid;
|
||||
if (!restrictedBgActivity && !isHomeProcess) {
|
||||
if (balCode != BAL_BLOCK && !isHomeProcess) {
|
||||
mService.resumeAppSwitches();
|
||||
}
|
||||
|
||||
mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
|
||||
request.voiceInteractor, startFlags, true /* doResume */, checkedOptions,
|
||||
inTask, inTaskFragment, restrictedBgActivity, intentGrants);
|
||||
inTask, inTaskFragment, balCode, intentGrants);
|
||||
|
||||
if (request.outActivity != null) {
|
||||
request.outActivity[0] = mLastStartActivityRecord;
|
||||
@@ -1273,282 +1276,6 @@ class ActivityStarter {
|
||||
mController.onExecutionStarted();
|
||||
}
|
||||
|
||||
private boolean isHomeApp(int uid, @Nullable String packageName) {
|
||||
if (mService.mHomeProcess != null) {
|
||||
// Fast check
|
||||
return uid == mService.mHomeProcess.mUid;
|
||||
}
|
||||
if (packageName == null) {
|
||||
return false;
|
||||
}
|
||||
ComponentName activity =
|
||||
mService.getPackageManagerInternalLocked().getDefaultHomeActivity(
|
||||
UserHandle.getUserId(uid));
|
||||
return activity != null && packageName.equals(activity.getPackageName());
|
||||
}
|
||||
|
||||
boolean shouldAbortBackgroundActivityStart(int callingUid, int callingPid,
|
||||
final String callingPackage, int realCallingUid, int realCallingPid,
|
||||
WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent,
|
||||
boolean allowBackgroundActivityStart, Intent intent, ActivityOptions checkedOptions) {
|
||||
// don't abort for the most important UIDs
|
||||
final int callingAppId = UserHandle.getAppId(callingUid);
|
||||
final boolean useCallingUidState =
|
||||
originatingPendingIntent == null || checkedOptions == null
|
||||
|| !checkedOptions.getIgnorePendingIntentCreatorForegroundState();
|
||||
if (useCallingUidState) {
|
||||
if (callingUid == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID
|
||||
|| callingAppId == Process.NFC_UID) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG,
|
||||
"Activity start allowed for important callingUid (" + callingUid + ")");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Always allow home application to start activities.
|
||||
if (isHomeApp(callingUid, callingPackage)) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG,
|
||||
"Activity start allowed for home app callingUid (" + callingUid + ")");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// IME should always be allowed to start activity, like IME settings.
|
||||
final WindowState imeWindow = mRootWindowContainer.getCurrentInputMethodWindow();
|
||||
if (imeWindow != null && callingAppId == imeWindow.mOwnerUid) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG, "Activity start allowed for active ime (" + callingUid + ")");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// This is used to block background activity launch even if the app is still
|
||||
// visible to user after user clicking home button.
|
||||
final int appSwitchState = mService.getBalAppSwitchesState();
|
||||
|
||||
// don't abort if the callingUid has a visible window or is a persistent system process
|
||||
final int callingUidProcState = mService.mActiveUids.getUidState(callingUid);
|
||||
final boolean callingUidHasAnyVisibleWindow = mService.hasActiveVisibleWindow(callingUid);
|
||||
final boolean isCallingUidForeground = callingUidHasAnyVisibleWindow
|
||||
|| callingUidProcState == ActivityManager.PROCESS_STATE_TOP
|
||||
|| callingUidProcState == ActivityManager.PROCESS_STATE_BOUND_TOP;
|
||||
final boolean isCallingUidPersistentSystemProcess =
|
||||
callingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
|
||||
|
||||
// Normal apps with visible app window will be allowed to start activity if app switching
|
||||
// is allowed, or apps like live wallpaper with non app visible window will be allowed.
|
||||
final boolean appSwitchAllowedOrFg =
|
||||
appSwitchState == APP_SWITCH_ALLOW || appSwitchState == APP_SWITCH_FG_ONLY;
|
||||
final boolean allowCallingUidStartActivity =
|
||||
((appSwitchAllowedOrFg || mService.mActiveUids.hasNonAppVisibleWindow(callingUid))
|
||||
&& callingUidHasAnyVisibleWindow)
|
||||
|| isCallingUidPersistentSystemProcess;
|
||||
if (useCallingUidState && allowCallingUidStartActivity) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG, "Activity start allowed: callingUidHasAnyVisibleWindow = " + callingUid
|
||||
+ ", isCallingUidPersistentSystemProcess = "
|
||||
+ isCallingUidPersistentSystemProcess);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// take realCallingUid into consideration
|
||||
final int realCallingUidProcState = (callingUid == realCallingUid)
|
||||
? callingUidProcState
|
||||
: mService.mActiveUids.getUidState(realCallingUid);
|
||||
final boolean realCallingUidHasAnyVisibleWindow = (callingUid == realCallingUid)
|
||||
? callingUidHasAnyVisibleWindow
|
||||
: mService.hasActiveVisibleWindow(realCallingUid);
|
||||
final boolean isRealCallingUidForeground = (callingUid == realCallingUid)
|
||||
? isCallingUidForeground
|
||||
: realCallingUidHasAnyVisibleWindow
|
||||
|| realCallingUidProcState == ActivityManager.PROCESS_STATE_TOP;
|
||||
final int realCallingAppId = UserHandle.getAppId(realCallingUid);
|
||||
final boolean isRealCallingUidPersistentSystemProcess = (callingUid == realCallingUid)
|
||||
? isCallingUidPersistentSystemProcess
|
||||
: (realCallingAppId == Process.SYSTEM_UID)
|
||||
|| realCallingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
|
||||
|
||||
// In the case of an SDK sandbox calling uid, check if the corresponding app uid has a
|
||||
// visible window.
|
||||
if (Process.isSdkSandboxUid(realCallingUid)) {
|
||||
int realCallingSdkSandboxUidToAppUid = Process.getAppUidForSdkSandboxUid(
|
||||
UserHandle.getAppId(realCallingUid));
|
||||
|
||||
if (mService.hasActiveVisibleWindow(realCallingSdkSandboxUidToAppUid)) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG, "Activity start allowed: uid in SDK sandbox ("
|
||||
+ realCallingUid + ") has visible (non-toast) window.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy behavior allows to use caller foreground state to bypass BAL restriction.
|
||||
final boolean balAllowedByPiSender =
|
||||
PendingIntentRecord.isPendingIntentBalAllowedByCaller(checkedOptions);
|
||||
|
||||
if (balAllowedByPiSender && realCallingUid != callingUid) {
|
||||
final boolean useCallerPermission =
|
||||
PendingIntentRecord.isPendingIntentBalAllowedByPermission(checkedOptions);
|
||||
if (useCallerPermission && ActivityManager.checkComponentPermission(
|
||||
android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
|
||||
realCallingUid, -1, true)
|
||||
== PackageManager.PERMISSION_GRANTED) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG, "Activity start allowed: realCallingUid (" + realCallingUid
|
||||
+ ") has BAL permission.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// don't abort if the realCallingUid has a visible window
|
||||
// TODO(b/171459802): We should check appSwitchAllowed also
|
||||
if (realCallingUidHasAnyVisibleWindow) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG, "Activity start allowed: realCallingUid (" + realCallingUid
|
||||
+ ") has visible (non-toast) window");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// if the realCallingUid is a persistent system process, abort if the IntentSender
|
||||
// wasn't allowed to start an activity
|
||||
if (isRealCallingUidPersistentSystemProcess && allowBackgroundActivityStart) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG, "Activity start allowed: realCallingUid (" + realCallingUid
|
||||
+ ") is persistent system process AND intent sender allowed "
|
||||
+ "(allowBackgroundActivityStart = true)");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// don't abort if the realCallingUid is an associated companion app
|
||||
if (mService.isAssociatedCompanionApp(UserHandle.getUserId(realCallingUid),
|
||||
realCallingUid)) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG, "Activity start allowed: realCallingUid (" + realCallingUid
|
||||
+ ") is companion app");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (useCallingUidState) {
|
||||
// don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
|
||||
if (mService.checkPermission(
|
||||
START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
|
||||
== PERMISSION_GRANTED) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG,
|
||||
"Background activity start allowed: START_ACTIVITIES_FROM_BACKGROUND "
|
||||
+ "permission granted for uid "
|
||||
+ callingUid);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// don't abort if the caller has the same uid as the recents component
|
||||
if (mSupervisor.mRecentTasks.isCallerRecents(callingUid)) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG, "Background activity start allowed: callingUid (" + callingUid
|
||||
+ ") is recents");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// don't abort if the callingUid is the device owner
|
||||
if (mService.isDeviceOwner(callingUid)) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG, "Background activity start allowed: callingUid (" + callingUid
|
||||
+ ") is device owner");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// don't abort if the callingUid has companion device
|
||||
final int callingUserId = UserHandle.getUserId(callingUid);
|
||||
if (mService.isAssociatedCompanionApp(callingUserId,
|
||||
callingUid)) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG, "Background activity start allowed: callingUid (" + callingUid
|
||||
+ ") is companion app");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission
|
||||
if (mService.hasSystemAlertWindowPermission(callingUid,
|
||||
callingPid, callingPackage)) {
|
||||
Slog.w(TAG, "Background activity start for " + callingPackage
|
||||
+ " allowed because SYSTEM_ALERT_WINDOW permission is granted.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// If we don't have callerApp at this point, no caller was provided to startActivity().
|
||||
// That's the case for PendingIntent-based starts, since the creator's process might not be
|
||||
// up and alive. If that's the case, we retrieve the WindowProcessController for the send()
|
||||
// caller if caller allows, so that we can make the decision based on its state.
|
||||
int callerAppUid = callingUid;
|
||||
if (callerApp == null && balAllowedByPiSender) {
|
||||
callerApp = mService.getProcessController(realCallingPid, realCallingUid);
|
||||
callerAppUid = realCallingUid;
|
||||
}
|
||||
// don't abort if the callerApp or other processes of that uid are allowed in any way
|
||||
if (callerApp != null && useCallingUidState) {
|
||||
// first check the original calling process
|
||||
if (callerApp.areBackgroundActivityStartsAllowed(appSwitchState)) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG, "Background activity start allowed: callerApp process (pid = "
|
||||
+ callerApp.getPid() + ", uid = " + callerAppUid + ") is allowed");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// only if that one wasn't allowed, check the other ones
|
||||
final ArraySet<WindowProcessController> uidProcesses =
|
||||
mService.mProcessMap.getProcesses(callerAppUid);
|
||||
if (uidProcesses != null) {
|
||||
for (int i = uidProcesses.size() - 1; i >= 0; i--) {
|
||||
final WindowProcessController proc = uidProcesses.valueAt(i);
|
||||
if (proc != callerApp
|
||||
&& proc.areBackgroundActivityStartsAllowed(appSwitchState)) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG,
|
||||
"Background activity start allowed: process " + proc.getPid()
|
||||
+ " from uid " + callerAppUid + " is allowed");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// anything that has fallen through would currently be aborted
|
||||
Slog.w(TAG, "Background activity start [callingPackage: " + callingPackage
|
||||
+ "; callingUid: " + callingUid
|
||||
+ "; appSwitchState: " + appSwitchState
|
||||
+ "; isCallingUidForeground: " + isCallingUidForeground
|
||||
+ "; callingUidHasAnyVisibleWindow: " + callingUidHasAnyVisibleWindow
|
||||
+ "; callingUidProcState: " + DebugUtils.valueToString(ActivityManager.class,
|
||||
"PROCESS_STATE_", callingUidProcState)
|
||||
+ "; isCallingUidPersistentSystemProcess: " + isCallingUidPersistentSystemProcess
|
||||
+ "; realCallingUid: " + realCallingUid
|
||||
+ "; isRealCallingUidForeground: " + isRealCallingUidForeground
|
||||
+ "; realCallingUidHasAnyVisibleWindow: " + realCallingUidHasAnyVisibleWindow
|
||||
+ "; realCallingUidProcState: " + DebugUtils.valueToString(ActivityManager.class,
|
||||
"PROCESS_STATE_", realCallingUidProcState)
|
||||
+ "; isRealCallingUidPersistentSystemProcess: "
|
||||
+ isRealCallingUidPersistentSystemProcess
|
||||
+ "; originatingPendingIntent: " + originatingPendingIntent
|
||||
+ "; allowBackgroundActivityStart: " + allowBackgroundActivityStart
|
||||
+ "; intent: " + intent
|
||||
+ "; callerApp: " + callerApp
|
||||
+ "; inVisibleTask: " + (callerApp != null && callerApp.hasActivityInVisibleTask())
|
||||
+ "]");
|
||||
// log aborted activity start to TRON
|
||||
if (mService.isActivityStartsLoggingEnabled()) {
|
||||
mSupervisor.getActivityMetricsLogger().logAbortedBgActivityStart(intent, callerApp,
|
||||
callingUid, callingPackage, callingUidProcState, callingUidHasAnyVisibleWindow,
|
||||
realCallingUid, realCallingUidProcState, realCallingUidHasAnyVisibleWindow,
|
||||
(originatingPendingIntent != null));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a launch intent for the given auxiliary resolution data.
|
||||
*/
|
||||
@@ -1649,7 +1376,7 @@ class ActivityStarter {
|
||||
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
|
||||
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
|
||||
int startFlags, boolean doResume, ActivityOptions options, Task inTask,
|
||||
TaskFragment inTaskFragment, boolean restrictedBgActivity,
|
||||
TaskFragment inTaskFragment, @BalCode int balCode,
|
||||
NeededUriGrants intentGrants) {
|
||||
int result = START_CANCELED;
|
||||
final Task startedActivityRootTask;
|
||||
@@ -1669,7 +1396,7 @@ class ActivityStarter {
|
||||
try {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
|
||||
result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
|
||||
startFlags, doResume, options, inTask, inTaskFragment, restrictedBgActivity,
|
||||
startFlags, doResume, options, inTask, inTaskFragment, balCode,
|
||||
intentGrants);
|
||||
} finally {
|
||||
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
|
||||
@@ -1816,10 +1543,10 @@ class ActivityStarter {
|
||||
int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,
|
||||
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
|
||||
int startFlags, boolean doResume, ActivityOptions options, Task inTask,
|
||||
TaskFragment inTaskFragment, boolean restrictedBgActivity,
|
||||
TaskFragment inTaskFragment, @BalCode int balCode,
|
||||
NeededUriGrants intentGrants) {
|
||||
setInitialState(r, options, inTask, inTaskFragment, doResume, startFlags, sourceRecord,
|
||||
voiceSession, voiceInteractor, restrictedBgActivity);
|
||||
voiceSession, voiceInteractor, balCode);
|
||||
|
||||
computeLaunchingTaskFlags();
|
||||
mIntent.setFlags(mLaunchFlags);
|
||||
@@ -2055,7 +1782,8 @@ class ActivityStarter {
|
||||
|| !targetTask.isUidPresent(mCallingUid)
|
||||
|| (LAUNCH_SINGLE_INSTANCE == mLaunchMode && targetTask.inPinnedWindowingMode()));
|
||||
|
||||
if (mRestrictedBgActivity && blockBalInTask && handleBackgroundActivityAbort(r)) {
|
||||
if (mBalCode == BAL_BLOCK && blockBalInTask
|
||||
&& handleBackgroundActivityAbort(r)) {
|
||||
Slog.e(TAG, "Abort background activity starts from " + mCallingUid);
|
||||
return START_ABORTED;
|
||||
}
|
||||
@@ -2452,7 +2180,7 @@ class ActivityStarter {
|
||||
mIntent = null;
|
||||
mCallingUid = -1;
|
||||
mOptions = null;
|
||||
mRestrictedBgActivity = false;
|
||||
mBalCode = BAL_ALLOW_DEFAULT;
|
||||
|
||||
mLaunchTaskBehind = false;
|
||||
mLaunchFlags = 0;
|
||||
@@ -2497,7 +2225,7 @@ class ActivityStarter {
|
||||
private void setInitialState(ActivityRecord r, ActivityOptions options, Task inTask,
|
||||
TaskFragment inTaskFragment, boolean doResume, int startFlags,
|
||||
ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession,
|
||||
IVoiceInteractor voiceInteractor, boolean restrictedBgActivity) {
|
||||
IVoiceInteractor voiceInteractor, @BalCode int balCode) {
|
||||
reset(false /* clearRequest */);
|
||||
|
||||
mStartActivity = r;
|
||||
@@ -2508,7 +2236,7 @@ class ActivityStarter {
|
||||
mSourceRootTask = mSourceRecord != null ? mSourceRecord.getRootTask() : null;
|
||||
mVoiceSession = voiceSession;
|
||||
mVoiceInteractor = voiceInteractor;
|
||||
mRestrictedBgActivity = restrictedBgActivity;
|
||||
mBalCode = balCode;
|
||||
|
||||
mLaunchParams.reset();
|
||||
|
||||
@@ -2645,7 +2373,7 @@ class ActivityStarter {
|
||||
|
||||
mNoAnimation = (mLaunchFlags & FLAG_ACTIVITY_NO_ANIMATION) != 0;
|
||||
|
||||
if (mRestrictedBgActivity && !mService.isBackgroundActivityStartsEnabled()) {
|
||||
if (mBalCode == BAL_BLOCK && !mService.isBackgroundActivityStartsEnabled()) {
|
||||
mAvoidMoveToFront = true;
|
||||
mDoResume = false;
|
||||
}
|
||||
|
||||
@@ -2182,10 +2182,19 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
|
||||
if (appThread != null) {
|
||||
callerApp = getProcessController(appThread);
|
||||
}
|
||||
final ActivityStarter starter = getActivityStartController().obtainStarter(
|
||||
null /* intent */, "moveTaskToFront");
|
||||
if (starter.shouldAbortBackgroundActivityStart(callingUid, callingPid, callingPackage, -1,
|
||||
-1, callerApp, null, false, null, null)) {
|
||||
final BackgroundActivityStartController balController =
|
||||
getActivityStartController().getBackgroundActivityLaunchController();
|
||||
if (balController.shouldAbortBackgroundActivityStart(
|
||||
callingUid,
|
||||
callingPid,
|
||||
callingPackage,
|
||||
-1,
|
||||
-1,
|
||||
callerApp,
|
||||
null,
|
||||
false,
|
||||
null,
|
||||
null)) {
|
||||
if (!isBackgroundActivityStartsEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -119,10 +119,20 @@ class AppTaskImpl extends IAppTask.Stub {
|
||||
if (appThread != null) {
|
||||
callerApp = mService.getProcessController(appThread);
|
||||
}
|
||||
final ActivityStarter starter = mService.getActivityStartController().obtainStarter(
|
||||
null /* intent */, "moveToFront");
|
||||
if (starter.shouldAbortBackgroundActivityStart(callingUid, callingPid,
|
||||
callingPackage, -1, -1, callerApp, null, false, null, null)) {
|
||||
final BackgroundActivityStartController balController =
|
||||
mService.getActivityStartController()
|
||||
.getBackgroundActivityLaunchController();
|
||||
if (balController.shouldAbortBackgroundActivityStart(
|
||||
callingUid,
|
||||
callingPid,
|
||||
callingPackage,
|
||||
-1,
|
||||
-1,
|
||||
callerApp,
|
||||
null,
|
||||
false,
|
||||
null,
|
||||
null)) {
|
||||
if (!mService.isBackgroundActivityStartsEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,483 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ACTIVITY_STARTS;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
|
||||
import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_ALLOW;
|
||||
import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_FG_ONLY;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.util.ArraySet;
|
||||
import android.util.DebugUtils;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
import com.android.server.am.PendingIntentRecord;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
/**
|
||||
* Helper class to check permissions for starting Activities.
|
||||
*
|
||||
* <p>This class collects all the logic to prevent malicious attempts to start activities.
|
||||
*/
|
||||
public class BackgroundActivityStartController {
|
||||
|
||||
private static final String TAG =
|
||||
TAG_WITH_CLASS_NAME ? "BackgroundActivityStartController" : TAG_ATM;
|
||||
|
||||
private final ActivityTaskManagerService mService;
|
||||
private final ActivityTaskSupervisor mSupervisor;
|
||||
|
||||
// TODO(b/263368846) Rename when ASM logic is moved in
|
||||
@Retention(SOURCE)
|
||||
@IntDef({BAL_BLOCK,
|
||||
BAL_ALLOW_DEFAULT,
|
||||
BAL_ALLOW_ALLOWLISTED_UID,
|
||||
BAL_ALLOW_ALLOWLISTED_COMPONENT,
|
||||
BAL_ALLOW_VISIBLE_WINDOW,
|
||||
BAL_ALLOW_PENDING_INTENT,
|
||||
BAL_ALLOW_BAL_PERMISSION,
|
||||
BAL_ALLOW_SAW_PERMISSION,
|
||||
BAL_ALLOW_GRACE_PERIOD,
|
||||
BAL_ALLOW_FOREGROUND,
|
||||
BAL_ALLOW_SDK_SANDBOX
|
||||
})
|
||||
public @interface BalCode {}
|
||||
|
||||
static final int BAL_BLOCK = 0;
|
||||
|
||||
static final int BAL_ALLOW_DEFAULT = 1;
|
||||
|
||||
// Following codes are in order of precedence
|
||||
|
||||
/** Important UIDs which should be always allowed to launch activities */
|
||||
static final int BAL_ALLOW_ALLOWLISTED_UID = 2;
|
||||
|
||||
/** Apps that fulfill a certain role that can can always launch new tasks */
|
||||
static final int BAL_ALLOW_ALLOWLISTED_COMPONENT = 3;
|
||||
|
||||
/** Apps which currently have a visible window */
|
||||
static final int BAL_ALLOW_VISIBLE_WINDOW = 4;
|
||||
|
||||
/** Allowed due to the PendingIntent sender */
|
||||
static final int BAL_ALLOW_PENDING_INTENT = 5;
|
||||
|
||||
/** App has START_ACTIVITIES_FROM_BACKGROUND permission or BAL instrumentation privileges
|
||||
* granted to it */
|
||||
static final int BAL_ALLOW_BAL_PERMISSION = 6;
|
||||
|
||||
/** Process has SYSTEM_ALERT_WINDOW permission granted to it */
|
||||
static final int BAL_ALLOW_SAW_PERMISSION = 7;
|
||||
|
||||
/** App is in grace period after an activity was started or finished */
|
||||
static final int BAL_ALLOW_GRACE_PERIOD = 8;
|
||||
|
||||
/** App is in a foreground task or bound to a foreground service (but not itself visible) */
|
||||
static final int BAL_ALLOW_FOREGROUND = 9;
|
||||
|
||||
/** Process belongs to a SDK sandbox */
|
||||
static final int BAL_ALLOW_SDK_SANDBOX = 10;
|
||||
|
||||
BackgroundActivityStartController(
|
||||
final ActivityTaskManagerService service, final ActivityTaskSupervisor supervisor) {
|
||||
mService = service;
|
||||
mSupervisor = supervisor;
|
||||
}
|
||||
|
||||
private boolean isHomeApp(int uid, @Nullable String packageName) {
|
||||
if (mService.mHomeProcess != null) {
|
||||
// Fast check
|
||||
return uid == mService.mHomeProcess.mUid;
|
||||
}
|
||||
if (packageName == null) {
|
||||
return false;
|
||||
}
|
||||
ComponentName activity =
|
||||
mService.getPackageManagerInternalLocked()
|
||||
.getDefaultHomeActivity(UserHandle.getUserId(uid));
|
||||
return activity != null && packageName.equals(activity.getPackageName());
|
||||
}
|
||||
|
||||
boolean shouldAbortBackgroundActivityStart(
|
||||
int callingUid,
|
||||
int callingPid,
|
||||
final String callingPackage,
|
||||
int realCallingUid,
|
||||
int realCallingPid,
|
||||
WindowProcessController callerApp,
|
||||
PendingIntentRecord originatingPendingIntent,
|
||||
boolean allowBackgroundActivityStart,
|
||||
Intent intent,
|
||||
ActivityOptions checkedOptions) {
|
||||
return checkBackgroundActivityStart(callingUid, callingPid, callingPackage,
|
||||
realCallingUid, realCallingPid, callerApp, originatingPendingIntent,
|
||||
allowBackgroundActivityStart, intent, checkedOptions) == BAL_BLOCK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A code denoting which BAL rule allows an activity to be started,
|
||||
* or {@link BAL_BLOCK} if the launch should be blocked
|
||||
*/
|
||||
@BalCode
|
||||
int checkBackgroundActivityStart(
|
||||
int callingUid,
|
||||
int callingPid,
|
||||
final String callingPackage,
|
||||
int realCallingUid,
|
||||
int realCallingPid,
|
||||
WindowProcessController callerApp,
|
||||
PendingIntentRecord originatingPendingIntent,
|
||||
boolean allowBackgroundActivityStart,
|
||||
Intent intent,
|
||||
ActivityOptions checkedOptions) {
|
||||
// don't abort for the most important UIDs
|
||||
final int callingAppId = UserHandle.getAppId(callingUid);
|
||||
final boolean useCallingUidState =
|
||||
originatingPendingIntent == null
|
||||
|| checkedOptions == null
|
||||
|| !checkedOptions.getIgnorePendingIntentCreatorForegroundState();
|
||||
if (useCallingUidState) {
|
||||
if (callingUid == Process.ROOT_UID
|
||||
|| callingAppId == Process.SYSTEM_UID
|
||||
|| callingAppId == Process.NFC_UID) {
|
||||
return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_UID, /*background*/ false,
|
||||
callingUid, realCallingUid, intent, "Important callingUid");
|
||||
}
|
||||
|
||||
// Always allow home application to start activities.
|
||||
if (isHomeApp(callingUid, callingPackage)) {
|
||||
return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
|
||||
/*background*/ false, callingUid, realCallingUid, intent,
|
||||
"Home app");
|
||||
}
|
||||
|
||||
// IME should always be allowed to start activity, like IME settings.
|
||||
final WindowState imeWindow =
|
||||
mService.mRootWindowContainer.getCurrentInputMethodWindow();
|
||||
if (imeWindow != null && callingAppId == imeWindow.mOwnerUid) {
|
||||
return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
|
||||
/*background*/ false, callingUid, realCallingUid, intent,
|
||||
"Active ime");
|
||||
}
|
||||
}
|
||||
|
||||
// This is used to block background activity launch even if the app is still
|
||||
// visible to user after user clicking home button.
|
||||
final int appSwitchState = mService.getBalAppSwitchesState();
|
||||
|
||||
// don't abort if the callingUid has a visible window or is a persistent system process
|
||||
final int callingUidProcState = mService.mActiveUids.getUidState(callingUid);
|
||||
final boolean callingUidHasAnyVisibleWindow = mService.hasActiveVisibleWindow(callingUid);
|
||||
final boolean isCallingUidForeground =
|
||||
callingUidHasAnyVisibleWindow
|
||||
|| callingUidProcState == ActivityManager.PROCESS_STATE_TOP
|
||||
|| callingUidProcState == ActivityManager.PROCESS_STATE_BOUND_TOP;
|
||||
final boolean isCallingUidPersistentSystemProcess =
|
||||
callingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
|
||||
|
||||
// Normal apps with visible app window will be allowed to start activity if app switching
|
||||
// is allowed, or apps like live wallpaper with non app visible window will be allowed.
|
||||
final boolean appSwitchAllowedOrFg =
|
||||
appSwitchState == APP_SWITCH_ALLOW || appSwitchState == APP_SWITCH_FG_ONLY;
|
||||
final boolean allowCallingUidStartActivity =
|
||||
((appSwitchAllowedOrFg || mService.mActiveUids.hasNonAppVisibleWindow(callingUid))
|
||||
&& callingUidHasAnyVisibleWindow)
|
||||
|| isCallingUidPersistentSystemProcess;
|
||||
if (useCallingUidState && allowCallingUidStartActivity) {
|
||||
return logStartAllowedAndReturnCode(BAL_ALLOW_VISIBLE_WINDOW,
|
||||
/*background*/ false, callingUid, realCallingUid, intent,
|
||||
"callingUidHasAnyVisibleWindow = "
|
||||
+ callingUid
|
||||
+ ", isCallingUidPersistentSystemProcess = "
|
||||
+ isCallingUidPersistentSystemProcess);
|
||||
}
|
||||
// take realCallingUid into consideration
|
||||
final int realCallingUidProcState =
|
||||
(callingUid == realCallingUid)
|
||||
? callingUidProcState
|
||||
: mService.mActiveUids.getUidState(realCallingUid);
|
||||
final boolean realCallingUidHasAnyVisibleWindow =
|
||||
(callingUid == realCallingUid)
|
||||
? callingUidHasAnyVisibleWindow
|
||||
: mService.hasActiveVisibleWindow(realCallingUid);
|
||||
final boolean isRealCallingUidForeground =
|
||||
(callingUid == realCallingUid)
|
||||
? isCallingUidForeground
|
||||
: realCallingUidHasAnyVisibleWindow
|
||||
|| realCallingUidProcState == ActivityManager.PROCESS_STATE_TOP;
|
||||
final int realCallingAppId = UserHandle.getAppId(realCallingUid);
|
||||
final boolean isRealCallingUidPersistentSystemProcess =
|
||||
(callingUid == realCallingUid)
|
||||
? isCallingUidPersistentSystemProcess
|
||||
: (realCallingAppId == Process.SYSTEM_UID)
|
||||
|| realCallingUidProcState
|
||||
<= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
|
||||
|
||||
// In the case of an SDK sandbox calling uid, check if the corresponding app uid has a
|
||||
// visible window.
|
||||
if (Process.isSdkSandboxUid(realCallingUid)) {
|
||||
int realCallingSdkSandboxUidToAppUid =
|
||||
Process.getAppUidForSdkSandboxUid(UserHandle.getAppId(realCallingUid));
|
||||
|
||||
if (mService.hasActiveVisibleWindow(realCallingSdkSandboxUidToAppUid)) {
|
||||
return logStartAllowedAndReturnCode(BAL_ALLOW_SDK_SANDBOX,
|
||||
/*background*/ false, callingUid, realCallingUid, intent,
|
||||
"uid in SDK sandbox has visible (non-toast) window");
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy behavior allows to use caller foreground state to bypass BAL restriction.
|
||||
final boolean balAllowedByPiSender =
|
||||
PendingIntentRecord.isPendingIntentBalAllowedByCaller(checkedOptions);
|
||||
|
||||
if (balAllowedByPiSender && realCallingUid != callingUid) {
|
||||
final boolean useCallerPermission =
|
||||
PendingIntentRecord.isPendingIntentBalAllowedByPermission(checkedOptions);
|
||||
if (useCallerPermission
|
||||
&& ActivityManager.checkComponentPermission(
|
||||
android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND,
|
||||
realCallingUid,
|
||||
-1,
|
||||
true)
|
||||
== PackageManager.PERMISSION_GRANTED) {
|
||||
return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
|
||||
/*background*/ false, callingUid, realCallingUid, intent,
|
||||
"realCallingUid has BAL permission. realCallingUid: " + realCallingUid);
|
||||
}
|
||||
|
||||
// don't abort if the realCallingUid has a visible window
|
||||
// TODO(b/171459802): We should check appSwitchAllowed also
|
||||
if (realCallingUidHasAnyVisibleWindow) {
|
||||
return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
|
||||
/*background*/ false, callingUid, realCallingUid, intent,
|
||||
"realCallingUid has visible (non-toast) window. realCallingUid: "
|
||||
+ realCallingUid);
|
||||
}
|
||||
// if the realCallingUid is a persistent system process, abort if the IntentSender
|
||||
// wasn't allowed to start an activity
|
||||
if (isRealCallingUidPersistentSystemProcess && allowBackgroundActivityStart) {
|
||||
return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
|
||||
/*background*/ false, callingUid, realCallingUid, intent,
|
||||
"realCallingUid is persistent system process AND intent "
|
||||
+ "sender allowed (allowBackgroundActivityStart = true). "
|
||||
+ "realCallingUid: " + realCallingUid);
|
||||
}
|
||||
// don't abort if the realCallingUid is an associated companion app
|
||||
if (mService.isAssociatedCompanionApp(
|
||||
UserHandle.getUserId(realCallingUid), realCallingUid)) {
|
||||
return logStartAllowedAndReturnCode(BAL_ALLOW_PENDING_INTENT,
|
||||
/*background*/ false, callingUid, realCallingUid, intent,
|
||||
"realCallingUid is a companion app. "
|
||||
+ "realCallingUid: " + realCallingUid);
|
||||
}
|
||||
}
|
||||
if (useCallingUidState) {
|
||||
// don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
|
||||
if (ActivityTaskManagerService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND,
|
||||
callingPid, callingUid) == PERMISSION_GRANTED) {
|
||||
return logStartAllowedAndReturnCode(BAL_ALLOW_BAL_PERMISSION,
|
||||
/*background*/ true, callingUid, realCallingUid, intent,
|
||||
"START_ACTIVITIES_FROM_BACKGROUND permission granted");
|
||||
}
|
||||
// don't abort if the caller has the same uid as the recents component
|
||||
if (mSupervisor.mRecentTasks.isCallerRecents(callingUid)) {
|
||||
return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
|
||||
/*background*/ true, callingUid, realCallingUid,
|
||||
intent, "Recents Component");
|
||||
}
|
||||
// don't abort if the callingUid is the device owner
|
||||
if (mService.isDeviceOwner(callingUid)) {
|
||||
return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
|
||||
/*background*/ true, callingUid, realCallingUid,
|
||||
intent, "Device Owner");
|
||||
}
|
||||
// don't abort if the callingUid has companion device
|
||||
final int callingUserId = UserHandle.getUserId(callingUid);
|
||||
if (mService.isAssociatedCompanionApp(callingUserId, callingUid)) {
|
||||
return logStartAllowedAndReturnCode(BAL_ALLOW_ALLOWLISTED_COMPONENT,
|
||||
/*background*/ true, callingUid, realCallingUid,
|
||||
intent, "Companion App");
|
||||
}
|
||||
// don't abort if the callingUid has SYSTEM_ALERT_WINDOW permission
|
||||
if (mService.hasSystemAlertWindowPermission(callingUid, callingPid, callingPackage)) {
|
||||
Slog.w(
|
||||
TAG,
|
||||
"Background activity start for "
|
||||
+ callingPackage
|
||||
+ " allowed because SYSTEM_ALERT_WINDOW permission is granted.");
|
||||
return logStartAllowedAndReturnCode(BAL_ALLOW_SAW_PERMISSION,
|
||||
/*background*/ true, callingUid, realCallingUid,
|
||||
intent, "SYSTEM_ALERT_WINDOW permission is granted");
|
||||
}
|
||||
}
|
||||
// If we don't have callerApp at this point, no caller was provided to startActivity().
|
||||
// That's the case for PendingIntent-based starts, since the creator's process might not be
|
||||
// up and alive. If that's the case, we retrieve the WindowProcessController for the send()
|
||||
// caller if caller allows, so that we can make the decision based on its state.
|
||||
int callerAppUid = callingUid;
|
||||
if (callerApp == null && balAllowedByPiSender) {
|
||||
callerApp = mService.getProcessController(realCallingPid, realCallingUid);
|
||||
callerAppUid = realCallingUid;
|
||||
}
|
||||
// don't abort if the callerApp or other processes of that uid are allowed in any way
|
||||
if (callerApp != null && useCallingUidState) {
|
||||
// first check the original calling process
|
||||
@BalCode int balAllowedForCaller = callerApp
|
||||
.areBackgroundActivityStartsAllowed(appSwitchState);
|
||||
if (balAllowedForCaller != BAL_BLOCK) {
|
||||
return logStartAllowedAndReturnCode(balAllowedForCaller,
|
||||
/*background*/ true, callingUid, realCallingUid, intent,
|
||||
"callerApp process (pid = " + callerApp.getPid()
|
||||
+ ", uid = " + callerAppUid + ") is allowed");
|
||||
}
|
||||
// only if that one wasn't allowed, check the other ones
|
||||
final ArraySet<WindowProcessController> uidProcesses =
|
||||
mService.mProcessMap.getProcesses(callerAppUid);
|
||||
if (uidProcesses != null) {
|
||||
for (int i = uidProcesses.size() - 1; i >= 0; i--) {
|
||||
final WindowProcessController proc = uidProcesses.valueAt(i);
|
||||
int balAllowedForUid = proc.areBackgroundActivityStartsAllowed(appSwitchState);
|
||||
if (proc != callerApp
|
||||
&& balAllowedForUid != BAL_BLOCK) {
|
||||
return logStartAllowedAndReturnCode(balAllowedForUid,
|
||||
/*background*/ true, callingUid, realCallingUid, intent,
|
||||
"process" + proc.getPid()
|
||||
+ " from uid " + callerAppUid + " is allowed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// anything that has fallen through would currently be aborted
|
||||
Slog.w(
|
||||
TAG,
|
||||
"Background activity start [callingPackage: "
|
||||
+ callingPackage
|
||||
+ "; callingUid: "
|
||||
+ callingUid
|
||||
+ "; appSwitchState: "
|
||||
+ appSwitchState
|
||||
+ "; isCallingUidForeground: "
|
||||
+ isCallingUidForeground
|
||||
+ "; callingUidHasAnyVisibleWindow: "
|
||||
+ callingUidHasAnyVisibleWindow
|
||||
+ "; callingUidProcState: "
|
||||
+ DebugUtils.valueToString(
|
||||
ActivityManager.class, "PROCESS_STATE_", callingUidProcState)
|
||||
+ "; isCallingUidPersistentSystemProcess: "
|
||||
+ isCallingUidPersistentSystemProcess
|
||||
+ "; realCallingUid: "
|
||||
+ realCallingUid
|
||||
+ "; isRealCallingUidForeground: "
|
||||
+ isRealCallingUidForeground
|
||||
+ "; realCallingUidHasAnyVisibleWindow: "
|
||||
+ realCallingUidHasAnyVisibleWindow
|
||||
+ "; realCallingUidProcState: "
|
||||
+ DebugUtils.valueToString(
|
||||
ActivityManager.class, "PROCESS_STATE_", realCallingUidProcState)
|
||||
+ "; isRealCallingUidPersistentSystemProcess: "
|
||||
+ isRealCallingUidPersistentSystemProcess
|
||||
+ "; originatingPendingIntent: "
|
||||
+ originatingPendingIntent
|
||||
+ "; allowBackgroundActivityStart: "
|
||||
+ allowBackgroundActivityStart
|
||||
+ "; intent: "
|
||||
+ intent
|
||||
+ "; callerApp: "
|
||||
+ callerApp
|
||||
+ "; inVisibleTask: "
|
||||
+ (callerApp != null && callerApp.hasActivityInVisibleTask())
|
||||
+ "]");
|
||||
// log aborted activity start to TRON
|
||||
if (mService.isActivityStartsLoggingEnabled()) {
|
||||
mSupervisor
|
||||
.getActivityMetricsLogger()
|
||||
.logAbortedBgActivityStart(
|
||||
intent,
|
||||
callerApp,
|
||||
callingUid,
|
||||
callingPackage,
|
||||
callingUidProcState,
|
||||
callingUidHasAnyVisibleWindow,
|
||||
realCallingUid,
|
||||
realCallingUidProcState,
|
||||
realCallingUidHasAnyVisibleWindow,
|
||||
(originatingPendingIntent != null));
|
||||
}
|
||||
return BAL_BLOCK;
|
||||
}
|
||||
|
||||
static @BalCode int logStartAllowedAndReturnCode(@BalCode int code, boolean background,
|
||||
int callingUid, int realCallingUid, Intent intent, int pid, String msg) {
|
||||
return logStartAllowedAndReturnCode(code, background, callingUid, realCallingUid, intent,
|
||||
DEBUG_ACTIVITY_STARTS ? ("[Process(" + pid + ")]" + msg) : "");
|
||||
}
|
||||
|
||||
static @BalCode int logStartAllowedAndReturnCode(@BalCode int code, boolean background,
|
||||
int callingUid, int realCallingUid, Intent intent, String msg) {
|
||||
statsLogBalAllowed(code, callingUid, realCallingUid, intent);
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (background) {
|
||||
builder.append("Background ");
|
||||
}
|
||||
builder.append("Activity start allowed: " + msg + ". callingUid: " + callingUid + ". ");
|
||||
builder.append("BAL Code: ");
|
||||
builder.append(code);
|
||||
Slog.d(TAG, builder.toString());
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
private static void statsLogBalAllowed(
|
||||
@BalCode int code, int callingUid, int realCallingUid, Intent intent) {
|
||||
if (code == BAL_ALLOW_PENDING_INTENT
|
||||
&& (callingUid == Process.SYSTEM_UID || realCallingUid == Process.SYSTEM_UID)) {
|
||||
String activityName =
|
||||
intent != null ? intent.getComponent().flattenToShortString() : "";
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
|
||||
activityName,
|
||||
code,
|
||||
callingUid,
|
||||
realCallingUid);
|
||||
}
|
||||
if (code == BAL_ALLOW_BAL_PERMISSION || code == BAL_ALLOW_FOREGROUND
|
||||
|| code == BAL_ALLOW_SAW_PERMISSION) {
|
||||
// We don't need to know which activity in this case.
|
||||
FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
|
||||
/*activityName*/ "",
|
||||
code,
|
||||
callingUid,
|
||||
realCallingUid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,10 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLAS
|
||||
import static com.android.server.wm.ActivityTaskManagerService.ACTIVITY_BG_START_GRACE_PERIOD_MS;
|
||||
import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_ALLOW;
|
||||
import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_FG_ONLY;
|
||||
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_BAL_PERMISSION;
|
||||
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_FOREGROUND;
|
||||
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_GRACE_PERIOD;
|
||||
import static com.android.server.wm.BackgroundActivityStartController.BAL_BLOCK;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -71,7 +75,8 @@ class BackgroundLaunchProcessController {
|
||||
mBackgroundActivityStartCallback = callback;
|
||||
}
|
||||
|
||||
boolean areBackgroundActivityStartsAllowed(int pid, int uid, String packageName,
|
||||
@BackgroundActivityStartController.BalCode
|
||||
int areBackgroundActivityStartsAllowed(int pid, int uid, String packageName,
|
||||
int appSwitchState, boolean isCheckingForFgsStart,
|
||||
boolean hasActivityInVisibleTask, boolean hasBackgroundActivityStartPrivileges,
|
||||
long lastStopAppSwitchesTime, long lastActivityLaunchTime,
|
||||
@@ -88,12 +93,10 @@ class BackgroundLaunchProcessController {
|
||||
// let app to be able to start background activity even it's in grace period.
|
||||
if (lastActivityLaunchTime > lastStopAppSwitchesTime
|
||||
|| lastActivityFinishTime > lastStopAppSwitchesTime) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG, "[Process(" + pid
|
||||
+ ")] Activity start allowed: within "
|
||||
+ ACTIVITY_BG_START_GRACE_PERIOD_MS + "ms grace period");
|
||||
}
|
||||
return true;
|
||||
return BackgroundActivityStartController.logStartAllowedAndReturnCode(
|
||||
BAL_ALLOW_GRACE_PERIOD, /*background*/ true, uid, uid, /*intent*/ null,
|
||||
pid, "Activity start allowed: within "
|
||||
+ ACTIVITY_BG_START_GRACE_PERIOD_MS + "ms grace period");
|
||||
}
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG, "[Process(" + pid + ")] Activity start within "
|
||||
@@ -105,39 +108,31 @@ class BackgroundLaunchProcessController {
|
||||
}
|
||||
// Allow if the proc is instrumenting with background activity starts privs.
|
||||
if (hasBackgroundActivityStartPrivileges) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG, "[Process(" + pid
|
||||
+ ")] Activity start allowed: process instrumenting with background "
|
||||
return BackgroundActivityStartController.logStartAllowedAndReturnCode(
|
||||
BAL_ALLOW_BAL_PERMISSION, /*background*/ true, uid, uid, /*intent*/ null,
|
||||
pid, "Activity start allowed: process instrumenting with background "
|
||||
+ "activity starts privileges");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Allow if the caller has an activity in any foreground task.
|
||||
if (hasActivityInVisibleTask
|
||||
&& (appSwitchState == APP_SWITCH_ALLOW || appSwitchState == APP_SWITCH_FG_ONLY)) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG, "[Process(" + pid
|
||||
+ ")] Activity start allowed: process has activity in foreground task");
|
||||
}
|
||||
return true;
|
||||
return BackgroundActivityStartController.logStartAllowedAndReturnCode(
|
||||
BAL_ALLOW_FOREGROUND, /*background*/ false, uid, uid, /*intent*/ null,
|
||||
pid, "Activity start allowed: process has activity in foreground task");
|
||||
}
|
||||
// Allow if the caller is bound by a UID that's currently foreground.
|
||||
if (isBoundByForegroundUid()) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG, "[Process(" + pid
|
||||
+ ")] Activity start allowed: process bound by foreground uid");
|
||||
}
|
||||
return true;
|
||||
return BackgroundActivityStartController.logStartAllowedAndReturnCode(
|
||||
BAL_ALLOW_FOREGROUND, /*background*/ false, uid, uid, /*intent*/ null,
|
||||
pid, "Activity start allowed: process bound by foreground uid");
|
||||
}
|
||||
// Allow if the flag was explicitly set.
|
||||
if (isBackgroundStartAllowedByToken(uid, packageName, isCheckingForFgsStart)) {
|
||||
if (DEBUG_ACTIVITY_STARTS) {
|
||||
Slog.d(TAG, "[Process(" + pid
|
||||
+ ")] Activity start allowed: process allowed by token");
|
||||
}
|
||||
return true;
|
||||
return BackgroundActivityStartController.logStartAllowedAndReturnCode(
|
||||
BAL_ALLOW_BAL_PERMISSION, /*background*/ true, uid, uid, /*intent*/ null,
|
||||
pid, "Activity start allowed: process allowed by token");
|
||||
}
|
||||
return false;
|
||||
return BAL_BLOCK;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,3 +14,6 @@ winsonc@google.com
|
||||
tigerhuang@google.com
|
||||
lihongyu@google.com
|
||||
mariiasand@google.com
|
||||
|
||||
per-file BackgroundActivityStartController.java = set noparent
|
||||
per-file BackgroundActivityStartController.java = brufino@google.com, ogunwale@google.com, louischang@google.com, lus@google.com, rickywai@google.com
|
||||
|
||||
@@ -40,6 +40,7 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
|
||||
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
|
||||
import static com.android.server.wm.ActivityTaskManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MILLIS;
|
||||
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
|
||||
import static com.android.server.wm.BackgroundActivityStartController.BAL_BLOCK;
|
||||
import static com.android.server.wm.WindowManagerService.MY_PID;
|
||||
|
||||
import android.Manifest;
|
||||
@@ -544,15 +545,17 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
|
||||
@HotPath(caller = HotPath.START_SERVICE)
|
||||
public boolean areBackgroundFgsStartsAllowed() {
|
||||
return areBackgroundActivityStartsAllowed(mAtm.getBalAppSwitchesState(),
|
||||
true /* isCheckingForFgsStart */);
|
||||
true /* isCheckingForFgsStart */) != BAL_BLOCK;
|
||||
}
|
||||
|
||||
boolean areBackgroundActivityStartsAllowed(int appSwitchState) {
|
||||
@BackgroundActivityStartController.BalCode
|
||||
int areBackgroundActivityStartsAllowed(int appSwitchState) {
|
||||
return areBackgroundActivityStartsAllowed(appSwitchState,
|
||||
false /* isCheckingForFgsStart */);
|
||||
}
|
||||
|
||||
private boolean areBackgroundActivityStartsAllowed(int appSwitchState,
|
||||
@BackgroundActivityStartController.BalCode
|
||||
private int areBackgroundActivityStartsAllowed(int appSwitchState,
|
||||
boolean isCheckingForFgsStart) {
|
||||
return mBgLaunchController.areBackgroundActivityStartsAllowed(mPid, mUid, mInfo.packageName,
|
||||
appSwitchState, isCheckingForFgsStart, hasActivityInVisibleTask(),
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
package com.android.server.wm;
|
||||
|
||||
import static android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND;
|
||||
import static android.app.Activity.RESULT_CANCELED;
|
||||
import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
|
||||
import static android.app.ActivityManager.PROCESS_STATE_TOP;
|
||||
import static android.app.ActivityManager.START_ABORTED;
|
||||
import static android.app.ActivityManager.START_CANCELED;
|
||||
@@ -42,6 +44,7 @@ import static android.content.pm.ActivityInfo.FLAG_ALLOW_UNTRUSTED_ACTIVITY_EMBE
|
||||
import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
|
||||
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
|
||||
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
|
||||
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
||||
import static android.os.Process.SYSTEM_UID;
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.clearInvocations;
|
||||
@@ -49,6 +52,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||
@@ -73,6 +77,7 @@ import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyObject;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.notNull;
|
||||
@@ -103,6 +108,8 @@ import android.window.TaskFragmentOrganizerToken;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
import com.android.server.am.PendingIntentRecord;
|
||||
import com.android.server.pm.parsing.pkg.AndroidPackage;
|
||||
import com.android.server.wm.LaunchParamsController.LaunchParamsModifier;
|
||||
import com.android.server.wm.utils.MockTracker;
|
||||
@@ -110,6 +117,8 @@ import com.android.server.wm.utils.MockTracker;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.MockitoSession;
|
||||
import org.mockito.quality.Strictness;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
@@ -150,6 +159,9 @@ public class ActivityStarterTests extends WindowTestsBase {
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mController = mock(ActivityStartController.class);
|
||||
BackgroundActivityStartController balController =
|
||||
new BackgroundActivityStartController(mAtm, mSupervisor);
|
||||
doReturn(balController).when(mController).getBackgroundActivityLaunchController();
|
||||
mActivityMetricsLogger = mock(ActivityMetricsLogger.class);
|
||||
clearInvocations(mActivityMetricsLogger);
|
||||
}
|
||||
@@ -211,10 +223,13 @@ public class ActivityStarterTests extends WindowTestsBase {
|
||||
int expectedResult) {
|
||||
final ActivityTaskManagerService service = mAtm;
|
||||
final IPackageManager packageManager = mock(IPackageManager.class);
|
||||
final ActivityStartController controller = mock(ActivityStartController.class);
|
||||
|
||||
final ActivityStarter starter = new ActivityStarter(controller, service,
|
||||
service.mTaskSupervisor, mock(ActivityStartInterceptor.class));
|
||||
final ActivityStarter starter =
|
||||
new ActivityStarter(
|
||||
mController,
|
||||
service,
|
||||
service.mTaskSupervisor,
|
||||
mock(ActivityStartInterceptor.class));
|
||||
prepareStarter(launchFlags);
|
||||
final IApplicationThread caller = mock(IApplicationThread.class);
|
||||
final WindowProcessListener listener = mock(WindowProcessListener.class);
|
||||
@@ -723,6 +738,63 @@ public class ActivityStarterTests extends WindowTestsBase {
|
||||
isCallingUidDeviceOwner, false /* isPinnedSingleInstance */);
|
||||
}
|
||||
|
||||
/**
|
||||
* This test ensures proper logging for BAL_ALLOW_PERMISSION.
|
||||
*/
|
||||
@Test
|
||||
public void testBackgroundActivityStartsAllowed_logging() {
|
||||
doReturn(false).when(mAtm).isBackgroundActivityStartsEnabled();
|
||||
MockitoSession mockingSession = mockitoSession()
|
||||
.mockStatic(ActivityTaskManagerService.class)
|
||||
.mockStatic(FrameworkStatsLog.class)
|
||||
.strictness(Strictness.LENIENT)
|
||||
.startMocking();
|
||||
doReturn(PERMISSION_GRANTED).when(() -> ActivityTaskManagerService.checkPermission(
|
||||
eq(START_ACTIVITIES_FROM_BACKGROUND),
|
||||
anyInt(), anyInt()));
|
||||
runAndVerifyBackgroundActivityStartsSubtest(
|
||||
"allowed_notAborted", false,
|
||||
UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP,
|
||||
UNIMPORTANT_UID2, false, PROCESS_STATE_BOUND_TOP,
|
||||
false, true, false, false, false);
|
||||
verify(() -> FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
|
||||
"", // activity name
|
||||
BackgroundActivityStartController.BAL_ALLOW_BAL_PERMISSION,
|
||||
UNIMPORTANT_UID,
|
||||
UNIMPORTANT_UID2));
|
||||
mockingSession.finishMocking();
|
||||
}
|
||||
|
||||
/**
|
||||
* This test ensures proper logging for BAL_ALLOW_PENDING_INTENT.
|
||||
*/
|
||||
@Test
|
||||
public void testBackgroundActivityStartsAllowed_loggingPendingIntentAllowed() {
|
||||
doReturn(false).when(mAtm).isBackgroundActivityStartsEnabled();
|
||||
MockitoSession mockingSession = mockitoSession()
|
||||
.mockStatic(ActivityTaskManagerService.class)
|
||||
.mockStatic(FrameworkStatsLog.class)
|
||||
.mockStatic(PendingIntentRecord.class)
|
||||
.strictness(Strictness.LENIENT)
|
||||
.startMocking();
|
||||
doReturn(PERMISSION_GRANTED).when(() -> ActivityTaskManagerService.checkPermission(
|
||||
eq(START_ACTIVITIES_FROM_BACKGROUND),
|
||||
anyInt(), anyInt()));
|
||||
doReturn(true).when(
|
||||
() -> PendingIntentRecord.isPendingIntentBalAllowedByCaller(anyObject()));
|
||||
runAndVerifyBackgroundActivityStartsSubtest(
|
||||
"allowed_notAborted", false,
|
||||
UNIMPORTANT_UID, false, PROCESS_STATE_BOUND_TOP,
|
||||
Process.SYSTEM_UID, true, PROCESS_STATE_BOUND_TOP,
|
||||
false, true, false, false, false);
|
||||
verify(() -> FrameworkStatsLog.write(FrameworkStatsLog.BAL_ALLOWED,
|
||||
DEFAULT_COMPONENT_PACKAGE_NAME + "/" + DEFAULT_COMPONENT_PACKAGE_NAME,
|
||||
BackgroundActivityStartController.BAL_ALLOW_PENDING_INTENT,
|
||||
UNIMPORTANT_UID,
|
||||
Process.SYSTEM_UID));
|
||||
mockingSession.finishMocking();
|
||||
}
|
||||
|
||||
private void runAndVerifyBackgroundActivityStartsSubtest(String name, boolean shouldHaveAborted,
|
||||
int callingUid, boolean callingUidHasVisibleWindow, int callingUidProcState,
|
||||
int realCallingUid, boolean realCallingUidHasVisibleWindow, int realCallingUidProcState,
|
||||
@@ -1491,7 +1563,7 @@ public class ActivityStarterTests extends WindowTestsBase {
|
||||
TaskFragment inTaskFragment) {
|
||||
starter.startActivityInner(target, source, null /* voiceSession */,
|
||||
null /* voiceInteractor */, 0 /* startFlags */, true /* doResume */,
|
||||
options, inTask, inTaskFragment, false /* restrictedBgActivity */,
|
||||
null /* intentGrants */);
|
||||
options, inTask, inTaskFragment,
|
||||
BackgroundActivityStartController.BAL_ALLOW_DEFAULT, null /* intentGrants */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase {
|
||||
/* options */null,
|
||||
/* inTask */null,
|
||||
/* inTaskFragment */ null,
|
||||
/* restrictedBgActivity */false,
|
||||
/* balCode */ BackgroundActivityStartController.BAL_ALLOW_DEFAULT,
|
||||
/* intentGrants */null);
|
||||
|
||||
assertEquals(result, START_ABORTED);
|
||||
|
||||
Reference in New Issue
Block a user