Merge "Formalize recents component in the system"
This commit is contained in:
@@ -102,7 +102,7 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
|
||||
public static final int ACTIVITY_TYPE_STANDARD = 1;
|
||||
/** Home/Launcher activity type. */
|
||||
public static final int ACTIVITY_TYPE_HOME = 2;
|
||||
/** Recents/Overview activity type. */
|
||||
/** Recents/Overview activity type. There is only one activity with this type in the system. */
|
||||
public static final int ACTIVITY_TYPE_RECENTS = 3;
|
||||
/** Assistant activity type. */
|
||||
public static final int ACTIVITY_TYPE_ASSISTANT = 4;
|
||||
|
||||
@@ -2356,6 +2356,10 @@
|
||||
property. If this is false, then the following recents config flags are ignored. -->
|
||||
<bool name="config_hasRecents">true</bool>
|
||||
|
||||
<!-- Component name for the activity that will be presenting the Recents UI, which will receive
|
||||
special permissions for API related to fetching and presenting recent tasks. -->
|
||||
<string name="config_recentsComponentName" translatable="false">com.android.systemui/.recents.RecentsActivity</string>
|
||||
|
||||
<!-- The minimum number of visible recent tasks to be presented to the user through the
|
||||
SystemUI. Can be -1 if there is no minimum limit. -->
|
||||
<integer name="config_minNumVisibleRecentTasks_grid">-1</integer>
|
||||
|
||||
@@ -311,6 +311,7 @@
|
||||
<java-symbol type="bool" name="config_enableMultiUserUI"/>
|
||||
<java-symbol type="bool" name="config_disableUsbPermissionDialogs"/>
|
||||
<java-symbol type="bool" name="config_hasRecents" />
|
||||
<java-symbol type="string" name="config_recentsComponentName" />
|
||||
<java-symbol type="integer" name="config_minNumVisibleRecentTasks_lowRam" />
|
||||
<java-symbol type="integer" name="config_maxNumVisibleRecentTasks_lowRam" />
|
||||
<java-symbol type="integer" name="config_minNumVisibleRecentTasks_grid" />
|
||||
|
||||
@@ -302,11 +302,6 @@ public class RecentsTransitionHelper {
|
||||
*/
|
||||
private List<AppTransitionAnimationSpec> composeAnimationSpecs(final Task task,
|
||||
final TaskStackView stackView, int windowingMode, int activityType, Rect windowRect) {
|
||||
if (activityType == ACTIVITY_TYPE_RECENTS || activityType == ACTIVITY_TYPE_HOME
|
||||
|| windowingMode == WINDOWING_MODE_PINNED) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Calculate the offscreen task rect (for tasks that are not backed by views)
|
||||
TaskView taskView = stackView.getChildViewForTask(task);
|
||||
TaskStackLayoutAlgorithm stackLayout = stackView.getStackAlgorithm();
|
||||
|
||||
@@ -23,6 +23,7 @@ import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
|
||||
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
|
||||
import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
|
||||
import static android.Manifest.permission.READ_FRAME_BUFFER;
|
||||
import static android.Manifest.permission.REMOVE_TASKS;
|
||||
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
|
||||
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
|
||||
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
|
||||
@@ -672,7 +673,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
/**
|
||||
* List of intents that were used to start the most recent tasks.
|
||||
*/
|
||||
final RecentTasks mRecentTasks;
|
||||
private final RecentTasks mRecentTasks;
|
||||
|
||||
/**
|
||||
* For addAppTask: cached of the last activity component that was added.
|
||||
@@ -2773,7 +2774,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
mTaskChangeNotificationController =
|
||||
new TaskChangeNotificationController(this, mStackSupervisor, mHandler);
|
||||
mActivityStarter = new ActivityStarter(this);
|
||||
mRecentTasks = new RecentTasks(this, mStackSupervisor);
|
||||
mRecentTasks = createRecentTasks();
|
||||
mStackSupervisor.setRecentTasks(mRecentTasks);
|
||||
mLockTaskController = new LockTaskController(mContext, mStackSupervisor, mHandler);
|
||||
|
||||
@@ -2819,6 +2820,14 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
return new ActivityStackSupervisor(this, mHandler.getLooper());
|
||||
}
|
||||
|
||||
protected RecentTasks createRecentTasks() {
|
||||
return new RecentTasks(this, mStackSupervisor);
|
||||
}
|
||||
|
||||
RecentTasks getRecentTasks() {
|
||||
return mRecentTasks;
|
||||
}
|
||||
|
||||
public void setSystemServiceManager(SystemServiceManager mgr) {
|
||||
mSystemServiceManager = mgr;
|
||||
}
|
||||
@@ -3154,6 +3163,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
synchronized (this) {
|
||||
final ActivityStack stack = mStackSupervisor.getStack(stackId);
|
||||
if (stack == null) {
|
||||
Slog.w(TAG, "setFocusedStack: No stack with id=" + stackId);
|
||||
return;
|
||||
}
|
||||
final ActivityRecord r = stack.topRunningActivityLocked();
|
||||
@@ -3190,7 +3200,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
/** Sets the task stack listener that gets callbacks when a task stack changes. */
|
||||
@Override
|
||||
public void registerTaskStackListener(ITaskStackListener listener) throws RemoteException {
|
||||
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "registerTaskStackListener()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
|
||||
"registerTaskStackListener()");
|
||||
mTaskChangeNotificationController.registerTaskStackListener(listener);
|
||||
}
|
||||
|
||||
@@ -3199,7 +3210,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
*/
|
||||
@Override
|
||||
public void unregisterTaskStackListener(ITaskStackListener listener) throws RemoteException {
|
||||
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "unregisterTaskStackListener()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
|
||||
"unregisterTaskStackListener()");
|
||||
mTaskChangeNotificationController.unregisterTaskStackListener(listener);
|
||||
}
|
||||
|
||||
@@ -4877,12 +4889,9 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
|
||||
@Override
|
||||
public final int startActivityFromRecents(int taskId, Bundle bOptions) {
|
||||
if (checkCallingPermission(START_TASKS_FROM_RECENTS) != PackageManager.PERMISSION_GRANTED) {
|
||||
String msg = "Permission Denial: startActivityFromRecents called without " +
|
||||
START_TASKS_FROM_RECENTS;
|
||||
Slog.w(TAG, msg);
|
||||
throw new SecurityException(msg);
|
||||
}
|
||||
enforceCallerIsRecentsOrHasPermission(START_TASKS_FROM_RECENTS,
|
||||
"startActivityFromRecents()");
|
||||
|
||||
final long origId = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (this) {
|
||||
@@ -8334,9 +8343,6 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This can be called with or without the global lock held.
|
||||
*/
|
||||
int checkComponentPermission(String permission, int pid, int uid,
|
||||
int owningUid, boolean exported) {
|
||||
if (pid == MY_PID) {
|
||||
@@ -8410,6 +8416,15 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
throw new SecurityException(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* This can be called with or without the global lock held.
|
||||
*/
|
||||
void enforceCallerIsRecentsOrHasPermission(String permission, String func) {
|
||||
if (!mRecentTasks.isCallerRecents(Binder.getCallingUid())) {
|
||||
enforceCallingPermission(permission, func);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if UID is holding permissions required to access {@link Uri} in
|
||||
* the given {@link ProviderInfo}. Final permission checking is always done
|
||||
@@ -9799,6 +9814,11 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
}
|
||||
|
||||
private boolean isGetTasksAllowed(String caller, int callingPid, int callingUid) {
|
||||
if (mRecentTasks.isCallerRecents(callingUid)) {
|
||||
// Always allow the recents component to get tasks
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean allowed = checkPermission(android.Manifest.permission.REAL_GET_TASKS,
|
||||
callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
|
||||
if (!allowed) {
|
||||
@@ -9846,8 +9866,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
@Override
|
||||
public ActivityManager.TaskDescription getTaskDescription(int id) {
|
||||
synchronized (this) {
|
||||
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
|
||||
"getTaskDescription()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getTaskDescription()");
|
||||
final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(id,
|
||||
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
|
||||
if (tr != null) {
|
||||
@@ -10041,7 +10060,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
|
||||
@Override
|
||||
public void cancelTaskWindowTransition(int taskId) {
|
||||
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "cancelTaskWindowTransition()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
|
||||
"cancelTaskWindowTransition()");
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (this) {
|
||||
@@ -10060,7 +10080,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
|
||||
@Override
|
||||
public void cancelTaskThumbnailTransition(int taskId) {
|
||||
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "cancelTaskThumbnailTransition()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
|
||||
"cancelTaskThumbnailTransition()");
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (this) {
|
||||
@@ -10079,7 +10100,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
|
||||
@Override
|
||||
public TaskSnapshot getTaskSnapshot(int taskId, boolean reducedResolution) {
|
||||
enforceCallingPermission(READ_FRAME_BUFFER, "getTaskSnapshot()");
|
||||
enforceCallerIsRecentsOrHasPermission(READ_FRAME_BUFFER, "getTaskSnapshot()");
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
final TaskRecord task;
|
||||
@@ -10132,12 +10153,13 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
|
||||
@Override
|
||||
public void removeStack(int stackId) {
|
||||
enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS, "removeStack()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "removeStack()");
|
||||
synchronized (this) {
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
final ActivityStack stack = mStackSupervisor.getStack(stackId);
|
||||
if (stack == null) {
|
||||
Slog.w(TAG, "removeStack: No stack with id=" + stackId);
|
||||
return;
|
||||
}
|
||||
if (!stack.isActivityTypeStandardOrUndefined()) {
|
||||
@@ -10157,7 +10179,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
*/
|
||||
@Override
|
||||
public void removeStacksInWindowingModes(int[] windowingModes) {
|
||||
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "removeStacksInWindowingModes()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
|
||||
"removeStacksInWindowingModes()");
|
||||
synchronized (this) {
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
@@ -10170,7 +10193,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
|
||||
@Override
|
||||
public void removeStacksWithActivityTypes(int[] activityTypes) {
|
||||
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "removeStacksWithActivityTypes()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
|
||||
"removeStacksWithActivityTypes()");
|
||||
synchronized (this) {
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
@@ -10199,7 +10223,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
|
||||
@Override
|
||||
public boolean removeTask(int taskId) {
|
||||
enforceCallingPermission(android.Manifest.permission.REMOVE_TASKS, "removeTask()");
|
||||
enforceCallerIsRecentsOrHasPermission(REMOVE_TASKS, "removeTask()");
|
||||
synchronized (this) {
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
@@ -10376,7 +10400,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
|
||||
@Override
|
||||
public void setTaskWindowingMode(int taskId, int windowingMode, boolean toTop) {
|
||||
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "setTaskWindowingMode()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "setTaskWindowingMode()");
|
||||
synchronized (this) {
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
@@ -10412,7 +10436,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
|
||||
@Override
|
||||
public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
|
||||
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToStack()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToStack()");
|
||||
synchronized (this) {
|
||||
long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
@@ -10463,7 +10487,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
@Override
|
||||
public boolean moveTaskToDockedStack(int taskId, int createMode, boolean toTop, boolean animate,
|
||||
Rect initialBounds) {
|
||||
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToDockedStack()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToDockedStack()");
|
||||
synchronized (this) {
|
||||
long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
@@ -10502,12 +10526,16 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
*/
|
||||
@Override
|
||||
public void dismissSplitScreenMode(boolean toTop) {
|
||||
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "dismissSplitScreenMode()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "dismissSplitScreenMode()");
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (this) {
|
||||
final ActivityStack stack =
|
||||
mStackSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
|
||||
if (stack == null) {
|
||||
Slog.w(TAG, "dismissSplitScreenMode: primary split-screen stack not found.");
|
||||
return;
|
||||
}
|
||||
if (toTop) {
|
||||
mStackSupervisor.resizeStackLocked(stack, null /* destBounds */,
|
||||
null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
|
||||
@@ -10530,14 +10558,14 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
*/
|
||||
@Override
|
||||
public void dismissPip(boolean animate, int animationDuration) {
|
||||
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "dismissPip()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "dismissPip()");
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (this) {
|
||||
final PinnedActivityStack stack =
|
||||
mStackSupervisor.getDefaultDisplay().getPinnedStack();
|
||||
|
||||
if (stack == null) {
|
||||
Slog.w(TAG, "dismissPip: pinned stack not found.");
|
||||
return;
|
||||
}
|
||||
if (stack.getWindowingMode() != WINDOWING_MODE_PINNED) {
|
||||
@@ -10567,7 +10595,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
*/
|
||||
@Override
|
||||
public boolean moveTopActivityToPinnedStack(int stackId, Rect bounds) {
|
||||
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTopActivityToPinnedStack()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
|
||||
"moveTopActivityToPinnedStack()");
|
||||
synchronized (this) {
|
||||
if (!mSupportsPictureInPicture) {
|
||||
throw new IllegalStateException("moveTopActivityToPinnedStack:"
|
||||
@@ -10586,13 +10615,14 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
@Override
|
||||
public void resizeStack(int stackId, Rect destBounds, boolean allowResizeInDockedMode,
|
||||
boolean preserveWindows, boolean animate, int animationDuration) {
|
||||
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "resizeStack()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizeStack()");
|
||||
long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (this) {
|
||||
if (animate) {
|
||||
final PinnedActivityStack stack = mStackSupervisor.getStack(stackId);
|
||||
if (stack == null) {
|
||||
Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
|
||||
return;
|
||||
}
|
||||
if (stack.getWindowingMode() != WINDOWING_MODE_PINNED) {
|
||||
@@ -10621,8 +10651,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
public void resizeDockedStack(Rect dockedBounds, Rect tempDockedTaskBounds,
|
||||
Rect tempDockedTaskInsetBounds,
|
||||
Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds) {
|
||||
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
|
||||
"resizeDockedStack()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizeDockedStack()");
|
||||
long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (this) {
|
||||
@@ -10637,8 +10666,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
|
||||
@Override
|
||||
public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
|
||||
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
|
||||
"resizePinnedStack()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizePinnedStack()");
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (this) {
|
||||
@@ -10697,7 +10725,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
|
||||
@Override
|
||||
public List<StackInfo> getAllStackInfos() {
|
||||
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "getAllStackInfos()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getAllStackInfos()");
|
||||
long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (this) {
|
||||
@@ -10710,7 +10738,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
|
||||
@Override
|
||||
public StackInfo getStackInfo(int windowingMode, int activityType) {
|
||||
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
|
||||
long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (this) {
|
||||
@@ -11871,8 +11899,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
|
||||
@Override
|
||||
public void appNotRespondingViaProvider(IBinder connection) {
|
||||
enforceCallingPermission(
|
||||
android.Manifest.permission.REMOVE_TASKS, "appNotRespondingViaProvider()");
|
||||
enforceCallingPermission(REMOVE_TASKS, "appNotRespondingViaProvider()");
|
||||
|
||||
final ContentProviderConnection conn = (ContentProviderConnection) connection;
|
||||
if (conn == null) {
|
||||
@@ -18135,8 +18162,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
// =========================================================
|
||||
|
||||
@Override
|
||||
public List<ActivityManager.RunningServiceInfo> getServices(int maxNum,
|
||||
int flags) {
|
||||
public List<ActivityManager.RunningServiceInfo> getServices(int maxNum, int flags) {
|
||||
enforceNotIsolatedCaller("getServices");
|
||||
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
@@ -20080,7 +20106,7 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
|
||||
@Override
|
||||
public StackInfo getFocusedStackInfo() throws RemoteException {
|
||||
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
|
||||
long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
synchronized (this) {
|
||||
@@ -20120,7 +20146,8 @@ public class ActivityManagerService extends IActivityManager.Stub
|
||||
@Override
|
||||
// TODO: API should just be about changing windowing modes...
|
||||
public void moveTasksToFullscreenStack(int fromStackId, boolean onTop) {
|
||||
enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "moveTasksToFullscreenStack()");
|
||||
enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
|
||||
"moveTasksToFullscreenStack()");
|
||||
synchronized (this) {
|
||||
final long origId = Binder.clearCallingIdentity();
|
||||
try {
|
||||
|
||||
@@ -2305,7 +2305,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
|
||||
int runWrite(PrintWriter pw) {
|
||||
mInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
|
||||
"registerUidObserver()");
|
||||
mInternal.mRecentTasks.flush();
|
||||
mInternal.getRecentTasks().flush();
|
||||
pw.println("All tasks persisted.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -204,7 +204,6 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
|
||||
private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
|
||||
|
||||
private static final boolean SHOW_ACTIVITY_START_TIME = true;
|
||||
private static final String RECENTS_PACKAGE_NAME = "com.android.systemui.recents";
|
||||
|
||||
private static final String ATTR_ID = "id";
|
||||
private static final String TAG_INTENT = "intent";
|
||||
@@ -1058,7 +1057,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
|
||||
// We only allow home activities to be resizeable if they explicitly requested it.
|
||||
info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
|
||||
}
|
||||
} else if (realActivity.getClassName().contains(RECENTS_PACKAGE_NAME)) {
|
||||
} else if (service.getRecentTasks().isRecentsComponent(realActivity, appInfo.uid)) {
|
||||
activityType = ACTIVITY_TYPE_RECENTS;
|
||||
} else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_ASSISTANT
|
||||
&& canLaunchAssistActivity(launchedFromPackage)) {
|
||||
@@ -1562,17 +1561,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean isVisible = !behindFullscreenActivity || mLaunchTaskBehind;
|
||||
|
||||
if (service.mSupportsLeanbackOnly && isVisible && isActivityTypeRecents()) {
|
||||
// On devices that support leanback only (Android TV), Recents activity can only be
|
||||
// visible if the home stack is the focused stack or we are in split-screen mode.
|
||||
final ActivityDisplay display = getDisplay();
|
||||
boolean hasSplitScreenStack = display != null && display.hasSplitScreenPrimaryStack();
|
||||
isVisible = hasSplitScreenStack || mStackSupervisor.isFocusedStack(getStack());
|
||||
}
|
||||
|
||||
return isVisible;
|
||||
return !behindFullscreenActivity || mLaunchTaskBehind;
|
||||
}
|
||||
|
||||
void makeVisibleIfNeeded(ActivityRecord starting) {
|
||||
@@ -2074,7 +2063,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
|
||||
final File iconFile = new File(TaskPersister.getUserImagesDir(task.userId),
|
||||
iconFilename);
|
||||
final String iconFilePath = iconFile.getAbsolutePath();
|
||||
service.mRecentTasks.saveImage(icon, iconFilePath);
|
||||
service.getRecentTasks().saveImage(icon, iconFilePath);
|
||||
_taskDescription.setIconFilename(iconFilePath);
|
||||
}
|
||||
taskDescription = _taskDescription;
|
||||
|
||||
@@ -285,7 +285,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
|
||||
RecentTasks mRecentTasks;
|
||||
|
||||
/** Helper class to abstract out logic for fetching the set of currently running tasks */
|
||||
private RunningTasks mRunningTasks = new RunningTasks();
|
||||
private RunningTasks mRunningTasks;
|
||||
|
||||
final ActivityStackSupervisorHandler mHandler;
|
||||
|
||||
@@ -572,6 +572,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
|
||||
public ActivityStackSupervisor(ActivityManagerService service, Looper looper) {
|
||||
mService = service;
|
||||
mHandler = new ActivityStackSupervisorHandler(looper);
|
||||
mRunningTasks = createRunningTasks();
|
||||
mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext);
|
||||
mKeyguardController = new KeyguardController(service, this);
|
||||
|
||||
@@ -584,6 +585,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
|
||||
mRecentTasks.registerCallback(this);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
RunningTasks createRunningTasks() {
|
||||
return new RunningTasks();
|
||||
}
|
||||
|
||||
/**
|
||||
* At the time when the constructor runs, the power manager has not yet been
|
||||
* initialized. So we initialize our wakelocks afterwards.
|
||||
@@ -1559,7 +1565,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
|
||||
return false;
|
||||
}
|
||||
if (options != null) {
|
||||
if (options.getLaunchTaskId() != INVALID_STACK_ID) {
|
||||
// If a launch task id is specified, then ensure that the caller is the recents
|
||||
// component or has the START_TASKS_FROM_RECENTS permission
|
||||
if (options.getLaunchTaskId() != INVALID_TASK_ID
|
||||
&& !mRecentTasks.isCallerRecents(callingUid)) {
|
||||
final int startInTaskPerm = mService.checkPermission(START_TASKS_FROM_RECENTS,
|
||||
callingPid, callingUid);
|
||||
if (startInTaskPerm == PERMISSION_DENIED) {
|
||||
|
||||
@@ -82,7 +82,7 @@ class AppTaskImpl extends IAppTask.Stub {
|
||||
if (tr == null) {
|
||||
throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
|
||||
}
|
||||
return mService.mRecentTasks.createRecentTaskInfo(tr);
|
||||
return mService.getRecentTasks().createRecentTaskInfo(tr);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(origId);
|
||||
}
|
||||
|
||||
@@ -37,8 +37,6 @@ import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NA
|
||||
import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
|
||||
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
|
||||
|
||||
import com.google.android.collect.Sets;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.AppGlobals;
|
||||
import android.content.ComponentName;
|
||||
@@ -58,9 +56,8 @@ import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArraySet;
|
||||
import android.util.MutableBoolean;
|
||||
import android.util.MutableInt;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseBooleanArray;
|
||||
@@ -68,6 +65,8 @@ import android.util.SparseBooleanArray;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.am.TaskRecord.TaskActivitiesReport;
|
||||
|
||||
import com.google.android.collect.Sets;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
@@ -124,6 +123,13 @@ class RecentTasks {
|
||||
private final ActivityManagerService mService;
|
||||
private final UserController mUserController;
|
||||
|
||||
/**
|
||||
* Keeps track of the static recents package/component which is granted additional permissions
|
||||
* to call recents-related APIs.
|
||||
*/
|
||||
private int mRecentsUid = -1;
|
||||
private ComponentName mRecentsComponent = null;
|
||||
|
||||
/**
|
||||
* Mapping of user id -> whether recent tasks have been loaded for that user.
|
||||
*/
|
||||
@@ -153,8 +159,7 @@ class RecentTasks {
|
||||
private final HashMap<ComponentName, ActivityInfo> mTmpAvailActCache = new HashMap<>();
|
||||
private final HashMap<String, ApplicationInfo> mTmpAvailAppCache = new HashMap<>();
|
||||
private final SparseBooleanArray mTmpQuietProfileUserIds = new SparseBooleanArray();
|
||||
private final TaskRecord.TaskActivitiesReport mTmpReport =
|
||||
new TaskRecord.TaskActivitiesReport();
|
||||
private final TaskActivitiesReport mTmpReport = new TaskActivitiesReport();
|
||||
|
||||
@VisibleForTesting
|
||||
RecentTasks(ActivityManagerService service, TaskPersister taskPersister,
|
||||
@@ -174,7 +179,7 @@ class RecentTasks {
|
||||
mTaskPersister = new TaskPersister(systemDir, stackSupervisor, service, this);
|
||||
mGlobalMaxNumTasks = ActivityManager.getMaxRecentTasksStatic();
|
||||
mHasVisibleRecentTasks = res.getBoolean(com.android.internal.R.bool.config_hasRecents);
|
||||
loadParametersFromResources(service.mContext.getResources());
|
||||
loadParametersFromResources(res);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -218,6 +223,47 @@ class RecentTasks {
|
||||
: -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the static recents component. This is called after the system is ready, but before
|
||||
* any dependent services (like SystemUI) is started.
|
||||
*/
|
||||
void loadRecentsComponent(Resources res) {
|
||||
final String rawRecentsComponent = res.getString(
|
||||
com.android.internal.R.string.config_recentsComponentName);
|
||||
if (TextUtils.isEmpty(rawRecentsComponent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ComponentName cn = ComponentName.unflattenFromString(rawRecentsComponent);
|
||||
if (cn != null) {
|
||||
try {
|
||||
final ApplicationInfo appInfo = AppGlobals.getPackageManager()
|
||||
.getApplicationInfo(cn.getPackageName(), 0, mService.mContext.getUserId());
|
||||
if (appInfo != null) {
|
||||
mRecentsUid = appInfo.uid;
|
||||
mRecentsComponent = cn;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Slog.w(TAG, "Could not load application info for recents component: " + cn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether the current caller has the same uid as the recents component.
|
||||
*/
|
||||
boolean isCallerRecents(int callingUid) {
|
||||
return UserHandle.isSameApp(callingUid, mRecentsUid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether the given component is the recents component and shares the same uid as the
|
||||
* recents component.
|
||||
*/
|
||||
boolean isRecentsComponent(ComponentName cn, int uid) {
|
||||
return cn.equals(mRecentsComponent) && UserHandle.isSameApp(uid, mRecentsUid);
|
||||
}
|
||||
|
||||
void registerCallback(Callbacks callback) {
|
||||
mCallbacks.add(callback);
|
||||
}
|
||||
@@ -340,6 +386,7 @@ class RecentTasks {
|
||||
}
|
||||
|
||||
void onSystemReadyLocked() {
|
||||
loadRecentsComponent(mService.mContext.getResources());
|
||||
mTasks.clear();
|
||||
mTaskPersister.startPersisting();
|
||||
}
|
||||
@@ -1328,12 +1375,14 @@ class RecentTasks {
|
||||
|
||||
void dump(PrintWriter pw, boolean dumpAll, String dumpPackage) {
|
||||
pw.println("ACTIVITY MANAGER RECENT TASKS (dumpsys activity recents)");
|
||||
pw.println("mRecentsUid=" + mRecentsUid);
|
||||
pw.println("mRecentsComponent=" + mRecentsComponent);
|
||||
if (mTasks.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final MutableBoolean printedAnything = new MutableBoolean(false);
|
||||
final MutableBoolean printedHeader = new MutableBoolean(false);
|
||||
boolean printedAnything = false;
|
||||
boolean printedHeader = false;
|
||||
final int size = mTasks.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
final TaskRecord tr = mTasks.get(i);
|
||||
@@ -1342,10 +1391,10 @@ class RecentTasks {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!printedHeader.value) {
|
||||
if (!printedHeader) {
|
||||
pw.println(" Recent tasks:");
|
||||
printedHeader.value = true;
|
||||
printedAnything.value = true;
|
||||
printedHeader = true;
|
||||
printedAnything = true;
|
||||
}
|
||||
pw.print(" * Recent #"); pw.print(i); pw.print(": ");
|
||||
pw.println(tr);
|
||||
@@ -1354,7 +1403,7 @@ class RecentTasks {
|
||||
}
|
||||
}
|
||||
|
||||
if (!printedAnything.value) {
|
||||
if (!printedAnything) {
|
||||
pw.println(" (nothing)");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2020,7 +2020,7 @@ class UserController implements Handler.Callback {
|
||||
|
||||
void loadUserRecents(int userId) {
|
||||
synchronized (mService) {
|
||||
mService.mRecentTasks.loadUserRecentsLocked(userId);
|
||||
mService.getRecentTasks().loadUserRecentsLocked(userId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,11 @@ public class ActivityTestsBase {
|
||||
}
|
||||
|
||||
protected ActivityManagerService createActivityManagerService() {
|
||||
final ActivityManagerService service = spy(new TestActivityManagerService(mContext));
|
||||
return setupActivityManagerService(new TestActivityManagerService(mContext));
|
||||
}
|
||||
|
||||
protected ActivityManagerService setupActivityManagerService(ActivityManagerService service) {
|
||||
service = spy(service);
|
||||
service.mWindowManager = prepareMockWindowManager();
|
||||
return service;
|
||||
}
|
||||
|
||||
@@ -16,44 +16,55 @@
|
||||
|
||||
package com.android.server.am;
|
||||
|
||||
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
|
||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import static java.lang.Integer.MAX_VALUE;
|
||||
|
||||
import android.app.ActivityManager.RecentTaskInfo;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.Debug;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.filters.MediumTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.util.MutableLong;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseBooleanArray;
|
||||
|
||||
import com.android.server.am.RecentTasks.Callbacks;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* runtest --path frameworks/base/services/tests/servicestests/src/com/android/server/am/RecentTasksTest.java
|
||||
@@ -67,13 +78,17 @@ public class RecentTasksTest extends ActivityTestsBase {
|
||||
private static final int TEST_QUIET_USER_ID = 20;
|
||||
private static final UserInfo DEFAULT_USER_INFO = new UserInfo();
|
||||
private static final UserInfo QUIET_USER_INFO = new UserInfo();
|
||||
private static final ComponentName MY_COMPONENT = new ComponentName(
|
||||
RecentTasksTest.class.getPackage().getName(), RecentTasksTest.class.getName());
|
||||
private static int LAST_TASK_ID = 1;
|
||||
private static int INVALID_STACK_ID = 999;
|
||||
|
||||
private Context mContext = InstrumentationRegistry.getContext();
|
||||
private ActivityManagerService mService;
|
||||
private ActivityStack mStack;
|
||||
private TestTaskPersister mTaskPersister;
|
||||
private RecentTasks mRecentTasks;
|
||||
private RunningTasks mRunningTasks;
|
||||
|
||||
private static ArrayList<TaskRecord> mTasks = new ArrayList<>();
|
||||
private static ArrayList<TaskRecord> mSameDocumentTasks = new ArrayList<>();
|
||||
@@ -90,6 +105,14 @@ public class RecentTasksTest extends ActivityTestsBase {
|
||||
return new int[] { TEST_USER_0_ID, TEST_QUIET_USER_ID };
|
||||
}
|
||||
|
||||
@Override
|
||||
Set<Integer> getProfileIds(int userId) {
|
||||
Set<Integer> profileIds = new HashSet<>();
|
||||
profileIds.add(TEST_USER_0_ID);
|
||||
profileIds.add(TEST_QUIET_USER_ID);
|
||||
return profileIds;
|
||||
}
|
||||
|
||||
@Override
|
||||
UserInfo getUserInfo(int userId) {
|
||||
switch (userId) {
|
||||
@@ -108,12 +131,12 @@ public class RecentTasksTest extends ActivityTestsBase {
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
mService = createActivityManagerService();
|
||||
mTaskPersister = new TestTaskPersister(mContext.getFilesDir());
|
||||
mService = setupActivityManagerService(new MyTestActivityManagerService(mContext));
|
||||
mRecentTasks = mService.getRecentTasks();
|
||||
mRecentTasks.loadParametersFromResources(mContext.getResources());
|
||||
mStack = mService.mStackSupervisor.getDefaultDisplay().createStack(
|
||||
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
|
||||
mTaskPersister = new TestTaskPersister(mContext.getFilesDir());
|
||||
mRecentTasks = new RecentTasks(mService, mTaskPersister, new TestUserController(mService));
|
||||
mRecentTasks.loadParametersFromResources(mContext.getResources());
|
||||
mCallbacksRecorder = new CallbacksRecorder();
|
||||
mRecentTasks.registerCallback(mCallbacksRecorder);
|
||||
QUIET_USER_INFO.flags = UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_QUIET_MODE;
|
||||
@@ -322,6 +345,103 @@ public class RecentTasksTest extends ActivityTestsBase {
|
||||
assertTrimmed(mTasks.get(0), mTasks.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotRecentsComponent_denyApiAccess() throws Exception {
|
||||
doReturn(PackageManager.PERMISSION_DENIED).when(mService).checkPermission(anyString(),
|
||||
anyInt(), anyInt());
|
||||
|
||||
// Expect the following methods to fail due to recents component not being set
|
||||
((TestRecentTasks) mRecentTasks).setIsCallerRecentsOverride(
|
||||
TestRecentTasks.DENY_THROW_SECURITY_EXCEPTION);
|
||||
testRecentTasksApis(false /* expectNoSecurityException */);
|
||||
// Don't throw for the following tests
|
||||
((TestRecentTasks) mRecentTasks).setIsCallerRecentsOverride(TestRecentTasks.DENY);
|
||||
testGetTasksApis(false /* expectNoSecurityException */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRecentsComponent_allowApiAccessWithoutPermissions() throws Exception {
|
||||
doReturn(PackageManager.PERMISSION_DENIED).when(mService).checkPermission(anyString(),
|
||||
anyInt(), anyInt());
|
||||
|
||||
// Set the recents component and ensure that the following calls do not fail
|
||||
((TestRecentTasks) mRecentTasks).setIsCallerRecentsOverride(TestRecentTasks.GRANT);
|
||||
testRecentTasksApis(true /* expectNoSecurityException */);
|
||||
testGetTasksApis(true /* expectNoSecurityException */);
|
||||
}
|
||||
|
||||
private void testRecentTasksApis(boolean expectCallable) {
|
||||
assertSecurityException(expectCallable, () -> mService.removeStack(INVALID_STACK_ID));
|
||||
assertSecurityException(expectCallable,
|
||||
() -> mService.removeStacksInWindowingModes(new int[] {WINDOWING_MODE_UNDEFINED}));
|
||||
assertSecurityException(expectCallable,
|
||||
() -> mService.removeStacksWithActivityTypes(new int[] {ACTIVITY_TYPE_UNDEFINED}));
|
||||
assertSecurityException(expectCallable, () -> mService.removeTask(0));
|
||||
assertSecurityException(expectCallable,
|
||||
() -> mService.setTaskWindowingMode(0, WINDOWING_MODE_UNDEFINED, true));
|
||||
assertSecurityException(expectCallable,
|
||||
() -> mService.moveTaskToStack(0, INVALID_STACK_ID, true));
|
||||
assertSecurityException(expectCallable,
|
||||
() -> mService.moveTaskToDockedStack(0, DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, true,
|
||||
true, new Rect()));
|
||||
assertSecurityException(expectCallable, () -> mService.dismissSplitScreenMode(true));
|
||||
assertSecurityException(expectCallable, () -> mService.dismissPip(true, 0));
|
||||
assertSecurityException(expectCallable,
|
||||
() -> mService.moveTopActivityToPinnedStack(INVALID_STACK_ID, new Rect()));
|
||||
assertSecurityException(expectCallable,
|
||||
() -> mService.resizeStack(INVALID_STACK_ID, new Rect(), true, true, true, 0));
|
||||
assertSecurityException(expectCallable,
|
||||
() -> mService.resizeDockedStack(new Rect(), new Rect(), new Rect(), new Rect(),
|
||||
new Rect()));
|
||||
assertSecurityException(expectCallable,
|
||||
() -> mService.resizePinnedStack(new Rect(), new Rect()));
|
||||
assertSecurityException(expectCallable, () -> mService.getAllStackInfos());
|
||||
assertSecurityException(expectCallable,
|
||||
() -> mService.getStackInfo(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_UNDEFINED));
|
||||
assertSecurityException(expectCallable, () -> {
|
||||
try {
|
||||
mService.getFocusedStackInfo();
|
||||
} catch (RemoteException e) {
|
||||
// Ignore
|
||||
}
|
||||
});
|
||||
assertSecurityException(expectCallable,
|
||||
() -> mService.moveTasksToFullscreenStack(INVALID_STACK_ID, true));
|
||||
assertSecurityException(expectCallable,
|
||||
() -> mService.startActivityFromRecents(0, new Bundle()));
|
||||
assertSecurityException(expectCallable,
|
||||
() -> mService.getTaskSnapshot(0, true));
|
||||
assertSecurityException(expectCallable, () -> {
|
||||
try {
|
||||
mService.registerTaskStackListener(null);
|
||||
} catch (RemoteException e) {
|
||||
// Ignore
|
||||
}
|
||||
});
|
||||
assertSecurityException(expectCallable, () -> {
|
||||
try {
|
||||
mService.unregisterTaskStackListener(null);
|
||||
} catch (RemoteException e) {
|
||||
// Ignore
|
||||
}
|
||||
});
|
||||
assertSecurityException(expectCallable, () -> mService.getTaskDescription(0));
|
||||
assertSecurityException(expectCallable, () -> mService.cancelTaskWindowTransition(0));
|
||||
assertSecurityException(expectCallable, () -> mService.cancelTaskThumbnailTransition(0));
|
||||
}
|
||||
|
||||
private void testGetTasksApis(boolean expectCallable) {
|
||||
mService.getRecentTasks(MAX_VALUE, 0, TEST_USER_0_ID);
|
||||
mService.getTasks(MAX_VALUE);
|
||||
if (expectCallable) {
|
||||
assertTrue(((TestRecentTasks) mRecentTasks).mLastAllowed);
|
||||
assertTrue(((TestRunningTasks) mRunningTasks).mLastAllowed);
|
||||
} else {
|
||||
assertFalse(((TestRecentTasks) mRecentTasks).mLastAllowed);
|
||||
assertFalse(((TestRunningTasks) mRunningTasks).mLastAllowed);
|
||||
}
|
||||
}
|
||||
|
||||
private ComponentName createComponent(String className) {
|
||||
return new ComponentName(mContext.getPackageName(), className);
|
||||
}
|
||||
@@ -367,6 +487,55 @@ public class RecentTasksTest extends ActivityTestsBase {
|
||||
}
|
||||
}
|
||||
|
||||
private void assertSecurityException(boolean expectCallable, Runnable runnable) {
|
||||
boolean noSecurityException = true;
|
||||
try {
|
||||
runnable.run();
|
||||
} catch (SecurityException se) {
|
||||
noSecurityException = false;
|
||||
} catch (Exception e) {
|
||||
// We only care about SecurityExceptions, fall through here
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (noSecurityException != expectCallable) {
|
||||
fail("Expected callable: " + expectCallable + " but got no security exception: "
|
||||
+ noSecurityException);
|
||||
}
|
||||
}
|
||||
|
||||
private class MyTestActivityManagerService extends TestActivityManagerService {
|
||||
MyTestActivityManagerService(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ActivityStackSupervisor createStackSupervisor() {
|
||||
return new MyTestActivityStackSupervisor(this, mHandlerThread.getLooper());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RecentTasks createRecentTasks() {
|
||||
return new TestRecentTasks(this, mTaskPersister, new TestUserController(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUserRunning(int userId, int flags) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class MyTestActivityStackSupervisor extends TestActivityStackSupervisor {
|
||||
public MyTestActivityStackSupervisor(ActivityManagerService service, Looper looper) {
|
||||
super(service, looper);
|
||||
}
|
||||
|
||||
@Override
|
||||
RunningTasks createRunningTasks() {
|
||||
mRunningTasks = new TestRunningTasks();
|
||||
return mRunningTasks;
|
||||
}
|
||||
}
|
||||
|
||||
private static class CallbacksRecorder implements Callbacks {
|
||||
ArrayList<TaskRecord> added = new ArrayList<>();
|
||||
ArrayList<TaskRecord> trimmed = new ArrayList<>();
|
||||
@@ -417,4 +586,61 @@ public class RecentTasksTest extends ActivityTestsBase {
|
||||
return super.restoreTasksForUserLocked(userId, preaddedTasks);
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestRecentTasks extends RecentTasks {
|
||||
static final int GRANT = 0;
|
||||
static final int DENY = 1;
|
||||
static final int DENY_THROW_SECURITY_EXCEPTION = 2;
|
||||
|
||||
private boolean mOverrideIsCallerRecents;
|
||||
private int mIsCallerRecentsPolicy;
|
||||
boolean mLastAllowed;
|
||||
|
||||
TestRecentTasks(ActivityManagerService service, TaskPersister taskPersister,
|
||||
UserController userController) {
|
||||
super(service, taskPersister, userController);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isCallerRecents(int callingUid) {
|
||||
if (mOverrideIsCallerRecents) {
|
||||
switch (mIsCallerRecentsPolicy) {
|
||||
case GRANT:
|
||||
return true;
|
||||
case DENY:
|
||||
return false;
|
||||
case DENY_THROW_SECURITY_EXCEPTION:
|
||||
throw new SecurityException();
|
||||
}
|
||||
}
|
||||
return super.isCallerRecents(callingUid);
|
||||
}
|
||||
|
||||
void setIsCallerRecentsOverride(int policy) {
|
||||
mOverrideIsCallerRecents = true;
|
||||
mIsCallerRecentsPolicy = policy;
|
||||
}
|
||||
|
||||
@Override
|
||||
ParceledListSlice<RecentTaskInfo> getRecentTasks(int maxNum, int flags,
|
||||
boolean getTasksAllowed,
|
||||
boolean getDetailedTasks, int userId, int callingUid) {
|
||||
mLastAllowed = getTasksAllowed;
|
||||
return super.getRecentTasks(maxNum, flags, getTasksAllowed, getDetailedTasks, userId,
|
||||
callingUid);
|
||||
}
|
||||
}
|
||||
|
||||
private static class TestRunningTasks extends RunningTasks {
|
||||
boolean mLastAllowed;
|
||||
|
||||
@Override
|
||||
void getTasks(int maxNum, List<RunningTaskInfo> list, int ignoreActivityType,
|
||||
int ignoreWindowingMode, SparseArray<ActivityDisplay> activityDisplays,
|
||||
int callingUid, boolean allowed) {
|
||||
mLastAllowed = allowed;
|
||||
super.getTasks(maxNum, list, ignoreActivityType, ignoreWindowingMode, activityDisplays,
|
||||
callingUid, allowed);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user