diff options
author | 2019-04-04 16:01:06 +0100 | |
---|---|---|
committer | 2019-04-10 17:24:30 +0100 | |
commit | aca8a770cd28367f85b8965e6def6f73cc4927e1 (patch) | |
tree | 13224b602b9e62e27fd7992f58b3bef9fbfd68e6 | |
parent | 10a222bf3c35cc62ea5062987814fc60c93b16d8 (diff) |
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
12 files changed, 126 insertions, 39 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 395c867de9d7..53cd6759b2f2 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -2001,7 +2001,10 @@ public class ActivityManager { @RequiresPermission(android.Manifest.permission.REORDER_TASKS) public void moveTaskToFront(int taskId, @MoveTaskFlags int flags, Bundle options) { try { - getTaskService().moveTaskToFront(taskId, flags, options); + ActivityThread thread = ActivityThread.currentActivityThread(); + IApplicationThread appThread = thread.getApplicationThread(); + String packageName = mContext.getPackageName(); + getTaskService().moveTaskToFront(appThread, packageName, taskId, flags, options); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -4212,7 +4215,10 @@ public class ActivityManager { */ public void moveToFront() { try { - mAppTaskImpl.moveToFront(); + ActivityThread thread = ActivityThread.currentActivityThread(); + IApplicationThread appThread = thread.getApplicationThread(); + String packageName = ActivityThread.currentPackageName(); + mAppTaskImpl.moveToFront(appThread, packageName); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 65f10808534f..1785d2a0843b 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -130,7 +130,8 @@ interface IActivityManager { List<ActivityManager.RunningTaskInfo> getFilteredTasks(int maxNum, int ignoreActivityType, int ignoreWindowingMode); @UnsupportedAppUsage - void moveTaskToFront(int task, int flags, in Bundle options); + void moveTaskToFront(in IApplicationThread caller, in String callingPackage, int task, + int flags, in Bundle options); @UnsupportedAppUsage int getTaskForActivity(in IBinder token, in boolean onlyRoot); ContentProviderHolder getContentProvider(in IApplicationThread caller, in String callingPackage, diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl index a6b76cb0db60..7953d42514fc 100644 --- a/core/java/android/app/IActivityTaskManager.aidl +++ b/core/java/android/app/IActivityTaskManager.aidl @@ -149,7 +149,8 @@ interface IActivityTaskManager { boolean shouldUpRecreateTask(in IBinder token, in String destAffinity); boolean navigateUpTo(in IBinder token, in Intent target, int resultCode, in Intent resultData); - void moveTaskToFront(int task, int flags, in Bundle options); + void moveTaskToFront(in IApplicationThread app, in String callingPackage, int task, + int flags, in Bundle options); int getTaskForActivity(in IBinder token, in boolean onlyRoot); void finishSubActivity(in IBinder token, in String resultWho, int requestCode); ParceledListSlice getRecentTasks(int maxNum, int flags, int userId); diff --git a/core/java/android/app/IAppTask.aidl b/core/java/android/app/IAppTask.aidl index 61f6264408f8..3ce71908bbfd 100644 --- a/core/java/android/app/IAppTask.aidl +++ b/core/java/android/app/IAppTask.aidl @@ -17,6 +17,7 @@ package android.app; import android.app.ActivityManager; +import android.app.IApplicationThread; import android.content.Intent; import android.os.Bundle; @@ -25,7 +26,7 @@ interface IAppTask { void finishAndRemoveTask(); @UnsupportedAppUsage ActivityManager.RecentTaskInfo getTaskInfo(); - void moveToFront(); + void moveToFront(in IApplicationThread appThread, in String callingPackage); int startActivity(IBinder whoThread, String callingPackage, in Intent intent, String resolvedType, in Bundle options); void setExcludeFromRecents(boolean exclude); diff --git a/core/java/com/android/internal/app/HeavyWeightSwitcherActivity.java b/core/java/com/android/internal/app/HeavyWeightSwitcherActivity.java index 7735d84ab751..015238788191 100644 --- a/core/java/com/android/internal/app/HeavyWeightSwitcherActivity.java +++ b/core/java/com/android/internal/app/HeavyWeightSwitcherActivity.java @@ -16,11 +16,11 @@ package com.android.internal.app; -import com.android.internal.R; - import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityTaskManager; +import android.app.ActivityThread; +import android.app.IApplicationThread; import android.content.Intent; import android.content.IntentSender; import android.content.pm.ApplicationInfo; @@ -29,13 +29,14 @@ import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.RemoteException; import android.util.Log; -import android.util.TypedValue; import android.view.View; -import android.view.Window; import android.view.View.OnClickListener; +import android.view.Window; import android.widget.ImageView; import android.widget.TextView; +import com.android.internal.R; + /** * This activity is displayed when the system attempts to start an Intent for * which there is more than one matching activity, allowing the user to decide @@ -127,7 +128,10 @@ public class HeavyWeightSwitcherActivity extends Activity { private OnClickListener mSwitchOldListener = new OnClickListener() { public void onClick(View v) { try { - ActivityTaskManager.getService().moveTaskToFront(mCurTask, 0, null); + ActivityThread thread = ActivityThread.currentActivityThread(); + IApplicationThread appThread = thread.getApplicationThread(); + ActivityTaskManager.getService().moveTaskToFront(appThread, getPackageName(), + mCurTask, 0, null); } catch (RemoteException e) { } finish(); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 1757c9816355..0b9e3bb1b99e 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 @@ public class ActivityManagerService extends IActivityManager.Stub } @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 53dc1df5a46a..f573b7df1eea 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 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { 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 3b358e897ccc..a187bf73a817 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 @@ class ActivityStarter { 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 @@ class ActivityStarter { 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 @@ class ActivityStarter { 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 @@ class ActivityStarter { + "; realCallingUid: " + realCallingUid + "; isRealCallingUidForeground: " + isRealCallingUidForeground + "; isRealCallingUidPersistentSystemProcess: " - + isRealCallingUidPersistentSystemProcess + + isRealCallingUidPersistentSystemProcess + "; originatingPendingIntent: " + originatingPendingIntent + "; isBgStartWhitelisted: " + allowBackgroundActivityStart + "; intent: " + intent @@ -1076,6 +1069,18 @@ class ActivityStarter { 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 b64abdb48fba..2c27654826b5 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 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { * 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 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } + /** + * 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 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { 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 441c5935a507..e967a92f1891 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.Binder; 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 @@ import android.os.UserHandle; * 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 @@ class AppTaskImpl extends IAppTask.Stub { } @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 d8a01b9eb9b4..1880ef5b5f0b 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.platform.test.annotations.Presubmit; 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 @@ public class TaskStackChangedListenerTest { // 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]); diff --git a/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java index 548a0c22c569..5fb23b0ad507 100644 --- a/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java +++ b/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java @@ -40,7 +40,7 @@ public class ActivityManagerPermissionTests extends TestCase { @SmallTest public void testREORDER_TASKS() { try { - mAm.moveTaskToFront(0, 0, null); + mAm.moveTaskToFront(null, null, 0, 0, null); fail("IActivityManager.moveTaskToFront did not throw SecurityException as" + " expected"); } catch (SecurityException e) { |