Do not allow moveToFront() and moveTaskToFront() when app is in background
Bug: 129063631
Test: Unable to start activity / move task in background
Change-Id: Icb5ebad3567b911719341f221483df1a1512109b
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1757c98..0b9e3bb 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -6147,8 +6147,9 @@
}
@Override
- public void moveTaskToFront(int taskId, int flags, Bundle bOptions) {
- mActivityTaskManager.moveTaskToFront(taskId, flags, bOptions);
+ public void moveTaskToFront(IApplicationThread appThread, String callingPackage, int taskId,
+ int flags, Bundle bOptions) {
+ mActivityTaskManager.moveTaskToFront(appThread, callingPackage, taskId, flags, bOptions);
}
/**
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 53dc1df..f573b7d 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -2776,8 +2776,8 @@
true /* forceSend */, targetActivity);
mActivityMetricsLogger.notifyActivityLaunching(task.intent);
try {
- mService.moveTaskToFrontLocked(task.taskId, 0, options,
- true /* fromRecents */);
+ mService.moveTaskToFrontLocked(null /* appThread */, null /* callingPackage */,
+ task.taskId, 0, options, true /* fromRecents */);
// Apply options to prevent pendingOptions be taken by client to make sure
// the override pending app transition will be applied immediately.
targetActivity.applyOptionsLocked();
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 3b358e8..a187bf73 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -759,8 +759,8 @@
try {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
"shouldAbortBackgroundActivityStart");
- abortBackgroundStart = shouldAbortBackgroundActivityStart(callingUid, callingPid,
- callingPackage, realCallingUid, realCallingPid, callerApp,
+ abortBackgroundStart = shouldAbortBackgroundActivityStart(callingUid,
+ callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
originatingPendingIntent, allowBackgroundActivityStart, intent);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
@@ -768,14 +768,7 @@
abort |= (abortBackgroundStart && !mService.isBackgroundActivityStartsEnabled());
// TODO: remove this toast after feature development is done
if (abortBackgroundStart) {
- final Resources res = mService.mContext.getResources();
- final String toastMsg = res.getString(abort
- ? R.string.activity_starter_block_bg_activity_starts_enforcing
- : R.string.activity_starter_block_bg_activity_starts_permissive,
- callingPackage);
- mService.mUiHandler.post(() -> {
- Toast.makeText(mService.mContext, toastMsg, Toast.LENGTH_LONG).show();
- });
+ showBackgroundActivityBlockedToast(abort, callingPackage);
}
}
@@ -935,7 +928,7 @@
return res;
}
- private boolean shouldAbortBackgroundActivityStart(int callingUid, int callingPid,
+ boolean shouldAbortBackgroundActivityStart(int callingUid, int callingPid,
final String callingPackage, int realCallingUid, int realCallingPid,
WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent,
boolean allowBackgroundActivityStart, Intent intent) {
@@ -1048,7 +1041,7 @@
+ "; realCallingUid: " + realCallingUid
+ "; isRealCallingUidForeground: " + isRealCallingUidForeground
+ "; isRealCallingUidPersistentSystemProcess: "
- + isRealCallingUidPersistentSystemProcess
+ + isRealCallingUidPersistentSystemProcess
+ "; originatingPendingIntent: " + originatingPendingIntent
+ "; isBgStartWhitelisted: " + allowBackgroundActivityStart
+ "; intent: " + intent
@@ -1076,6 +1069,18 @@
return false;
}
+ // TODO: remove this toast after feature development is done
+ void showBackgroundActivityBlockedToast(boolean abort, String callingPackage) {
+ final Resources res = mService.mContext.getResources();
+ final String toastMsg = res.getString(abort
+ ? R.string.activity_starter_block_bg_activity_starts_enforcing
+ : R.string.activity_starter_block_bg_activity_starts_permissive,
+ callingPackage);
+ mService.mUiHandler.post(() -> {
+ Toast.makeText(mService.mContext, toastMsg, Toast.LENGTH_LONG).show();
+ });
+ }
+
/**
* Creates a launch intent for the given auxiliary resolution data.
*/
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index b64abdb..2c27654 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2280,25 +2280,48 @@
* TODO: Add mController hook
*/
@Override
- public void moveTaskToFront(int taskId, int flags, Bundle bOptions) {
+ public void moveTaskToFront(IApplicationThread appThread, String callingPackage, int taskId,
+ int flags, Bundle bOptions) {
mAmInternal.enforceCallingPermission(android.Manifest.permission.REORDER_TASKS, "moveTaskToFront()");
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToFront: moving taskId=" + taskId);
synchronized (mGlobalLock) {
- moveTaskToFrontLocked(taskId, flags, SafeActivityOptions.fromBundle(bOptions),
- false /* fromRecents */);
+ moveTaskToFrontLocked(appThread, callingPackage, taskId, flags,
+ SafeActivityOptions.fromBundle(bOptions), false /* fromRecents */);
}
}
- void moveTaskToFrontLocked(int taskId, int flags, SafeActivityOptions options,
+ void moveTaskToFrontLocked(@Nullable IApplicationThread appThread,
+ @Nullable String callingPackage, int taskId, int flags, SafeActivityOptions options,
boolean fromRecents) {
- if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
- Binder.getCallingUid(), -1, -1, "Task to front")) {
+ final int callingPid = Binder.getCallingPid();
+ final int callingUid = Binder.getCallingUid();
+ if (!isSameApp(callingUid, callingPackage)) {
+ String msg = "Permission Denial: moveTaskToFrontLocked() from pid="
+ + Binder.getCallingPid() + " as package " + callingPackage;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+ if (!checkAppSwitchAllowedLocked(callingPid, callingUid, -1, -1, "Task to front")) {
SafeActivityOptions.abort(options);
return;
}
final long origId = Binder.clearCallingIdentity();
+ WindowProcessController callerApp = null;
+ 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)) {
+ boolean abort = !isBackgroundActivityStartsEnabled();
+ starter.showBackgroundActivityBlockedToast(abort, callingPackage);
+ if (abort) {
+ return;
+ }
+ }
try {
final TaskRecord task = mRootActivityContainer.anyTaskForId(taskId);
if (task == null) {
@@ -2330,6 +2353,26 @@
}
}
+ /**
+ * Return true if callingUid is system, or packageName belongs to that callingUid.
+ */
+ boolean isSameApp(int callingUid, @Nullable String packageName) {
+ try {
+ if (callingUid != 0 && callingUid != SYSTEM_UID) {
+ if (packageName == null) {
+ return false;
+ }
+ final int uid = AppGlobals.getPackageManager().getPackageUid(packageName,
+ PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
+ UserHandle.getUserId(callingUid));
+ return UserHandle.isSameApp(callingUid, uid);
+ }
+ } catch (RemoteException e) {
+ // Should not happen
+ }
+ return true;
+ }
+
boolean checkAppSwitchAllowedLocked(int sourcePid, int sourceUid,
int callingPid, int callingUid, String name) {
if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
@@ -5290,7 +5333,10 @@
return mAmInternal.isBackgroundActivityStartsEnabled();
}
- boolean isPackageNameWhitelistedForBgActivityStarts(String packageName) {
+ boolean isPackageNameWhitelistedForBgActivityStarts(@Nullable String packageName) {
+ if (packageName == null) {
+ return false;
+ }
return mAmInternal.isPackageNameWhitelistedForBgActivityStarts(packageName);
}
diff --git a/services/core/java/com/android/server/wm/AppTaskImpl.java b/services/core/java/com/android/server/wm/AppTaskImpl.java
index 441c593..e967a92f 100644
--- a/services/core/java/com/android/server/wm/AppTaskImpl.java
+++ b/services/core/java/com/android/server/wm/AppTaskImpl.java
@@ -27,6 +27,7 @@
import android.os.Bundle;
import android.os.IBinder;
import android.os.UserHandle;
+import android.util.Slog;
/**
* An implementation of IAppTask, that allows an app to manage its own tasks via
@@ -34,6 +35,7 @@
* only the process that calls getAppTasks() can call the AppTask methods.
*/
class AppTaskImpl extends IAppTask.Stub {
+ private static final String TAG = "AppTaskImpl";
private ActivityTaskManagerService mService;
private int mTaskId;
@@ -90,16 +92,36 @@
}
@Override
- public void moveToFront() {
+ public void moveToFront(IApplicationThread appThread, String callingPackage) {
checkCaller();
// Will bring task to front if it already has a root activity.
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
+ if (!mService.isSameApp(callingUid, callingPackage)) {
+ String msg = "Permission Denial: moveToFront() from pid="
+ + Binder.getCallingPid() + " as package " + callingPackage;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mService.mGlobalLock) {
- mService.mStackSupervisor.startActivityFromRecents(callingPid, callingUid, mTaskId,
- null);
+ WindowProcessController callerApp = null;
+ 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)) {
+ boolean abort = !mService.isBackgroundActivityStartsEnabled();
+ starter.showBackgroundActivityBlockedToast(abort, callingPackage);
+ if (abort) {
+ return;
+ }
+ }
+ mService.mStackSupervisor.startActivityFromRecents(callingPid,
+ callingUid, mTaskId, null);
}
} finally {
Binder.restoreCallingIdentity(origId);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
index d8a01b9..1880ef5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
@@ -39,7 +39,6 @@
import android.support.test.uiautomator.UiDevice;
import android.text.TextUtils;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import com.android.internal.annotations.GuardedBy;
@@ -207,7 +206,8 @@
// Test for onTaskMovedToFront.
assertEquals(1, taskMovedToFrontLatch.getCount());
- mService.moveTaskToFront(id, 0, null);
+ mService.moveTaskToFront(null, getInstrumentation().getContext().getPackageName(), id, 0,
+ null);
waitForCallback(taskMovedToFrontLatch);
assertEquals(activity.getTaskId(), params[0]);