Merge "AM: introduce ActivityOptions.setLockTaskMode()."
This commit is contained in:
@@ -4023,6 +4023,7 @@ package android.app {
|
||||
public class ActivityOptions {
|
||||
method public android.graphics.Rect getLaunchBounds();
|
||||
method public int getLaunchDisplayId();
|
||||
method public boolean getLockTaskMode();
|
||||
method public static android.app.ActivityOptions makeBasic();
|
||||
method public static android.app.ActivityOptions makeClipRevealAnimation(android.view.View, int, int, int, int);
|
||||
method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
|
||||
@@ -4035,6 +4036,7 @@ package android.app {
|
||||
method public android.app.ActivityOptions setAppVerificationBundle(android.os.Bundle);
|
||||
method public android.app.ActivityOptions setLaunchBounds(android.graphics.Rect);
|
||||
method public android.app.ActivityOptions setLaunchDisplayId(int);
|
||||
method public android.app.ActivityOptions setLockTaskMode(boolean);
|
||||
method public android.os.Bundle toBundle();
|
||||
method public void update(android.app.ActivityOptions);
|
||||
field public static final java.lang.String EXTRA_USAGE_TIME_REPORT = "android.activity.usage_time";
|
||||
|
||||
@@ -4185,6 +4185,7 @@ package android.app {
|
||||
public class ActivityOptions {
|
||||
method public android.graphics.Rect getLaunchBounds();
|
||||
method public int getLaunchDisplayId();
|
||||
method public boolean getLockTaskMode();
|
||||
method public static android.app.ActivityOptions makeBasic();
|
||||
method public static android.app.ActivityOptions makeClipRevealAnimation(android.view.View, int, int, int, int);
|
||||
method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
|
||||
@@ -4197,6 +4198,7 @@ package android.app {
|
||||
method public android.app.ActivityOptions setAppVerificationBundle(android.os.Bundle);
|
||||
method public android.app.ActivityOptions setLaunchBounds(android.graphics.Rect);
|
||||
method public android.app.ActivityOptions setLaunchDisplayId(int);
|
||||
method public android.app.ActivityOptions setLockTaskMode(boolean);
|
||||
method public android.os.Bundle toBundle();
|
||||
method public void update(android.app.ActivityOptions);
|
||||
field public static final java.lang.String EXTRA_USAGE_TIME_REPORT = "android.activity.usage_time";
|
||||
|
||||
@@ -4043,6 +4043,7 @@ package android.app {
|
||||
public class ActivityOptions {
|
||||
method public android.graphics.Rect getLaunchBounds();
|
||||
method public int getLaunchDisplayId();
|
||||
method public boolean getLockTaskMode();
|
||||
method public static android.app.ActivityOptions makeBasic();
|
||||
method public static android.app.ActivityOptions makeClipRevealAnimation(android.view.View, int, int, int, int);
|
||||
method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
|
||||
@@ -4058,6 +4059,7 @@ package android.app {
|
||||
method public android.app.ActivityOptions setLaunchDisplayId(int);
|
||||
method public void setLaunchTaskId(int);
|
||||
method public void setLaunchWindowingMode(int);
|
||||
method public android.app.ActivityOptions setLockTaskMode(boolean);
|
||||
method public void setTaskOverlay(boolean, boolean);
|
||||
method public android.os.Bundle toBundle();
|
||||
method public void update(android.app.ActivityOptions);
|
||||
|
||||
@@ -23,6 +23,7 @@ import static android.view.Display.INVALID_DISPLAY;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.TestApi;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
@@ -157,6 +158,12 @@ public class ActivityOptions {
|
||||
*/
|
||||
private static final String KEY_ANIM_SPECS = "android:activity.animSpecs";
|
||||
|
||||
/**
|
||||
* Whether the activity should be launched into LockTask mode.
|
||||
* @see #setLockTaskMode(boolean)
|
||||
*/
|
||||
private static final String KEY_LOCK_TASK_MODE = "android:activity.lockTaskMode";
|
||||
|
||||
/**
|
||||
* The display id the activity should be launched into.
|
||||
* @see #setLaunchDisplayId(int)
|
||||
@@ -278,6 +285,7 @@ public class ActivityOptions {
|
||||
private int mResultCode;
|
||||
private int mExitCoordinatorIndex;
|
||||
private PendingIntent mUsageTimeReport;
|
||||
private boolean mLockTaskMode = false;
|
||||
private int mLaunchDisplayId = INVALID_DISPLAY;
|
||||
@WindowConfiguration.WindowingMode
|
||||
private int mLaunchWindowingMode = WINDOWING_MODE_UNDEFINED;
|
||||
@@ -869,6 +877,7 @@ public class ActivityOptions {
|
||||
mExitCoordinatorIndex = opts.getInt(KEY_EXIT_COORDINATOR_INDEX);
|
||||
break;
|
||||
}
|
||||
mLockTaskMode = opts.getBoolean(KEY_LOCK_TASK_MODE, false);
|
||||
mLaunchDisplayId = opts.getInt(KEY_LAUNCH_DISPLAY_ID, INVALID_DISPLAY);
|
||||
mLaunchWindowingMode = opts.getInt(KEY_LAUNCH_WINDOWING_MODE, WINDOWING_MODE_UNDEFINED);
|
||||
mLaunchActivityType = opts.getInt(KEY_LAUNCH_ACTIVITY_TYPE, ACTIVITY_TYPE_UNDEFINED);
|
||||
@@ -1054,6 +1063,37 @@ public class ActivityOptions {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the activity is to be launched into LockTask mode.
|
||||
* @return {@code true} if the activity is to be launched into LockTask mode.
|
||||
* @see Activity#startLockTask()
|
||||
* @see android.app.admin.DevicePolicyManager#setLockTaskPackages(ComponentName, String[])
|
||||
*/
|
||||
public boolean getLockTaskMode() {
|
||||
return mLockTaskMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the activity is to be launched into LockTask mode.
|
||||
*
|
||||
* Use this option to start an activity in LockTask mode. Note that only apps permitted by
|
||||
* {@link android.app.admin.DevicePolicyManager} can run in LockTask mode. Therefore, if
|
||||
* {@link android.app.admin.DevicePolicyManager#isLockTaskPermitted(String)} returns
|
||||
* {@code false} for the package of the target activity, a {@link SecurityException} will be
|
||||
* thrown during {@link Context#startActivity(Intent, Bundle)}.
|
||||
*
|
||||
* Defaults to {@code false} if not set.
|
||||
*
|
||||
* @param lockTaskMode {@code true} if the activity is to be launched into LockTask mode.
|
||||
* @return {@code this} {@link ActivityOptions} instance.
|
||||
* @see Activity#startLockTask()
|
||||
* @see android.app.admin.DevicePolicyManager#setLockTaskPackages(ComponentName, String[])
|
||||
*/
|
||||
public ActivityOptions setLockTaskMode(boolean lockTaskMode) {
|
||||
mLockTaskMode = lockTaskMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id of the display where activity should be launched.
|
||||
* @return The id of the display where activity should be launched,
|
||||
@@ -1247,6 +1287,7 @@ public class ActivityOptions {
|
||||
mExitCoordinatorIndex = otherOptions.mExitCoordinatorIndex;
|
||||
break;
|
||||
}
|
||||
mLockTaskMode = otherOptions.mLockTaskMode;
|
||||
mAnimSpecs = otherOptions.mAnimSpecs;
|
||||
mAnimationFinishedListener = otherOptions.mAnimationFinishedListener;
|
||||
mSpecsFuture = otherOptions.mSpecsFuture;
|
||||
@@ -1321,6 +1362,7 @@ public class ActivityOptions {
|
||||
b.putInt(KEY_EXIT_COORDINATOR_INDEX, mExitCoordinatorIndex);
|
||||
break;
|
||||
}
|
||||
b.putBoolean(KEY_LOCK_TASK_MODE, mLockTaskMode);
|
||||
b.putInt(KEY_LAUNCH_DISPLAY_ID, mLaunchDisplayId);
|
||||
b.putInt(KEY_LAUNCH_WINDOWING_MODE, mLaunchWindowingMode);
|
||||
b.putInt(KEY_LAUNCH_ACTIVITY_TYPE, mLaunchActivityType);
|
||||
|
||||
@@ -58,6 +58,10 @@ import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
|
||||
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
|
||||
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
|
||||
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
|
||||
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
|
||||
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
|
||||
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
|
||||
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
|
||||
import static android.content.pm.ActivityInfo.PERSIST_ACROSS_REBOOTS;
|
||||
import static android.content.pm.ActivityInfo.PERSIST_ROOT_ONLY;
|
||||
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
|
||||
@@ -282,6 +286,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
|
||||
int configChangeFlags; // which config values have changed
|
||||
private boolean keysPaused; // has key dispatching been paused for it?
|
||||
int launchMode; // the launch mode activity attribute.
|
||||
int lockTaskLaunchMode; // the lockTaskMode manifest attribute, subject to override
|
||||
boolean visible; // does this activity's window need to be shown?
|
||||
boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
|
||||
// might hide this activity?
|
||||
@@ -824,23 +829,6 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
|
||||
hasBeenLaunched = false;
|
||||
mStackSupervisor = supervisor;
|
||||
|
||||
mRotationAnimationHint = aInfo.rotationAnimation;
|
||||
|
||||
if (options != null) {
|
||||
pendingOptions = options;
|
||||
mLaunchTaskBehind = pendingOptions.getLaunchTaskBehind();
|
||||
|
||||
final int rotationAnimation = pendingOptions.getRotationAnimationHint();
|
||||
// Only override manifest supplied option if set.
|
||||
if (rotationAnimation >= 0) {
|
||||
mRotationAnimationHint = rotationAnimation;
|
||||
}
|
||||
PendingIntent usageReport = pendingOptions.getUsageTimeReport();
|
||||
if (usageReport != null) {
|
||||
appTimeTracker = new AppTimeTracker(usageReport);
|
||||
}
|
||||
}
|
||||
|
||||
// This starts out true, since the initial state of an activity is that we have everything,
|
||||
// and we shouldn't never consider it lacking in state to be removed if it dies.
|
||||
haveState = true;
|
||||
@@ -907,6 +895,32 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
|
||||
|
||||
mShowWhenLocked = (aInfo.flags & FLAG_SHOW_WHEN_LOCKED) != 0;
|
||||
mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0;
|
||||
|
||||
mRotationAnimationHint = aInfo.rotationAnimation;
|
||||
lockTaskLaunchMode = aInfo.lockTaskLaunchMode;
|
||||
if (appInfo.isPrivilegedApp() && (lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
|
||||
|| lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
|
||||
lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
|
||||
}
|
||||
|
||||
if (options != null) {
|
||||
pendingOptions = options;
|
||||
mLaunchTaskBehind = options.getLaunchTaskBehind();
|
||||
|
||||
final int rotationAnimation = pendingOptions.getRotationAnimationHint();
|
||||
// Only override manifest supplied option if set.
|
||||
if (rotationAnimation >= 0) {
|
||||
mRotationAnimationHint = rotationAnimation;
|
||||
}
|
||||
final PendingIntent usageReport = pendingOptions.getUsageTimeReport();
|
||||
if (usageReport != null) {
|
||||
appTimeTracker = new AppTimeTracker(usageReport);
|
||||
}
|
||||
final boolean useLockTask = pendingOptions.getLockTaskMode();
|
||||
if (useLockTask && lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_DEFAULT) {
|
||||
lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AppWindowContainerController getWindowContainerController() {
|
||||
|
||||
@@ -1611,6 +1611,16 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
|
||||
Slog.w(TAG, msg);
|
||||
throw new SecurityException(msg);
|
||||
}
|
||||
// Check if someone tries to launch an unwhitelisted activity into LockTask mode.
|
||||
final boolean lockTaskMode = options.getLockTaskMode();
|
||||
if (lockTaskMode && !mService.mLockTaskController.isPackageWhitelisted(
|
||||
UserHandle.getUserId(callingUid), aInfo.packageName)) {
|
||||
final String msg = "Permission Denial: starting " + intent.toString()
|
||||
+ " from " + callerApp + " (pid=" + callingPid
|
||||
+ ", uid=" + callingUid + ") with lockTaskMode=true";
|
||||
Slog.w(TAG, msg);
|
||||
throw new SecurityException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -43,7 +43,6 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
|
||||
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
|
||||
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED;
|
||||
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
|
||||
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
|
||||
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
|
||||
import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
@@ -165,7 +164,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
|
||||
private static final String ATTR_CALLING_PACKAGE = "calling_package";
|
||||
private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supports_picture_in_picture";
|
||||
private static final String ATTR_RESIZE_MODE = "resize_mode";
|
||||
private static final String ATTR_PRIVILEGED = "privileged";
|
||||
private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
|
||||
private static final String ATTR_MIN_WIDTH = "min_width";
|
||||
private static final String ATTR_MIN_HEIGHT = "min_height";
|
||||
@@ -235,10 +233,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
|
||||
// of the root activity.
|
||||
boolean mTemporarilyUnresizable; // Separate flag from mResizeMode used to suppress resize
|
||||
// changes on a temporary basis.
|
||||
private int mLockTaskMode; // Which tasklock mode to launch this task in. One of
|
||||
// ActivityManager.LOCK_TASK_LAUNCH_MODE_*
|
||||
private boolean mPrivileged; // The root activity application of this task holds
|
||||
// privileged permissions.
|
||||
|
||||
/** Can't be put in lockTask mode. */
|
||||
final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
|
||||
@@ -388,9 +382,8 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
|
||||
long lastTimeMoved, boolean neverRelinquishIdentity,
|
||||
TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
|
||||
int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
|
||||
int resizeMode, boolean supportsPictureInPicture, boolean privileged,
|
||||
boolean _realActivitySuspended, boolean userSetupComplete, int minWidth,
|
||||
int minHeight) {
|
||||
int resizeMode, boolean supportsPictureInPicture, boolean _realActivitySuspended,
|
||||
boolean userSetupComplete, int minWidth, int minHeight) {
|
||||
mService = service;
|
||||
mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
|
||||
TaskPersister.IMAGE_EXTENSION;
|
||||
@@ -426,7 +419,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
|
||||
mCallingPackage = callingPackage;
|
||||
mResizeMode = resizeMode;
|
||||
mSupportsPictureInPicture = supportsPictureInPicture;
|
||||
mPrivileged = privileged;
|
||||
mMinWidth = minWidth;
|
||||
mMinHeight = minHeight;
|
||||
mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
|
||||
@@ -802,6 +794,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
|
||||
mCallingUid = r.launchedFromUid;
|
||||
mCallingPackage = r.launchedFromPackage;
|
||||
setIntent(r.intent, r.info);
|
||||
setLockTaskAuth(r);
|
||||
}
|
||||
|
||||
/** Sets the original intent, _without_ updating the calling uid or package. */
|
||||
@@ -885,14 +878,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
|
||||
}
|
||||
mResizeMode = info.resizeMode;
|
||||
mSupportsPictureInPicture = info.supportsPictureInPicture();
|
||||
mPrivileged = (info.applicationInfo.privateFlags & PRIVATE_FLAG_PRIVILEGED) != 0;
|
||||
mLockTaskMode = info.lockTaskLaunchMode;
|
||||
if (!mPrivileged && (mLockTaskMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
|
||||
|| mLockTaskMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
|
||||
// Non-priv apps are not allowed to use always or never, fall back to default
|
||||
mLockTaskMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
|
||||
}
|
||||
setLockTaskAuth();
|
||||
}
|
||||
|
||||
/** Sets the original minimal width and height. */
|
||||
@@ -1429,8 +1414,17 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
|
||||
}
|
||||
|
||||
void setLockTaskAuth() {
|
||||
setLockTaskAuth(getRootActivity());
|
||||
}
|
||||
|
||||
private void setLockTaskAuth(@Nullable ActivityRecord r) {
|
||||
if (r == null) {
|
||||
mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
|
||||
return;
|
||||
}
|
||||
|
||||
final String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
|
||||
switch (mLockTaskMode) {
|
||||
switch (r.lockTaskLaunchMode) {
|
||||
case LOCK_TASK_LAUNCH_MODE_DEFAULT:
|
||||
mLockTaskAuth = mService.mLockTaskController.isPackageWhitelisted(userId, pkg)
|
||||
? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
|
||||
@@ -1671,7 +1665,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
|
||||
out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
|
||||
out.attribute(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE,
|
||||
String.valueOf(mSupportsPictureInPicture));
|
||||
out.attribute(null, ATTR_PRIVILEGED, String.valueOf(mPrivileged));
|
||||
if (mLastNonFullscreenBounds != null) {
|
||||
out.attribute(
|
||||
null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
|
||||
@@ -1739,7 +1732,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
|
||||
String callingPackage = "";
|
||||
int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
|
||||
boolean supportsPictureInPicture = false;
|
||||
boolean privileged = false;
|
||||
Rect bounds = null;
|
||||
int minWidth = INVALID_MIN_SIZE;
|
||||
int minHeight = INVALID_MIN_SIZE;
|
||||
@@ -1801,8 +1793,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
|
||||
resizeMode = Integer.parseInt(attrValue);
|
||||
} else if (ATTR_SUPPORTS_PICTURE_IN_PICTURE.equals(attrName)) {
|
||||
supportsPictureInPicture = Boolean.parseBoolean(attrValue);
|
||||
} else if (ATTR_PRIVILEGED.equals(attrName)) {
|
||||
privileged = Boolean.parseBoolean(attrValue);
|
||||
} else if (ATTR_NON_FULLSCREEN_BOUNDS.equals(attrName)) {
|
||||
bounds = Rect.unflattenFromString(attrValue);
|
||||
} else if (ATTR_MIN_WIDTH.equals(attrName)) {
|
||||
@@ -1889,8 +1879,8 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
|
||||
autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
|
||||
activities, lastTimeOnTop, neverRelinquishIdentity, taskDescription,
|
||||
taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, callingUid,
|
||||
callingPackage, resizeMode, supportsPictureInPicture, privileged,
|
||||
realActivitySuspended, userSetupComplete, minWidth, minHeight);
|
||||
callingPackage, resizeMode, supportsPictureInPicture, realActivitySuspended,
|
||||
userSetupComplete, minWidth, minHeight);
|
||||
task.updateOverrideConfiguration(bounds);
|
||||
|
||||
for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
|
||||
|
||||
Reference in New Issue
Block a user