Moved more stuff from ActivityManagerService to ActivityTaskManagerService (9/n)
Moved more stuff related to activities out of the current service to the new one.
Test: Existing tests pass
Test: go/wm-smoke-auto
Bug: 80414790
Change-Id: I16863dd977bf09136cc23b0ab3aa197c613879ea
diff --git a/services/core/java/com/android/server/am/ActivityTaskManagerService.java b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
index 90097fd..d554e0f 100644
--- a/services/core/java/com/android/server/am/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityTaskManagerService.java
@@ -24,6 +24,7 @@
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.Manifest.permission.STOP_APP_SWITCHES;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
import static android.app.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
@@ -32,6 +33,7 @@
import static android.app.ActivityTaskManager.INVALID_STACK_ID;
import static android.app.ActivityTaskManager.RESIZE_MODE_PRESERVE_WINDOW;
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
+import static android.app.AppOpsManager.OP_NONE;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
@@ -42,8 +44,19 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
+import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
+import static android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY;
+import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
+import static android.os.Build.VERSION_CODES.N;
import static android.os.Process.SYSTEM_UID;
+import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
+import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
+import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
+import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RTL;
+import static android.provider.Settings.Global.NETWORK_ACCESS_TIMEOUT_MS;
import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_APPLICATION;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
@@ -60,7 +73,9 @@
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_IMMERSIVE;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
@@ -69,10 +84,13 @@
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.ActivityManagerService.ALLOW_FULL_ONLY;
+import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static com.android.server.am.ActivityManagerService.ANIMATE;
-import static com.android.server.am.ActivityManagerService.DISPATCH_SCREEN_KEYGUARD_MSG;
+import static com.android.server.am.ActivityManagerService.MY_PID;
+import static com.android.server.am.ActivityManagerService.SEND_LOCALE_TO_MOUNT_DAEMON_MSG;
import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS;
+import static com.android.server.am.ActivityManagerService.UPDATE_CONFIGURATION_MSG;
+import static com.android.server.am.ActivityManagerService.checkComponentPermission;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_ONLY;
@@ -88,14 +106,17 @@
import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManagerInternal;
import android.app.AppGlobals;
+import android.app.IActivityController;
import android.app.IActivityTaskManager;
import android.app.IApplicationThread;
import android.app.IAssistDataReceiver;
@@ -108,17 +129,21 @@
import android.app.admin.DevicePolicyCache;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
+import android.app.servertransaction.ConfigurationChangeItem;
import android.app.usage.UsageEvents;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.IIntentSender;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Point;
import android.graphics.Rect;
@@ -134,21 +159,29 @@
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
-import android.os.TransactionTooLargeException;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.os.UpdateLock;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.voice.IVoiceInteractionSession;
import android.service.voice.VoiceInteractionManagerInternal;
import android.telecom.TelecomManager;
import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.EventLog;
+import android.util.Log;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.SparseIntArray;
+import android.util.StatsLog;
import android.util.proto.ProtoOutputStream;
import android.view.IRecentsAnimationRunner;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationDefinition;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.AssistUtils;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.logging.MetricsLogger;
@@ -157,6 +190,7 @@
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.KeyguardDismissCallback;
import com.android.internal.util.Preconditions;
+import com.android.server.AttributeCache;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.Watchdog;
@@ -166,6 +200,7 @@
import java.io.File;
import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
@@ -182,10 +217,13 @@
private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
+ private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
Context mContext;
H mH;
+ UiHandler mUiHandler;
ActivityManagerService mAm;
+ ActivityManagerInternal mAmInternal;
/* Global service lock used by the package the owns this service. */
Object mGlobalLock;
ActivityStackSupervisor mStackSupervisor;
@@ -245,14 +283,77 @@
}
/** Current sequencing integer of the configuration, for skipping old configurations. */
- int mConfigurationSeq;
+ private int mConfigurationSeq;
+ // To cache the list of supported system locales
+ private String[] mSupportedSystemLocales = null;
/**
* Temp object used when global and/or display override configuration is updated. It is also
* sent to outer world instead of {@link #getGlobalConfiguration} because we don't trust
* anyone...
*/
- Configuration mTempConfig = new Configuration();
+ private Configuration mTempConfig = new Configuration();
+
+ // Amount of time after a call to stopAppSwitches() during which we will
+ // prevent further untrusted switches from happening.
+ private static final long APP_SWITCH_DELAY_TIME = 5 * 1000;
+
+ /**
+ * The time at which we will allow normal application switches again,
+ * after a call to {@link #stopAppSwitches()}.
+ */
+ long mAppSwitchesAllowedTime;
+ /**
+ * This is set to true after the first switch after mAppSwitchesAllowedTime
+ * is set; any switches after that will clear the time.
+ */
+ boolean mDidAppSwitch;
+
+ IActivityController mController = null;
+ boolean mControllerIsAMonkey = false;
+
+ /**
+ * Used to retain an update lock when the foreground activity is in
+ * immersive mode.
+ */
+ final UpdateLock mUpdateLock = new UpdateLock("immersive");
+
+ /**
+ * Packages that are being allowed to perform unrestricted app switches. Mapping is
+ * User -> Type -> uid.
+ */
+ final SparseArray<ArrayMap<String, Integer>> mAllowAppSwitchUids = new SparseArray<>();
+
+ /** The dimensions of the thumbnails in the Recents UI. */
+ int mThumbnailWidth;
+ int mThumbnailHeight;
+ float mFullscreenThumbnailScale;
+
+ /**
+ * Flag that indicates if multi-window is enabled.
+ *
+ * For any particular form of multi-window to be enabled, generic multi-window must be enabled
+ * in {@link com.android.internal.R.bool#config_supportsMultiWindow} config or
+ * {@link Settings.Global#DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES} development option set.
+ * At least one of the forms of multi-window must be enabled in order for this flag to be
+ * initialized to 'true'.
+ *
+ * @see #mSupportsSplitScreenMultiWindow
+ * @see #mSupportsFreeformWindowManagement
+ * @see #mSupportsPictureInPicture
+ * @see #mSupportsMultiDisplay
+ */
+ boolean mSupportsMultiWindow;
+ boolean mSupportsSplitScreenMultiWindow;
+ boolean mSupportsFreeformWindowManagement;
+ boolean mSupportsPictureInPicture;
+ boolean mSupportsMultiDisplay;
+ boolean mForceResizableActivities;
+
+ final List<ActivityTaskManagerInternal.ScreenObserver> mScreenObservers = new ArrayList<>();
+
+ // VR Vr2d Display Id.
+ int mVr2dDisplayId = INVALID_DISPLAY;
ActivityTaskManagerService(Context context) {
mContext = context;
@@ -265,11 +366,87 @@
mRecentTasks.onSystemReadyLocked();
}
+ void retrieveSettings(ContentResolver resolver) {
+ final boolean freeformWindowManagement =
+ mContext.getPackageManager().hasSystemFeature(FEATURE_FREEFORM_WINDOW_MANAGEMENT)
+ || Settings.Global.getInt(
+ resolver, DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0;
+
+ final boolean supportsMultiWindow = ActivityTaskManager.supportsMultiWindow(mContext);
+ final boolean supportsPictureInPicture = supportsMultiWindow &&
+ mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
+ final boolean supportsSplitScreenMultiWindow =
+ ActivityTaskManager.supportsSplitScreenMultiWindow(mContext);
+ final boolean supportsMultiDisplay = mContext.getPackageManager()
+ .hasSystemFeature(FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS);
+ final boolean alwaysFinishActivities =
+ Settings.Global.getInt(resolver, ALWAYS_FINISH_ACTIVITIES, 0) != 0;
+ final boolean forceRtl = Settings.Global.getInt(resolver, DEVELOPMENT_FORCE_RTL, 0) != 0;
+ final boolean forceResizable = Settings.Global.getInt(
+ resolver, DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, 0) != 0;
+
+ // Transfer any global setting for forcing RTL layout, into a System Property
+ SystemProperties.set(DEVELOPMENT_FORCE_RTL, forceRtl ? "1":"0");
+
+ final Configuration configuration = new Configuration();
+ Settings.System.getConfiguration(resolver, configuration);
+ if (forceRtl) {
+ // This will take care of setting the correct layout direction flags
+ configuration.setLayoutDirection(configuration.locale);
+ }
+
+ synchronized (mGlobalLock) {
+ mForceResizableActivities = forceResizable;
+ final boolean multiWindowFormEnabled = freeformWindowManagement
+ || supportsSplitScreenMultiWindow
+ || supportsPictureInPicture
+ || supportsMultiDisplay;
+ if ((supportsMultiWindow || forceResizable) && multiWindowFormEnabled) {
+ mSupportsMultiWindow = true;
+ mSupportsFreeformWindowManagement = freeformWindowManagement;
+ mSupportsSplitScreenMultiWindow = supportsSplitScreenMultiWindow;
+ mSupportsPictureInPicture = supportsPictureInPicture;
+ mSupportsMultiDisplay = supportsMultiDisplay;
+ } else {
+ mSupportsMultiWindow = false;
+ mSupportsFreeformWindowManagement = false;
+ mSupportsSplitScreenMultiWindow = false;
+ mSupportsPictureInPicture = false;
+ mSupportsMultiDisplay = false;
+ }
+ mWindowManager.setForceResizableTasks(mForceResizableActivities);
+ mWindowManager.setSupportsPictureInPicture(mSupportsPictureInPicture);
+ // This happens before any activities are started, so we can change global configuration
+ // in-place.
+ updateConfigurationLocked(configuration, null, true);
+ final Configuration globalConfig = getGlobalConfiguration();
+ if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Initial config: " + globalConfig);
+
+ // Load resources only after the current configuration has been set.
+ final Resources res = mContext.getResources();
+ mThumbnailWidth = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.thumbnail_width);
+ mThumbnailHeight = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.thumbnail_height);
+
+ if ((globalConfig.uiMode & UI_MODE_TYPE_TELEVISION) == UI_MODE_TYPE_TELEVISION) {
+ mFullscreenThumbnailScale = (float) res
+ .getInteger(com.android.internal.R.integer.thumbnail_width_tv) /
+ (float) globalConfig.screenWidthDp;
+ } else {
+ mFullscreenThumbnailScale = res.getFraction(
+ com.android.internal.R.fraction.thumbnail_fullscreen_scale, 1, 1);
+ }
+ }
+ }
+
// TODO: Will be converted to WM lock once transition is complete.
void setActivityManagerService(ActivityManagerService am) {
mAm = am;
+ mAmInternal = LocalServices.getService(ActivityManagerInternal.class);
mGlobalLock = mAm;
mH = new H(mAm.mHandlerThread.getLooper());
+ mUiHandler = new UiHandler();
mTempConfig.setToDefaults();
mTempConfig.setLocales(LocaleList.getDefault());
@@ -278,12 +455,12 @@
mStackSupervisor.onConfigurationChanged(mTempConfig);
mTaskChangeNotificationController =
- new TaskChangeNotificationController(mAm, mStackSupervisor, mH);
+ new TaskChangeNotificationController(mGlobalLock, mStackSupervisor, mH);
mLockTaskController = new LockTaskController(mContext, mStackSupervisor, mH);
mActivityStartController = new ActivityStartController(this);
mRecentTasks = createRecentTasks();
mStackSupervisor.setRecentTasks(mRecentTasks);
- mVrController = new VrController(mAm);
+ mVrController = new VrController(mGlobalLock);
mKeyguardController = mStackSupervisor.getKeyguardController();
}
@@ -359,9 +536,8 @@
Intent[] intents, String[] resolvedTypes, IBinder resultTo, Bundle bOptions,
int userId) {
final String reason = "startActivities";
- mAm.enforceNotIsolatedCaller(reason);
- userId = mAm.mUserController.handleIncomingUser(Binder.getCallingPid(),
- Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, reason, null);
+ enforceNotIsolatedCaller(reason);
+ userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, reason);
// TODO: Switch to user app stacks here.
return getActivityStartController().startActivities(caller, -1, callingPackage, intents,
resolvedTypes, resultTo, SafeActivityOptions.fromBundle(bOptions), userId, reason);
@@ -380,7 +556,7 @@
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
boolean validateIncomingUser) {
- mAm.enforceNotIsolatedCaller("startActivityAsUser");
+ enforceNotIsolatedCaller("startActivityAsUser");
userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
@@ -404,9 +580,8 @@
@Override
public int startActivityIntentSender(IApplicationThread caller, IIntentSender target,
IBinder whitelistToken, Intent fillInIntent, String resolvedType, IBinder resultTo,
- String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle bOptions)
- throws TransactionTooLargeException {
- mAm.enforceNotIsolatedCaller("startActivityIntentSender");
+ String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle bOptions) {
+ enforceNotIsolatedCaller("startActivityIntentSender");
// Refuse possible leaked file descriptors
if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -421,15 +596,14 @@
synchronized (mGlobalLock) {
// If this is coming from the currently resumed activity, it is
// effectively saying that app switches are allowed at this point.
- final ActivityStack stack = mAm.getFocusedStack();
+ final ActivityStack stack = getFocusedStack();
if (stack.mResumedActivity != null &&
stack.mResumedActivity.info.applicationInfo.uid == Binder.getCallingUid()) {
- mAm.mAppSwitchesAllowedTime = 0;
+ mAppSwitchesAllowedTime = 0;
}
}
- int ret = pir.sendInner(0, fillInIntent, resolvedType, whitelistToken, null, null,
+ return pir.sendInner(0, fillInIntent, resolvedType, whitelistToken, null, null,
resultTo, resultWho, requestCode, flagsMask, flagsValues, bOptions);
- return ret;
}
@Override
@@ -556,10 +730,9 @@
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
final WaitResult res = new WaitResult();
synchronized (mGlobalLock) {
- mAm.enforceNotIsolatedCaller("startActivityAndWait");
- userId = mAm.mUserController.handleIncomingUser(Binder.getCallingPid(),
- Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY,
- "startActivityAndWait", null);
+ enforceNotIsolatedCaller("startActivityAndWait");
+ userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, "startActivityAndWait");
// TODO: Switch to user app stacks here.
getActivityStartController().obtainStarter(intent, "startActivityAndWait")
.setCaller(caller)
@@ -583,10 +756,9 @@
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, Configuration config, Bundle bOptions, int userId) {
synchronized (mGlobalLock) {
- mAm.enforceNotIsolatedCaller("startActivityWithConfig");
- userId = mAm.mUserController.handleIncomingUser(Binder.getCallingPid(),
- Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY,
- "startActivityWithConfig", null);
+ enforceNotIsolatedCaller("startActivityWithConfig");
+ userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
+ "startActivityWithConfig");
// TODO: Switch to user app stacks here.
return getActivityStartController().obtainStarter(intent, "startActivityWithConfig")
.setCaller(caller)
@@ -692,17 +864,21 @@
}
}
+ int handleIncomingUser(int callingPid, int callingUid, int userId, String name) {
+ return mAmInternal.handleIncomingUser(callingPid, callingUid, userId, false /* allowAll */,
+ ALLOW_FULL_ONLY, name, null /* callerPackage */);
+ }
+
@Override
public int startVoiceActivity(String callingPackage, int callingPid, int callingUid,
Intent intent, String resolvedType, IVoiceInteractionSession session,
IVoiceInteractor interactor, int startFlags, ProfilerInfo profilerInfo,
Bundle bOptions, int userId) {
- mAm.enforceCallingPermission(BIND_VOICE_INTERACTION, "startVoiceActivity()");
+ mAmInternal.enforceCallingPermission(BIND_VOICE_INTERACTION, "startVoiceActivity()");
if (session == null || interactor == null) {
throw new NullPointerException("null session or interactor");
}
- userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
- ALLOW_FULL_ONLY, "startVoiceActivity", null);
+ userId = handleIncomingUser(callingPid, callingUid, userId, "startVoiceActivity");
// TODO: Switch to user app stacks here.
return getActivityStartController().obtainStarter(intent, "startVoiceActivity")
.setCallingUid(callingUid)
@@ -720,9 +896,8 @@
@Override
public int startAssistantActivity(String callingPackage, int callingPid, int callingUid,
Intent intent, String resolvedType, Bundle bOptions, int userId) {
- mAm.enforceCallingPermission(BIND_VOICE_INTERACTION, "startAssistantActivity()");
- userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
- ALLOW_FULL_ONLY, "startAssistantActivity", null);
+ mAmInternal.enforceCallingPermission(BIND_VOICE_INTERACTION, "startAssistantActivity()");
+ userId = handleIncomingUser(callingPid, callingUid, userId, "startAssistantActivity");
return getActivityStartController().obtainStarter(intent, "startAssistantActivity")
.setCallingUid(callingUid)
@@ -736,7 +911,7 @@
@Override
public void startRecentsActivity(Intent intent, IAssistDataReceiver assistDataReceiver,
IRecentsAnimationRunner recentsAnimationRunner) {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "startRecentsActivity()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "startRecentsActivity()");
final int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
try {
@@ -745,9 +920,8 @@
final int recentsUid = mRecentTasks.getRecentsComponentUid();
// Start a new recents animation
- final RecentsAnimation anim = new RecentsAnimation(mAm, mStackSupervisor,
- getActivityStartController(), mAm.mWindowManager, mAm.mUserController,
- callingPid);
+ final RecentsAnimation anim = new RecentsAnimation(this, mStackSupervisor,
+ getActivityStartController(), mWindowManager, callingPid);
anim.startRecentsActivity(intent, recentsAnimationRunner, recentsComponent,
recentsUid, assistDataReceiver);
}
@@ -758,7 +932,7 @@
@Override
public final int startActivityFromRecents(int taskId, Bundle bOptions) {
- mAm.enforceCallerIsRecentsOrHasPermission(START_TASKS_FROM_RECENTS,
+ enforceCallerIsRecentsOrHasPermission(START_TASKS_FROM_RECENTS,
"startActivityFromRecents()");
final int callingPid = Binder.getCallingPid();
@@ -810,16 +984,18 @@
return false;
}
- if (mAm.mController != null) {
+ // TODO: There is a dup. of this block of code in ActivityStack.navigateUpToLocked
+ // We should consolidate.
+ if (mController != null) {
// Find the first activity that is not finishing.
ActivityRecord next = r.getStack().topRunningActivityLocked(token, 0);
if (next != null) {
// ask watcher if this is allowed
boolean resumeOK = true;
try {
- resumeOK = mAm.mController.activityResuming(next.packageName);
+ resumeOK = mController.activityResuming(next.packageName);
} catch (RemoteException e) {
- mAm.mController = null;
+ mController = null;
Watchdog.getInstance().setActivityController(null);
}
@@ -907,7 +1083,7 @@
final long origId = Binder.clearCallingIdentity();
synchronized (mGlobalLock) {
ActivityRecord.activityResumedLocked(token);
- mAm.mWindowManager.notifyAppResumedFinished(token);
+ mWindowManager.notifyAppResumedFinished(token);
}
Binder.restoreCallingIdentity(origId);
}
@@ -943,7 +1119,7 @@
}
}
- mAm.trimApplications();
+ mAmInternal.trimApplications();
Binder.restoreCallingIdentity(origId);
}
@@ -1022,11 +1198,30 @@
// update associated state if we're frontmost
if (r == mStackSupervisor.getResumedActivityLocked()) {
if (DEBUG_IMMERSIVE) Slog.d(TAG_IMMERSIVE, "Frontmost changed immersion: "+ r);
- mAm.applyUpdateLockStateLocked(r);
+ applyUpdateLockStateLocked(r);
}
}
}
+ void applyUpdateLockStateLocked(ActivityRecord r) {
+ // Modifications to the UpdateLock state are done on our handler, outside
+ // the activity manager's locks. The new state is determined based on the
+ // state *now* of the relevant activity record. The object is passed to
+ // the handler solely for logging detail, not to be consulted/modified.
+ final boolean nextState = r != null && r.immersive;
+ mH.post(() -> {
+ if (mUpdateLock.isHeld() != nextState) {
+ if (DEBUG_IMMERSIVE) Slog.d(TAG_IMMERSIVE,
+ "Applying new update lock state '" + nextState + "' for " + r);
+ if (nextState) {
+ mUpdateLock.acquire();
+ } else {
+ mUpdateLock.release();
+ }
+ }
+ });
+ }
+
@Override
public boolean isImmersive(IBinder token) {
synchronized (mGlobalLock) {
@@ -1040,9 +1235,9 @@
@Override
public boolean isTopActivityImmersive() {
- mAm.enforceNotIsolatedCaller("isTopActivityImmersive");
+ enforceNotIsolatedCaller("isTopActivityImmersive");
synchronized (mGlobalLock) {
- final ActivityRecord r = mAm.getFocusedStack().topRunningActivityLocked();
+ final ActivityRecord r = getFocusedStack().topRunningActivityLocked();
return (r != null) ? r.immersive : false;
}
}
@@ -1060,7 +1255,7 @@
if (self.isState(
ActivityStack.ActivityState.RESUMED, ActivityStack.ActivityState.PAUSING)) {
- mAm.mWindowManager.overridePendingAppTransition(packageName,
+ mWindowManager.overridePendingAppTransition(packageName,
enterAnim, exitAnim, null);
}
@@ -1070,19 +1265,34 @@
@Override
public int getFrontActivityScreenCompatMode() {
- mAm.enforceNotIsolatedCaller("getFrontActivityScreenCompatMode");
+ enforceNotIsolatedCaller("getFrontActivityScreenCompatMode");
+ ApplicationInfo ai;
synchronized (mGlobalLock) {
- return mAm.mCompatModePackages.getFrontActivityScreenCompatModeLocked();
+ final ActivityRecord r = getFocusedStack().topRunningActivityLocked();
+ if (r == null) {
+ return ActivityManager.COMPAT_MODE_UNKNOWN;
+ }
+ ai = r.info.applicationInfo;
}
+
+ return mAmInternal.getPackageScreenCompatMode(ai);
}
@Override
public void setFrontActivityScreenCompatMode(int mode) {
- mAm.enforceCallingPermission(android.Manifest.permission.SET_SCREEN_COMPATIBILITY,
+ mAmInternal.enforceCallingPermission(android.Manifest.permission.SET_SCREEN_COMPATIBILITY,
"setFrontActivityScreenCompatMode");
+ ApplicationInfo ai;
synchronized (mGlobalLock) {
- mAm.mCompatModePackages.setFrontActivityScreenCompatModeLocked(mode);
+ final ActivityRecord r = getFocusedStack().topRunningActivityLocked();
+ if (r == null) {
+ Slog.w(TAG, "setFrontActivityScreenCompatMode failed: no top activity");
+ return;
+ }
+ ai = r.info.applicationInfo;
}
+
+ mAmInternal.setPackageScreenCompatMode(ai, mode);
}
@Override
@@ -1122,7 +1332,7 @@
if (translucentChanged) {
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
- mAm.mWindowManager.setAppFullscreen(token, true);
+ mWindowManager.setAppFullscreen(token, true);
return translucentChanged;
}
} finally {
@@ -1151,7 +1361,7 @@
r.getStack().convertActivityToTranslucent(r);
}
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
- mAm.mWindowManager.setAppFullscreen(token, false);
+ mWindowManager.setAppFullscreen(token, false);
return translucentChanged;
}
} finally {
@@ -1194,11 +1404,11 @@
@Override
public ActivityManager.StackInfo getFocusedStackInfo() throws RemoteException {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
- ActivityStack focusedStack = mAm.getFocusedStack();
+ ActivityStack focusedStack = getFocusedStack();
if (focusedStack != null) {
return mStackSupervisor.getStackInfo(focusedStack.mStackId);
}
@@ -1211,7 +1421,7 @@
@Override
public void setFocusedStack(int stackId) {
- mAm.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "setFocusedStack()");
+ mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "setFocusedStack()");
if (DEBUG_FOCUS) Slog.d(TAG_FOCUS, "setFocusedStack: stackId=" + stackId);
final long callingId = Binder.clearCallingIdentity();
try {
@@ -1234,7 +1444,7 @@
@Override
public void setFocusedTask(int taskId) {
- mAm.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "setFocusedTask()");
+ mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "setFocusedTask()");
if (DEBUG_FOCUS) Slog.d(TAG_FOCUS, "setFocusedTask: taskId=" + taskId);
final long callingId = Binder.clearCallingIdentity();
try {
@@ -1255,7 +1465,7 @@
@Override
public boolean removeTask(int taskId) {
- mAm.enforceCallerIsRecentsOrHasPermission(REMOVE_TASKS, "removeTask()");
+ enforceCallerIsRecentsOrHasPermission(REMOVE_TASKS, "removeTask()");
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
try {
@@ -1312,7 +1522,7 @@
*/
@Override
public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
- mAm.enforceNotIsolatedCaller("moveActivityTaskToBack");
+ enforceNotIsolatedCaller("moveActivityTaskToBack");
synchronized (mGlobalLock) {
final long origId = Binder.clearCallingIdentity();
try {
@@ -1330,7 +1540,7 @@
@Override
public Rect getTaskBounds(int taskId) {
- mAm.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "getTaskBounds()");
+ mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "getTaskBounds()");
long ident = Binder.clearCallingIdentity();
Rect rect = new Rect();
try {
@@ -1364,7 +1574,7 @@
@Override
public ActivityManager.TaskDescription getTaskDescription(int id) {
synchronized (mGlobalLock) {
- mAm.enforceCallerIsRecentsOrHasPermission(
+ enforceCallerIsRecentsOrHasPermission(
MANAGE_ACTIVITY_STACKS, "getTaskDescription()");
final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(id,
MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
@@ -1382,7 +1592,7 @@
toTop, ANIMATE, null /* initialBounds */, true /* showRecents */);
return;
}
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "setTaskWindowingMode()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "setTaskWindowingMode()");
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
try {
@@ -1414,7 +1624,7 @@
@Override
public String getCallingPackage(IBinder token) {
- synchronized (this) {
+ synchronized (mGlobalLock) {
ActivityRecord r = getCallingRecordLocked(token);
return r != null ? r.info.packageName : null;
}
@@ -1422,7 +1632,7 @@
@Override
public ComponentName getCallingActivity(IBinder token) {
- synchronized (this) {
+ synchronized (mGlobalLock) {
ActivityRecord r = getCallingRecordLocked(token);
return r != null ? r.intent.getComponent() : null;
}
@@ -1438,12 +1648,12 @@
@Override
public void unhandledBack() {
- mAm.enforceCallingPermission(android.Manifest.permission.FORCE_BACK, "unhandledBack()");
+ mAmInternal.enforceCallingPermission(android.Manifest.permission.FORCE_BACK, "unhandledBack()");
synchronized (mGlobalLock) {
final long origId = Binder.clearCallingIdentity();
try {
- mAm.getFocusedStack().unhandledBackLocked();
+ getFocusedStack().unhandledBackLocked();
} finally {
Binder.restoreCallingIdentity(origId);
}
@@ -1455,7 +1665,7 @@
*/
@Override
public void moveTaskToFront(int taskId, int flags, Bundle bOptions) {
- mAm.enforceCallingPermission(android.Manifest.permission.REORDER_TASKS, "moveTaskToFront()");
+ mAmInternal.enforceCallingPermission(android.Manifest.permission.REORDER_TASKS, "moveTaskToFront()");
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToFront: moving taskId=" + taskId);
synchronized (mGlobalLock) {
@@ -1467,7 +1677,7 @@
void moveTaskToFrontLocked(int taskId, int flags, SafeActivityOptions options,
boolean fromRecents) {
- if (!mAm.checkAppSwitchAllowedLocked(Binder.getCallingPid(),
+ if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
Binder.getCallingUid(), -1, -1, "Task to front")) {
SafeActivityOptions.abort(options);
return;
@@ -1503,6 +1713,69 @@
SafeActivityOptions.abort(options);
}
+ boolean checkAppSwitchAllowedLocked(int sourcePid, int sourceUid,
+ int callingPid, int callingUid, String name) {
+ if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
+ return true;
+ }
+
+ if (getRecentTasks().isCallerRecents(sourceUid)) {
+ return true;
+ }
+
+ int perm = checkComponentPermission(STOP_APP_SWITCHES, sourcePid, sourceUid, -1, true);
+ if (perm == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+ if (checkAllowAppSwitchUid(sourceUid)) {
+ return true;
+ }
+
+ // If the actual IPC caller is different from the logical source, then
+ // also see if they are allowed to control app switches.
+ if (callingUid != -1 && callingUid != sourceUid) {
+ perm = checkComponentPermission(STOP_APP_SWITCHES, callingPid, callingUid, -1, true);
+ if (perm == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+ if (checkAllowAppSwitchUid(callingUid)) {
+ return true;
+ }
+ }
+
+ Slog.w(TAG, name + " request from " + sourceUid + " stopped");
+ return false;
+ }
+
+ private boolean checkAllowAppSwitchUid(int uid) {
+ ArrayMap<String, Integer> types = mAllowAppSwitchUids.get(UserHandle.getUserId(uid));
+ if (types != null) {
+ for (int i = types.size() - 1; i >= 0; i--) {
+ if (types.valueAt(i).intValue() == uid) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void setActivityController(IActivityController controller, boolean imAMonkey) {
+ mAmInternal.enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
+ "setActivityController()");
+ synchronized (mGlobalLock) {
+ mController = controller;
+ mControllerIsAMonkey = imAMonkey;
+ Watchdog.getInstance().setActivityController(controller);
+ }
+ }
+
+ boolean isControllerAMonkey() {
+ synchronized (mGlobalLock) {
+ return mController != null && mControllerIsAMonkey;
+ }
+ }
+
@Override
public int getTaskForActivity(IBinder token, boolean onlyRoot) {
synchronized (mGlobalLock) {
@@ -1525,7 +1798,7 @@
synchronized (mGlobalLock) {
if (DEBUG_ALL) Slog.v(TAG, "getTasks: max=" + maxNum);
- final boolean allowed = mAm.isGetTasksAllowed("getTasks", Binder.getCallingPid(),
+ final boolean allowed = isGetTasksAllowed("getTasks", Binder.getCallingPid(),
callingUid);
mStackSupervisor.getRunningTasks(maxNum, list, ignoreActivityType,
ignoreWindowingMode, callingUid, allowed);
@@ -1548,7 +1821,7 @@
@Override
public boolean willActivityBeVisible(IBinder token) {
- synchronized(this) {
+ synchronized (mGlobalLock) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
return stack.willActivityBeVisibleLocked(token);
@@ -1559,7 +1832,7 @@
@Override
public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToStack()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToStack()");
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
try {
@@ -1582,7 +1855,7 @@
+ taskId + " to stack " + stackId);
}
if (stack.inSplitScreenPrimaryWindowingMode()) {
- mAm.mWindowManager.setDockedStackCreateState(
+ mWindowManager.setDockedStackCreateState(
SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, null /* initialBounds */);
}
task.reparent(stack, toTop, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME,
@@ -1596,7 +1869,7 @@
@Override
public void resizeStack(int stackId, Rect destBounds, boolean allowResizeInDockedMode,
boolean preserveWindows, boolean animate, int animationDuration) {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizeStack()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizeStack()");
final long ident = Binder.clearCallingIdentity();
try {
@@ -1648,7 +1921,7 @@
@Override
public boolean setTaskWindowingModeSplitScreenPrimary(int taskId, int createMode,
boolean toTop, boolean animate, Rect initialBounds, boolean showRecents) {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
"setTaskWindowingModeSplitScreenPrimary()");
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
@@ -1666,7 +1939,7 @@
+ " non-standard task " + taskId + " to split-screen windowing mode");
}
- mAm.mWindowManager.setDockedStackCreateState(createMode, initialBounds);
+ mWindowManager.setDockedStackCreateState(createMode, initialBounds);
final int windowingMode = task.getWindowingMode();
final ActivityStack stack = task.getStack();
if (toTop) {
@@ -1687,7 +1960,7 @@
*/
@Override
public void removeStacksInWindowingModes(int[] windowingModes) {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
"removeStacksInWindowingModes()");
synchronized (mGlobalLock) {
@@ -1702,7 +1975,7 @@
@Override
public void removeStacksWithActivityTypes(int[] activityTypes) {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
"removeStacksWithActivityTypes()");
synchronized (mGlobalLock) {
@@ -1719,12 +1992,12 @@
public ParceledListSlice<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum, int flags,
int userId) {
final int callingUid = Binder.getCallingUid();
- userId = mAm.mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
- false, ALLOW_FULL_ONLY, "getRecentTasks", null);
- final boolean allowed = mAm.isGetTasksAllowed("getRecentTasks", Binder.getCallingPid(),
+ userId = handleIncomingUser(Binder.getCallingPid(), callingUid, userId, "getRecentTasks");
+ final boolean allowed = isGetTasksAllowed("getRecentTasks", Binder.getCallingPid(),
callingUid);
- final boolean detailed = mAm.checkCallingPermission(
- android.Manifest.permission.GET_DETAILED_TASKS)
+ final boolean detailed = checkGetTasksPermission(
+ android.Manifest.permission.GET_DETAILED_TASKS, Binder.getCallingPid(),
+ UserHandle.getAppId(callingUid))
== PackageManager.PERMISSION_GRANTED;
synchronized (mGlobalLock) {
@@ -1735,7 +2008,7 @@
@Override
public List<ActivityManager.StackInfo> getAllStackInfos() {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getAllStackInfos()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getAllStackInfos()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
@@ -1748,7 +2021,7 @@
@Override
public ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType) {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
@@ -1761,13 +2034,13 @@
@Override
public void cancelRecentsAnimation(boolean restoreHomeStackPosition) {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "cancelRecentsAnimation()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "cancelRecentsAnimation()");
final long callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
// Cancel the recents animation synchronously (do not hold the WM lock)
- mAm.mWindowManager.cancelRecentsAnimationSynchronously(restoreHomeStackPosition
+ mWindowManager.cancelRecentsAnimationSynchronously(restoreHomeStackPosition
? REORDER_MOVE_TO_ORIGINAL_POSITION
: REORDER_KEEP_IN_PLACE, "cancelRecentsAnimation/uid=" + callingUid);
}
@@ -1789,7 +2062,7 @@
@Override
public void startSystemLockTaskMode(int taskId) throws RemoteException {
- mAm.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "startSystemLockTaskMode");
+ mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "startSystemLockTaskMode");
// This makes inner call to look as if it was initiated by system.
long ident = Binder.clearCallingIdentity();
try {
@@ -1822,7 +2095,7 @@
*/
@Override
public void stopSystemLockTaskMode() throws RemoteException {
- mAm.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "stopSystemLockTaskMode");
+ mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "stopSystemLockTaskMode");
stopLockTaskModeInternal(null, true /* isSystemCaller */);
}
@@ -1979,7 +2252,7 @@
@Override
public void reportAssistContextExtras(IBinder token, Bundle extras, AssistStructure structure,
AssistContent content, Uri referrer) {
- PendingAssistExtras pae = (PendingAssistExtras)token;
+ PendingAssistExtras pae = (PendingAssistExtras) token;
synchronized (pae) {
pae.result = extras;
pae.structure = structure;
@@ -2003,13 +2276,13 @@
synchronized (mGlobalLock) {
buildAssistBundleLocked(pae, extras);
boolean exists = mPendingAssistExtras.remove(pae);
- mAm.mUiHandler.removeCallbacks(pae);
+ mUiHandler.removeCallbacks(pae);
if (!exists) {
// Timed out.
return;
}
- if ((sendReceiver=pae.receiver) != null) {
+ if ((sendReceiver = pae.receiver) != null) {
// Caller wants result sent back to them.
sendBundle = new Bundle();
sendBundle.putBundle(ASSIST_KEY_DATA, pae.extras);
@@ -2037,7 +2310,7 @@
pae.intent.setFlags(FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
- mAm.closeSystemDialogs("assist");
+ mAmInternal.closeSystemDialogs("assist");
try {
mContext.startActivityAsUser(pae.intent, new UserHandle(pae.userHandle));
@@ -2068,11 +2341,11 @@
throw new IllegalArgumentException("Intent " + intent
+ " must specify explicit component");
}
- if (thumbnail.getWidth() != mAm.mThumbnailWidth
- || thumbnail.getHeight() != mAm.mThumbnailHeight) {
+ if (thumbnail.getWidth() != mThumbnailWidth
+ || thumbnail.getHeight() != mThumbnailHeight) {
throw new IllegalArgumentException("Bad thumbnail size: got "
+ thumbnail.getWidth() + "x" + thumbnail.getHeight() + ", require "
- + mAm.mThumbnailWidth + "x" + mAm.mThumbnailHeight);
+ + mThumbnailWidth + "x" + mThumbnailHeight);
}
if (intent.getSelector() != null) {
intent.setSelector(null);
@@ -2118,7 +2391,7 @@
@Override
public Point getAppTaskThumbnailSize() {
synchronized (mGlobalLock) {
- return new Point(mAm.mThumbnailWidth, mAm.mThumbnailHeight);
+ return new Point(mThumbnailWidth, mThumbnailHeight);
}
}
@@ -2137,7 +2410,7 @@
@Override
public void resizeTask(int taskId, Rect bounds, int resizeMode) {
- mAm.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "resizeTask()");
+ mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "resizeTask()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
@@ -2215,7 +2488,7 @@
@Override
public void setLockScreenShown(boolean keyguardShowing, boolean aodShowing,
int secondaryDisplayShowing) {
- if (mAm.checkCallingPermission(android.Manifest.permission.DEVICE_POWER)
+ if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires permission "
+ android.Manifest.permission.DEVICE_POWER);
@@ -2235,14 +2508,25 @@
}
}
- mAm.mHandler.obtainMessage(DISPATCH_SCREEN_KEYGUARD_MSG, keyguardShowing ? 1 : 0, 0)
- .sendToTarget();
+ mH.post(() -> {
+ for (int i = mScreenObservers.size() - 1; i >= 0; i--) {
+ mScreenObservers.get(i).onKeyguardStateChanged(keyguardShowing);
+ }
+ });
+ }
+
+ void onScreenAwakeChanged(boolean isAwake) {
+ mH.post(() -> {
+ for (int i = mScreenObservers.size() - 1; i >= 0; i--) {
+ mScreenObservers.get(i).onAwakeStateChanged(isAwake);
+ }
+ });
}
@Override
public Bitmap getTaskDescriptionIcon(String filePath, int userId) {
- userId = mAm.mUserController.handleIncomingUser(Binder.getCallingPid(),
- Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "getTaskDescriptionIcon", null);
+ userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
+ userId, "getTaskDescriptionIcon");
final File passedIconFile = new File(filePath);
final File legitIconFile = new File(TaskPersister.getUserImagesDir(userId),
@@ -2256,8 +2540,7 @@
}
@Override
- public void startInPlaceAnimationOnFrontMostApplication(Bundle opts)
- throws RemoteException {
+ public void startInPlaceAnimationOnFrontMostApplication(Bundle opts) {
final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(opts);
final ActivityOptions activityOptions = safeOptions != null
? safeOptions.getOptions(mStackSupervisor)
@@ -2268,15 +2551,15 @@
throw new IllegalArgumentException("Expected in-place ActivityOption " +
"with valid animation");
}
- mAm.mWindowManager.prepareAppTransition(TRANSIT_TASK_IN_PLACE, false);
- mAm.mWindowManager.overridePendingAppTransitionInPlace(activityOptions.getPackageName(),
+ mWindowManager.prepareAppTransition(TRANSIT_TASK_IN_PLACE, false);
+ mWindowManager.overridePendingAppTransitionInPlace(activityOptions.getPackageName(),
activityOptions.getCustomInPlaceResId());
- mAm.mWindowManager.executeAppTransition();
+ mWindowManager.executeAppTransition();
}
@Override
public void removeStack(int stackId) {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "removeStack()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "removeStack()");
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
try {
@@ -2298,7 +2581,7 @@
@Override
public void moveStackToDisplay(int stackId, int displayId) {
- mAm.enforceCallingPermission(INTERNAL_SYSTEM_WINDOW, "moveStackToDisplay()");
+ mAmInternal.enforceCallingPermission(INTERNAL_SYSTEM_WINDOW, "moveStackToDisplay()");
synchronized (mGlobalLock) {
final long ident = Binder.clearCallingIdentity();
@@ -2314,7 +2597,7 @@
@Override
public int createStackOnDisplay(int displayId) {
- mAm.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "createStackOnDisplay()");
+ mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "createStackOnDisplay()");
synchronized (mGlobalLock) {
final ActivityDisplay display =
mStackSupervisor.getActivityDisplayOrCreateLocked(displayId);
@@ -2356,7 +2639,7 @@
/** Sets the task stack listener that gets callbacks when a task stack changes. */
@Override
public void registerTaskStackListener(ITaskStackListener listener) {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
"registerTaskStackListener()");
mTaskChangeNotificationController.registerTaskStackListener(listener);
}
@@ -2364,7 +2647,7 @@
/** Unregister a task stack listener so that it stops receiving callbacks. */
@Override
public void unregisterTaskStackListener(ITaskStackListener listener) {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
"unregisterTaskStackListener()");
mTaskChangeNotificationController.unregisterTaskStackListener(listener);
}
@@ -2418,20 +2701,78 @@
synchronized (mGlobalLock) {
buildAssistBundleLocked(pae, pae.result);
mPendingAssistExtras.remove(pae);
- mAm.mUiHandler.removeCallbacks(pae);
+ mUiHandler.removeCallbacks(pae);
}
return pae.extras;
}
+ /**
+ * Binder IPC calls go through the public entry point.
+ * This can be called with or without the global lock held.
+ */
+ private static int checkCallingPermission(String permission) {
+ return checkPermission(
+ permission, Binder.getCallingPid(), UserHandle.getAppId(Binder.getCallingUid()));
+ }
+
+ /** This can be called with or without the global lock held. */
+ void enforceCallerIsRecentsOrHasPermission(String permission, String func) {
+ if (!getRecentTasks().isCallerRecents(Binder.getCallingUid())) {
+ mAmInternal.enforceCallingPermission(permission, func);
+ }
+ }
+
+ @VisibleForTesting
+ int checkGetTasksPermission(String permission, int pid, int uid) {
+ return checkPermission(permission, pid, uid);
+ }
+
+ static int checkPermission(String permission, int pid, int uid) {
+ if (permission == null) {
+ return PackageManager.PERMISSION_DENIED;
+ }
+ return checkComponentPermission(permission, pid, uid, -1, true);
+ }
+
+ boolean isGetTasksAllowed(String caller, int callingPid, int callingUid) {
+ if (getRecentTasks().isCallerRecents(callingUid)) {
+ // Always allow the recents component to get tasks
+ return true;
+ }
+
+ boolean allowed = checkGetTasksPermission(android.Manifest.permission.REAL_GET_TASKS,
+ callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
+ if (!allowed) {
+ if (checkGetTasksPermission(android.Manifest.permission.GET_TASKS,
+ callingPid, callingUid) == PackageManager.PERMISSION_GRANTED) {
+ // Temporary compatibility: some existing apps on the system image may
+ // still be requesting the old permission and not switched to the new
+ // one; if so, we'll still allow them full access. This means we need
+ // to see if they are holding the old permission and are a system app.
+ try {
+ if (AppGlobals.getPackageManager().isUidPrivileged(callingUid)) {
+ allowed = true;
+ if (DEBUG_TASKS) Slog.w(TAG, caller + ": caller " + callingUid
+ + " is using old GET_TASKS but privileged; allowing");
+ }
+ } catch (RemoteException e) {
+ }
+ }
+ if (DEBUG_TASKS) Slog.w(TAG, caller + ": caller " + callingUid
+ + " does not hold REAL_GET_TASKS; limiting output");
+ }
+ return allowed;
+ }
+
private PendingAssistExtras enqueueAssistContext(int requestType, Intent intent, String hint,
IAssistDataReceiver receiver, Bundle receiverExtras, IBinder activityToken,
boolean focused, boolean newSessionId, int userHandle, Bundle args, long timeout,
int flags) {
- mAm.enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO,
+ mAmInternal.enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO,
"enqueueAssistContext()");
synchronized (mGlobalLock) {
- ActivityRecord activity = mAm.getFocusedStack().getTopActivity();
+ ActivityRecord activity = getFocusedStack().getTopActivity();
if (activity == null) {
Slog.w(TAG, "getAssistContextExtras failed: no top activity");
return null;
@@ -2482,7 +2823,7 @@
activity.app.thread.requestAssistContextExtras(activity.appToken, pae, requestType,
mViSessionId, flags);
mPendingAssistExtras.add(pae);
- mAm.mUiHandler.postDelayed(pae, timeout);
+ mUiHandler.postDelayed(pae, timeout);
} catch (RemoteException e) {
Slog.w(TAG, "getAssistContextExtras failed: crash calling " + activity);
return null;
@@ -2559,7 +2900,7 @@
public boolean isAssistDataAllowedOnCurrentActivity() {
int userId;
synchronized (mGlobalLock) {
- final ActivityStack focusedStack = mAm.getFocusedStack();
+ final ActivityStack focusedStack = getFocusedStack();
if (focusedStack == null || focusedStack.isActivityTypeAssistant()) {
return false;
}
@@ -2579,7 +2920,7 @@
try {
synchronized (mGlobalLock) {
ActivityRecord caller = ActivityRecord.forTokenLocked(token);
- ActivityRecord top = mAm.getFocusedStack().getTopActivity();
+ ActivityRecord top = getFocusedStack().getTopActivity();
if (top != caller) {
Slog.w(TAG, "showAssistFromActivity failed: caller " + caller
+ " is not current top " + top);
@@ -2644,7 +2985,7 @@
@Override
public void keyguardGoingAway(int flags) {
- mAm.enforceNotIsolatedCaller("keyguardGoingAway");
+ enforceNotIsolatedCaller("keyguardGoingAway");
final long token = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
@@ -2662,7 +3003,7 @@
*/
@Override
public void positionTaskInStack(int taskId, int stackId, int position) {
- mAm.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "positionTaskInStack()");
+ mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "positionTaskInStack()");
synchronized (mGlobalLock) {
long ident = Binder.clearCallingIdentity();
try {
@@ -2723,7 +3064,7 @@
*/
@Override
public void dismissSplitScreenMode(boolean toTop) {
- mAm.enforceCallerIsRecentsOrHasPermission(
+ enforceCallerIsRecentsOrHasPermission(
MANAGE_ACTIVITY_STACKS, "dismissSplitScreenMode()");
final long ident = Binder.clearCallingIdentity();
try {
@@ -2765,7 +3106,7 @@
*/
@Override
public void dismissPip(boolean animate, int animationDuration) {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "dismissPip()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "dismissPip()");
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
@@ -2793,7 +3134,7 @@
@Override
public void suppressResizeConfigChanges(boolean suppress) throws RemoteException {
- mAm.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "suppressResizeConfigChanges()");
+ mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "suppressResizeConfigChanges()");
synchronized (mGlobalLock) {
mSuppressResizeConfigChanges = suppress;
}
@@ -2807,7 +3148,7 @@
@Override
// TODO: API should just be about changing windowing modes...
public void moveTasksToFullscreenStack(int fromStackId, boolean onTop) {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
"moveTasksToFullscreenStack()");
synchronized (mGlobalLock) {
final long origId = Binder.clearCallingIdentity();
@@ -2837,10 +3178,10 @@
*/
@Override
public boolean moveTopActivityToPinnedStack(int stackId, Rect bounds) {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
"moveTopActivityToPinnedStack()");
synchronized (mGlobalLock) {
- if (!mAm.mSupportsPictureInPicture) {
+ if (!mSupportsPictureInPicture) {
throw new IllegalStateException("moveTopActivityToPinnedStack:"
+ "Device doesn't support picture-in-picture mode");
}
@@ -2942,8 +3283,8 @@
// device is currently locked).
dismissKeyguard(token, new KeyguardDismissCallback() {
@Override
- public void onDismissSucceeded() throws RemoteException {
- mAm.mHandler.post(enterPipRunnable);
+ public void onDismissSucceeded() {
+ mH.post(enterPipRunnable);
}
}, null /* message */);
} else {
@@ -3012,7 +3353,7 @@
*/
private ActivityRecord ensureValidPictureInPictureActivityParamsLocked(String caller,
IBinder token, PictureInPictureParams params) {
- if (!mAm.mSupportsPictureInPicture) {
+ if (!mSupportsPictureInPicture) {
throw new IllegalStateException(caller
+ ": Device doesn't support picture-in-picture mode.");
}
@@ -3029,7 +3370,7 @@
}
if (params.hasSetAspectRatio()
- && !mAm.mWindowManager.isValidPictureInPictureAspectRatio(r.getStack().mDisplayId,
+ && !mWindowManager.isValidPictureInPictureAspectRatio(r.getStack().mDisplayId,
params.getAspectRatio())) {
final float minAspectRatio = mContext.getResources().getFloat(
com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
@@ -3048,7 +3389,7 @@
@Override
public IBinder getUriPermissionOwnerForActivity(IBinder activityToken) {
- mAm.enforceNotIsolatedCaller("getUriPermissionOwnerForActivity");
+ enforceNotIsolatedCaller("getUriPermissionOwnerForActivity");
synchronized (mGlobalLock) {
ActivityRecord r = ActivityRecord.isInStackLocked(activityToken);
if (r == null) {
@@ -3063,7 +3404,7 @@
public void resizeDockedStack(Rect dockedBounds, Rect tempDockedTaskBounds,
Rect tempDockedTaskInsetBounds,
Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds) {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizeDockedStack()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizeDockedStack()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
@@ -3078,7 +3419,7 @@
@Override
public void setSplitScreenResizing(boolean resizing) {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "setSplitScreenResizing()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "setSplitScreenResizing()");
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
@@ -3089,9 +3430,20 @@
}
}
+ /**
+ * Check that we have the features required for VR-related API calls, and throw an exception if
+ * not.
+ */
+ void enforceSystemHasVrFeature() {
+ if (!mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE)) {
+ throw new UnsupportedOperationException("VR mode not supported on this device!");
+ }
+ }
+
@Override
public int setVrMode(IBinder token, boolean enabled, ComponentName packageName) {
- mAm.enforceSystemHasVrFeature();
+ enforceSystemHasVrFeature();
final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
@@ -3131,7 +3483,7 @@
public void startLocalVoiceInteraction(IBinder callingActivity, Bundle options) {
Slog.i(TAG, "Activity tried to startLocalVoiceInteraction");
synchronized (mGlobalLock) {
- ActivityRecord activity = mAm.getFocusedStack().getTopActivity();
+ ActivityRecord activity = getFocusedStack().getTopActivity();
if (ActivityRecord.forTokenLocked(callingActivity) != activity) {
throw new SecurityException("Only focused activity can call startVoiceInteraction");
}
@@ -3176,7 +3528,7 @@
@Override
public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizePinnedStack()");
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizePinnedStack()");
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mGlobalLock) {
@@ -3189,7 +3541,7 @@
@Override
public boolean updateDisplayOverrideConfiguration(Configuration values, int displayId) {
- mAm.enforceCallingPermission(CHANGE_CONFIGURATION, "updateDisplayOverrideConfiguration()");
+ mAmInternal.enforceCallingPermission(CHANGE_CONFIGURATION, "updateDisplayOverrideConfiguration()");
synchronized (mGlobalLock) {
// Check if display is initialized in AM.
@@ -3202,14 +3554,14 @@
return false;
}
- if (values == null && mAm.mWindowManager != null) {
+ if (values == null && mWindowManager != null) {
// sentinel: fetch the current configuration from the window manager
- values = mAm.mWindowManager.computeNewConfiguration(displayId);
+ values = mWindowManager.computeNewConfiguration(displayId);
}
- if (mAm.mWindowManager != null) {
+ if (mWindowManager != null) {
// Update OOM levels based on display size.
- mAm.mProcessList.applyDisplaySize(mAm.mWindowManager);
+ mAm.mProcessList.applyDisplaySize(mWindowManager);
}
final long origId = Binder.clearCallingIdentity();
@@ -3217,7 +3569,7 @@
if (values != null) {
Settings.System.clearConfiguration(values);
}
- mAm.updateDisplayOverrideConfigurationLocked(values, null /* starting */,
+ updateDisplayOverrideConfigurationLocked(values, null /* starting */,
false /* deferResume */, displayId, mTmpUpdateConfigurationResult);
return mTmpUpdateConfigurationResult.changes != 0;
} finally {
@@ -3228,17 +3580,17 @@
@Override
public boolean updateConfiguration(Configuration values) {
- mAm.enforceCallingPermission(CHANGE_CONFIGURATION, "updateConfiguration()");
+ mAmInternal.enforceCallingPermission(CHANGE_CONFIGURATION, "updateConfiguration()");
synchronized (mGlobalLock) {
- if (values == null && mAm.mWindowManager != null) {
+ if (values == null && mWindowManager != null) {
// sentinel: fetch the current configuration from the window manager
- values = mAm.mWindowManager.computeNewConfiguration(DEFAULT_DISPLAY);
+ values = mWindowManager.computeNewConfiguration(DEFAULT_DISPLAY);
}
- if (mAm.mWindowManager != null) {
+ if (mWindowManager != null) {
// Update OOM levels based on display size.
- mAm.mProcessList.applyDisplaySize(mAm.mWindowManager);
+ mAm.mProcessList.applyDisplaySize(mWindowManager);
}
final long origId = Binder.clearCallingIdentity();
@@ -3246,7 +3598,7 @@
if (values != null) {
Settings.System.clearConfiguration(values);
}
- mAm.updateConfigurationLocked(values, null, false, false /* persistent */,
+ updateConfigurationLocked(values, null, false, false /* persistent */,
UserHandle.USER_NULL, false /* deferResume */,
mTmpUpdateConfigurationResult);
return mTmpUpdateConfigurationResult.changes != 0;
@@ -3260,7 +3612,7 @@
public void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback,
CharSequence message) {
if (message != null) {
- mAm.enforceCallingPermission(
+ mAmInternal.enforceCallingPermission(
Manifest.permission.SHOW_KEYGUARD_MESSAGE, "dismissKeyguard()");
}
final long callingId = Binder.clearCallingIdentity();
@@ -3275,7 +3627,7 @@
@Override
public void cancelTaskWindowTransition(int taskId) {
- mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
+ enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
"cancelTaskWindowTransition()");
final long ident = Binder.clearCallingIdentity();
try {
@@ -3295,7 +3647,7 @@
@Override
public ActivityManager.TaskSnapshot getTaskSnapshot(int taskId, boolean reducedResolution) {
- mAm.enforceCallerIsRecentsOrHasPermission(READ_FRAME_BUFFER, "getTaskSnapshot()");
+ enforceCallerIsRecentsOrHasPermission(READ_FRAME_BUFFER, "getTaskSnapshot()");
final long ident = Binder.clearCallingIdentity();
try {
final TaskRecord task;
@@ -3336,11 +3688,11 @@
@Override
public @UserIdInt
int getLastResumedActivityUserId() {
- mAm.enforceCallingPermission(
+ mAmInternal.enforceCallingPermission(
Manifest.permission.INTERACT_ACROSS_USERS_FULL, "getLastResumedActivityUserId()");
synchronized (mGlobalLock) {
if (mAm.mLastResumedActivity == null) {
- return mAm.mUserController.getCurrentUserId();
+ return getCurrentUserId();
}
return mAm.mLastResumedActivity.userId;
}
@@ -3350,7 +3702,7 @@
public void updateLockTaskFeatures(int userId, int flags) {
final int callingUid = Binder.getCallingUid();
if (callingUid != 0 && callingUid != SYSTEM_UID) {
- mAm.enforceCallingPermission(android.Manifest.permission.UPDATE_LOCK_TASK_PACKAGES,
+ mAmInternal.enforceCallingPermission(android.Manifest.permission.UPDATE_LOCK_TASK_PACKAGES,
"updateLockTaskFeatures()");
}
synchronized (mGlobalLock) {
@@ -3394,7 +3746,7 @@
@Override
public void registerRemoteAnimations(IBinder token, RemoteAnimationDefinition definition) {
- mAm.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
+ mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
"registerRemoteAnimations");
definition.setCallingPid(Binder.getCallingPid());
synchronized (mGlobalLock) {
@@ -3414,7 +3766,7 @@
@Override
public void registerRemoteAnimationForNextActivityStart(String packageName,
RemoteAnimationAdapter adapter) {
- mAm.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
+ mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
"registerRemoteAnimationForNextActivityStart");
adapter.setCallingPid(Binder.getCallingPid());
synchronized (mGlobalLock) {
@@ -3443,7 +3795,7 @@
@Override
public void setVrThread(int tid) {
- mAm.enforceSystemHasVrFeature();
+ enforceSystemHasVrFeature();
synchronized (mGlobalLock) {
synchronized (mAm.mPidsSelfLocked) {
final int pid = Binder.getCallingPid();
@@ -3455,7 +3807,7 @@
@Override
public void setPersistentVrThread(int tid) {
- if (mAm.checkCallingPermission(Manifest.permission.RESTRICTED_VR_ACCESS)
+ if (checkCallingPermission(Manifest.permission.RESTRICTED_VR_ACCESS)
!= PERMISSION_GRANTED) {
final String msg = "Permission Denial: setPersistentVrThread() from pid="
+ Binder.getCallingPid()
@@ -3464,7 +3816,7 @@
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
- mAm.enforceSystemHasVrFeature();
+ enforceSystemHasVrFeature();
synchronized (mGlobalLock) {
synchronized (mAm.mPidsSelfLocked) {
final int pid = Binder.getCallingPid();
@@ -3474,9 +3826,41 @@
}
}
- /**
- * @return whether the system should disable UI modes incompatible with VR mode.
- */
+ @Override
+ public void stopAppSwitches() {
+ enforceCallerIsRecentsOrHasPermission(STOP_APP_SWITCHES, "stopAppSwitches");
+ synchronized (mGlobalLock) {
+ mAppSwitchesAllowedTime = SystemClock.uptimeMillis() + APP_SWITCH_DELAY_TIME;
+ mDidAppSwitch = false;
+ getActivityStartController().schedulePendingActivityLaunches(APP_SWITCH_DELAY_TIME);
+ }
+ }
+
+ @Override
+ public void resumeAppSwitches() {
+ enforceCallerIsRecentsOrHasPermission(STOP_APP_SWITCHES, "resumeAppSwitches");
+ synchronized (mGlobalLock) {
+ // Note that we don't execute any pending app switches... we will
+ // let those wait until either the timeout, or the next start
+ // activity request.
+ mAppSwitchesAllowedTime = 0;
+ }
+ }
+
+ void onStartActivitySetDidAppSwitch() {
+ if (mDidAppSwitch) {
+ // This is the second allowed switch since we stopped switches, so now just generally
+ // allow switches. Use case:
+ // - user presses home (switches disabled, switch to home, mDidAppSwitch now true);
+ // - user taps a home icon (coming from home so allowed, we hit here and now allow
+ // anyone to switch again).
+ mAppSwitchesAllowedTime = 0;
+ } else {
+ mDidAppSwitch = true;
+ }
+ }
+
+ /** @return whether the system should disable UI modes incompatible with VR mode. */
boolean shouldDisableNonVrUiLocked() {
return mVrController.shouldDisableNonVrUiLocked();
}
@@ -3512,6 +3896,10 @@
});
}
+ ActivityStack getFocusedStack() {
+ return mStackSupervisor.getFocusedStack();
+ }
+
/** Pokes the task persister. */
void notifyTaskPersisterLocked(TaskRecord task, boolean flush) {
mRecentTasks.notifyTaskPersisterLocked(task, flush);
@@ -3540,12 +3928,398 @@
mVrController.writeToProto(proto, fieldId);
}
+ int getCurrentUserId() {
+ return mAmInternal.getCurrentUserId();
+ }
+
+ private void enforceNotIsolatedCaller(String caller) {
+ if (UserHandle.isIsolated(Binder.getCallingUid())) {
+ throw new SecurityException("Isolated process not allowed to call " + caller);
+ }
+ }
+
+ /**
+ * Current global configuration information. Contains general settings for the entire system,
+ * also corresponds to the merged configuration of the default display.
+ */
+ Configuration getGlobalConfiguration() {
+ return mStackSupervisor.getConfiguration();
+ }
+
+ boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
+ boolean initLocale) {
+ return updateConfigurationLocked(values, starting, initLocale, false /* deferResume */);
+ }
+
+ boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
+ boolean initLocale, boolean deferResume) {
+ // pass UserHandle.USER_NULL as userId because we don't persist configuration for any user
+ return updateConfigurationLocked(values, starting, initLocale, false /* persistent */,
+ UserHandle.USER_NULL, deferResume);
+ }
+
+ void updatePersistentConfiguration(Configuration values, @UserIdInt int userId) {
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ updateConfigurationLocked(values, null, false, true, userId,
+ false /* deferResume */);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
+ void updateUserConfiguration() {
+ synchronized (mGlobalLock) {
+ final Configuration configuration = new Configuration(getGlobalConfiguration());
+ final int currentUserId = mAmInternal.getCurrentUserId();
+ Settings.System.adjustConfigurationForUser(mContext.getContentResolver(), configuration,
+ currentUserId, Settings.System.canWrite(mContext));
+ updateConfigurationLocked(configuration, null /* starting */, false /* initLocale */,
+ false /* persistent */, currentUserId, false /* deferResume */);
+ }
+ }
+
+ private boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
+ boolean initLocale, boolean persistent, int userId, boolean deferResume) {
+ return updateConfigurationLocked(values, starting, initLocale, persistent, userId,
+ deferResume, null /* result */);
+ }
+
+ /**
+ * Do either or both things: (1) change the current configuration, and (2)
+ * make sure the given activity is running with the (now) current
+ * configuration. Returns true if the activity has been left running, or
+ * false if <var>starting</var> is being destroyed to match the new
+ * configuration.
+ *
+ * @param userId is only used when persistent parameter is set to true to persist configuration
+ * for that particular user
+ */
+ boolean updateConfigurationLocked(Configuration values, ActivityRecord starting,
+ boolean initLocale, boolean persistent, int userId, boolean deferResume,
+ ActivityTaskManagerService.UpdateConfigurationResult result) {
+ int changes = 0;
+ boolean kept = true;
+
+ if (mWindowManager != null) {
+ mWindowManager.deferSurfaceLayout();
+ }
+ try {
+ if (values != null) {
+ changes = updateGlobalConfigurationLocked(values, initLocale, persistent, userId,
+ deferResume);
+ }
+
+ kept = ensureConfigAndVisibilityAfterUpdate(starting, changes);
+ } finally {
+ if (mWindowManager != null) {
+ mWindowManager.continueSurfaceLayout();
+ }
+ }
+
+ if (result != null) {
+ result.changes = changes;
+ result.activityRelaunched = !kept;
+ }
+ return kept;
+ }
+
+ /**
+ * Returns true if this configuration change is interesting enough to send an
+ * {@link Intent#ACTION_SPLIT_CONFIGURATION_CHANGED} broadcast.
+ */
+ private static boolean isSplitConfigurationChange(int configDiff) {
+ return (configDiff & (ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_DENSITY)) != 0;
+ }
+
+ /** Update default (global) configuration and notify listeners about changes. */
+ private int updateGlobalConfigurationLocked(@NonNull Configuration values, boolean initLocale,
+ boolean persistent, int userId, boolean deferResume) {
+ mTempConfig.setTo(getGlobalConfiguration());
+ final int changes = mTempConfig.updateFrom(values);
+ if (changes == 0) {
+ // Since calling to Activity.setRequestedOrientation leads to freezing the window with
+ // setting WindowManagerService.mWaitingForConfig to true, it is important that we call
+ // performDisplayOverrideConfigUpdate in order to send the new display configuration
+ // (even if there are no actual changes) to unfreeze the window.
+ performDisplayOverrideConfigUpdate(values, deferResume, DEFAULT_DISPLAY);
+ return 0;
+ }
+
+ if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.i(TAG_CONFIGURATION,
+ "Updating global configuration to: " + values);
+
+ EventLog.writeEvent(EventLogTags.CONFIGURATION_CHANGED, changes);
+ StatsLog.write(StatsLog.RESOURCE_CONFIGURATION_CHANGED,
+ values.colorMode,
+ values.densityDpi,
+ values.fontScale,
+ values.hardKeyboardHidden,
+ values.keyboard,
+ values.keyboardHidden,
+ values.mcc,
+ values.mnc,
+ values.navigation,
+ values.navigationHidden,
+ values.orientation,
+ values.screenHeightDp,
+ values.screenLayout,
+ values.screenWidthDp,
+ values.smallestScreenWidthDp,
+ values.touchscreen,
+ values.uiMode);
+
+
+ if (!initLocale && !values.getLocales().isEmpty() && values.userSetLocale) {
+ final LocaleList locales = values.getLocales();
+ int bestLocaleIndex = 0;
+ if (locales.size() > 1) {
+ if (mSupportedSystemLocales == null) {
+ mSupportedSystemLocales = Resources.getSystem().getAssets().getLocales();
+ }
+ bestLocaleIndex = Math.max(0, locales.getFirstMatchIndex(mSupportedSystemLocales));
+ }
+ SystemProperties.set("persist.sys.locale",
+ locales.get(bestLocaleIndex).toLanguageTag());
+ LocaleList.setDefault(locales, bestLocaleIndex);
+ mAm.mHandler.sendMessage(mAm.mHandler.obtainMessage(SEND_LOCALE_TO_MOUNT_DAEMON_MSG,
+ locales.get(bestLocaleIndex)));
+ }
+
+ mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
+ mTempConfig.seq = mConfigurationSeq;
+
+ // Update stored global config and notify everyone about the change.
+ mStackSupervisor.onConfigurationChanged(mTempConfig);
+
+ Slog.i(TAG, "Config changes=" + Integer.toHexString(changes) + " " + mTempConfig);
+ // TODO(multi-display): Update UsageEvents#Event to include displayId.
+ mAm.mUsageStatsService.reportConfigurationChange(
+ mTempConfig, mAmInternal.getCurrentUserId());
+
+ // TODO: If our config changes, should we auto dismiss any currently showing dialogs?
+ mAm.updateShouldShowDialogsLocked(mTempConfig);
+
+ AttributeCache ac = AttributeCache.instance();
+ if (ac != null) {
+ ac.updateConfiguration(mTempConfig);
+ }
+
+ // Make sure all resources in our process are updated right now, so that anyone who is going
+ // to retrieve resource values after we return will be sure to get the new ones. This is
+ // especially important during boot, where the first config change needs to guarantee all
+ // resources have that config before following boot code is executed.
+ mAm.mSystemThread.applyConfigurationToResources(mTempConfig);
+
+ // We need another copy of global config because we're scheduling some calls instead of
+ // running them in place. We need to be sure that object we send will be handled unchanged.
+ final Configuration configCopy = new Configuration(mTempConfig);
+ if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
+ Message msg = mAm.mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
+ msg.obj = configCopy;
+ msg.arg1 = userId;
+ mAm.mHandler.sendMessage(msg);
+ }
+
+ for (int i = mAm.mLruProcesses.size() - 1; i >= 0; i--) {
+ ProcessRecord app = mAm.mLruProcesses.get(i);
+ try {
+ if (app.thread != null) {
+ if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Sending to proc "
+ + app.processName + " new config " + configCopy);
+ getLifecycleManager().scheduleTransaction(app.thread,
+ ConfigurationChangeItem.obtain(configCopy));
+ }
+ } catch (Exception e) {
+ Slog.e(TAG_CONFIGURATION, "Failed to schedule configuration change", e);
+ }
+ }
+
+ Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_REPLACE_PENDING
+ | Intent.FLAG_RECEIVER_FOREGROUND
+ | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
+ mAm.broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
+ OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
+ UserHandle.USER_ALL);
+ if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) {
+ intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND
+ | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
+ | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
+ if (initLocale || !mAm.mProcessesReady) {
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ }
+ mAm.broadcastIntentLocked(null, null, intent, null, null, 0, null, null, null,
+ OP_NONE, null, false, false, MY_PID, SYSTEM_UID,
+ UserHandle.USER_ALL);
+ }
+
+ // Send a broadcast to PackageInstallers if the configuration change is interesting
+ // for the purposes of installing additional splits.
+ if (!initLocale && isSplitConfigurationChange(changes)) {
+ intent = new Intent(Intent.ACTION_SPLIT_CONFIGURATION_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
+ | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
+
+ // Typically only app stores will have this permission.
+ String[] permissions = new String[] { android.Manifest.permission.INSTALL_PACKAGES };
+ mAm.broadcastIntentLocked(null, null, intent, null, null, 0, null, null, permissions,
+ OP_NONE, null, false, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
+ }
+
+ // Override configuration of the default display duplicates global config, so we need to
+ // update it also. This will also notify WindowManager about changes.
+ performDisplayOverrideConfigUpdate(mStackSupervisor.getConfiguration(), deferResume,
+ DEFAULT_DISPLAY);
+
+ return changes;
+ }
+
+ boolean updateDisplayOverrideConfigurationLocked(Configuration values, ActivityRecord starting,
+ boolean deferResume, int displayId) {
+ return updateDisplayOverrideConfigurationLocked(values, starting, deferResume /* deferResume */,
+ displayId, null /* result */);
+ }
+
+ /**
+ * Updates override configuration specific for the selected display. If no config is provided,
+ * new one will be computed in WM based on current display info.
+ */
+ boolean updateDisplayOverrideConfigurationLocked(Configuration values,
+ ActivityRecord starting, boolean deferResume, int displayId,
+ ActivityTaskManagerService.UpdateConfigurationResult result) {
+ int changes = 0;
+ boolean kept = true;
+
+ if (mWindowManager != null) {
+ mWindowManager.deferSurfaceLayout();
+ }
+ try {
+ if (values != null) {
+ if (displayId == DEFAULT_DISPLAY) {
+ // Override configuration of the default display duplicates global config, so
+ // we're calling global config update instead for default display. It will also
+ // apply the correct override config.
+ changes = updateGlobalConfigurationLocked(values, false /* initLocale */,
+ false /* persistent */, UserHandle.USER_NULL /* userId */, deferResume);
+ } else {
+ changes = performDisplayOverrideConfigUpdate(values, deferResume, displayId);
+ }
+ }
+
+ kept = ensureConfigAndVisibilityAfterUpdate(starting, changes);
+ } finally {
+ if (mWindowManager != null) {
+ mWindowManager.continueSurfaceLayout();
+ }
+ }
+
+ if (result != null) {
+ result.changes = changes;
+ result.activityRelaunched = !kept;
+ }
+ return kept;
+ }
+
+ private int performDisplayOverrideConfigUpdate(Configuration values, boolean deferResume,
+ int displayId) {
+ mTempConfig.setTo(mStackSupervisor.getDisplayOverrideConfiguration(displayId));
+ final int changes = mTempConfig.updateFrom(values);
+ if (changes != 0) {
+ Slog.i(TAG, "Override config changes=" + Integer.toHexString(changes) + " "
+ + mTempConfig + " for displayId=" + displayId);
+ mStackSupervisor.setDisplayOverrideConfiguration(mTempConfig, displayId);
+
+ final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
+ if (isDensityChange && displayId == DEFAULT_DISPLAY) {
+ mAm.mAppWarnings.onDensityChanged();
+
+ mAm.killAllBackgroundProcessesExcept(N,
+ ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE);
+ }
+ }
+
+ // Update the configuration with WM first and check if any of the stacks need to be resized
+ // due to the configuration change. If so, resize the stacks now and do any relaunches if
+ // necessary. This way we don't need to relaunch again afterwards in
+ // ensureActivityConfiguration().
+ if (mWindowManager != null) {
+ final int[] resizedStacks =
+ mWindowManager.setNewDisplayOverrideConfiguration(mTempConfig, displayId);
+ if (resizedStacks != null) {
+ for (int stackId : resizedStacks) {
+ resizeStackWithBoundsFromWindowManager(stackId, deferResume);
+ }
+ }
+ }
+
+ return changes;
+ }
+
+ /** Helper method that requests bounds from WM and applies them to stack. */
+ private void resizeStackWithBoundsFromWindowManager(int stackId, boolean deferResume) {
+ final Rect newStackBounds = new Rect();
+ final ActivityStack stack = mStackSupervisor.getStack(stackId);
+
+ // TODO(b/71548119): Revert CL introducing below once cause of mismatch is found.
+ if (stack == null) {
+ final StringWriter writer = new StringWriter();
+ final PrintWriter printWriter = new PrintWriter(writer);
+ mStackSupervisor.dumpDisplays(printWriter);
+ printWriter.flush();
+
+ Log.wtf(TAG, "stack not found:" + stackId + " displays:" + writer);
+ }
+
+ stack.getBoundsForNewConfiguration(newStackBounds);
+ mStackSupervisor.resizeStackLocked(
+ stack, !newStackBounds.isEmpty() ? newStackBounds : null /* bounds */,
+ null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
+ false /* preserveWindows */, false /* allowResizeInDockedMode */, deferResume);
+ }
+
+ /** Applies latest configuration and/or visibility updates if needed. */
+ private boolean ensureConfigAndVisibilityAfterUpdate(ActivityRecord starting, int changes) {
+ boolean kept = true;
+ final ActivityStack mainStack = mStackSupervisor.getFocusedStack();
+ // mainStack is null during startup.
+ if (mainStack != null) {
+ if (changes != 0 && starting == null) {
+ // If the configuration changed, and the caller is not already
+ // in the process of starting an activity, then find the top
+ // activity to check if its configuration needs to change.
+ starting = mainStack.topRunningActivityLocked();
+ }
+
+ if (starting != null) {
+ kept = starting.ensureActivityConfiguration(changes,
+ false /* preserveWindow */);
+ // And we need to make sure at this point that all other activities
+ // are made visible with the correct configuration.
+ mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes,
+ !PRESERVE_WINDOWS);
+ }
+ }
+
+ return kept;
+ }
+
final class H extends Handler {
public H(Looper looper) {
super(looper, null, true);
}
}
+ final class UiHandler extends Handler {
+
+ public UiHandler() {
+ super(com.android.server.UiThread.get().getLooper(), null, true);
+ }
+ }
+
final class LocalService extends ActivityTaskManagerInternal {
@Override
public SleepToken acquireSleepToken(String tag, int displayId) {
@@ -3657,9 +4431,9 @@
// We might change the visibilities here, so prepare an empty app transition which
// might be overridden later if we actually change visibilities.
final boolean wasTransitionSet =
- mAm.mWindowManager.getPendingAppTransition() != TRANSIT_NONE;
+ mWindowManager.getPendingAppTransition() != TRANSIT_NONE;
if (!wasTransitionSet) {
- mAm.mWindowManager.prepareAppTransition(TRANSIT_NONE,
+ mWindowManager.prepareAppTransition(TRANSIT_NONE,
false /* alwaysKeepCurrent */);
}
mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
@@ -3667,7 +4441,7 @@
// If there was a transition set already we don't want to interfere with it as we
// might be starting it too early.
if (!wasTransitionSet) {
- mAm.mWindowManager.executeAppTransition();
+ mWindowManager.executeAppTransition();
}
}
if (callback != null) {
@@ -3693,7 +4467,7 @@
public void setVr2dDisplayId(int vr2dDisplayId) {
if (DEBUG_STACK) Slog.d(TAG, "setVr2dDisplayId called for: " + vr2dDisplayId);
synchronized (mGlobalLock) {
- mAm.mVr2dDisplayId = vr2dDisplayId;
+ mVr2dDisplayId = vr2dDisplayId;
}
}
@@ -3734,7 +4508,7 @@
@Override
public void registerScreenObserver(ScreenObserver observer) {
- mAm.mScreenObservers.add(observer);
+ mScreenObservers.add(observer);
}
@Override
@@ -3754,7 +4528,7 @@
@Override
public void enforceCallerIsRecentsOrHasPermission(String permission, String func) {
- mAm.enforceCallerIsRecentsOrHasPermission(permission, func);
+ ActivityTaskManagerService.this.enforceCallerIsRecentsOrHasPermission(permission, func);
}
@Override
@@ -3763,5 +4537,43 @@
mActiveVoiceInteractionServiceComponent = component;
}
}
+
+ @Override
+ public void setAllowAppSwitches(@NonNull String type, int uid, int userId) {
+ if (!mAmInternal.isUserRunning(userId, ActivityManager.FLAG_OR_STOPPED)) {
+ return;
+ }
+ synchronized (mGlobalLock) {
+ ArrayMap<String, Integer> types = mAllowAppSwitchUids.get(userId);
+ if (types == null) {
+ if (uid < 0) {
+ return;
+ }
+ types = new ArrayMap<>();
+ mAllowAppSwitchUids.put(userId, types);
+ }
+ if (uid < 0) {
+ types.remove(type);
+ } else {
+ types.put(type, uid);
+ }
+ }
+ }
+
+ @Override
+ public void onUserStopped(int userId) {
+ synchronized (mGlobalLock) {
+ getRecentTasks().unloadUserDataFromMemoryLocked(userId);
+ mAllowAppSwitchUids.remove(userId);
+ }
+ }
+
+ @Override
+ public boolean isGetTasksAllowed(String caller, int callingPid, int callingUid) {
+ synchronized (mGlobalLock) {
+ return ActivityTaskManagerService.this.isGetTasksAllowed(
+ caller, callingPid, callingUid);
+ }
+ }
}
}