Merge "Add lockTaskOnLaunch attribute."
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 4723c0d..24c026d 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -648,6 +648,12 @@
*/
public boolean resizeable;
+ /**
+ * Value indicating if the activity is to be locked at startup.
+ * @hide
+ */
+ public boolean lockTaskOnLaunch;
+
public ActivityInfo() {
}
@@ -665,13 +671,15 @@
uiOptions = orig.uiOptions;
parentActivityName = orig.parentActivityName;
maxRecents = orig.maxRecents;
+ resizeable = orig.resizeable;
+ lockTaskOnLaunch = orig.lockTaskOnLaunch;
}
-
+
/**
* Return the theme resource identifier to use for this activity. If
* the activity defines a theme, that is used; else, the application
* theme is used.
- *
+ *
* @return The theme associated with this activity.
*/
public final int getThemeResource() {
@@ -709,7 +717,7 @@
if (uiOptions != 0) {
pw.println(prefix + " uiOptions=0x" + Integer.toHexString(uiOptions));
}
- pw.println(prefix + "resizeable=" + resizeable);
+ pw.println(prefix + "resizeable=" + resizeable + " lockTaskOnLaunch=" + lockTaskOnLaunch);
super.dumpBack(pw, prefix);
}
@@ -739,6 +747,7 @@
dest.writeInt(persistableMode);
dest.writeInt(maxRecents);
dest.writeInt(resizeable ? 1 : 0);
+ dest.writeInt(lockTaskOnLaunch ? 1 : 0);
}
public static final Parcelable.Creator<ActivityInfo> CREATOR
@@ -767,5 +776,6 @@
persistableMode = source.readInt();
maxRecents = source.readInt();
resizeable = (source.readInt() == 1);
+ lockTaskOnLaunch = (source.readInt() == 1);
}
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 4b81fd4..3d5c2ed 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3113,6 +3113,9 @@
R.styleable.AndroidManifestActivity_screenOrientation,
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
}
+
+ a.info.lockTaskOnLaunch =
+ sa.getBoolean(R.styleable.AndroidManifestActivity_lockTaskOnLaunch, false);
} else {
a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
a.info.configChanges = 0;
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index b0b4e3a..1b3a5e9 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1038,6 +1038,13 @@
activity. -->
<attr name="resizeableActivity" format="boolean" />
+ <!-- Tasks rooted at this activity will start up in lock-task mode. That means that they
+ cannot be navigated away from until they finish or explicitly release lock-task mode.
+ This only works for system privileged activities. An exception will be thrown for
+ non-privileged activities that use this attribute.
+ @hide -->
+ <attr name="lockTaskOnLaunch" format="boolean" />
+
<!-- When set installer will extract native libraries. If set to false
libraries in the apk must be stored and page-aligned. -->
<attr name="extractNativeLibs" format="boolean"/>
@@ -1191,7 +1198,7 @@
features in your package (or other packages). See the
<a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a>
document for more information on permissions.
-
+
<p>This appears as a child tag of the root
{@link #AndroidManifest manifest} tag. -->
<declare-styleable name="AndroidManifestPermission" parent="AndroidManifest">
@@ -1210,15 +1217,15 @@
<attr name="protectionLevel" />
<attr name="permissionFlags" />
</declare-styleable>
-
+
<!-- The <code>permission-group</code> tag declares a logical grouping of
related permissions.
-
+
<p>Note that this tag does not declare a permission itself, only
a namespace in which further permissions can be placed. See
the {@link #AndroidManifestPermission <permission>} tag for
more information.
-
+
<p>This appears as a child tag of the root
{@link #AndroidManifest manifest} tag. -->
<declare-styleable name="AndroidManifestPermissionGroup" parent="AndroidManifest">
@@ -1236,7 +1243,7 @@
<attr name="permissionGroupFlags" />
<attr name="priority" />
</declare-styleable>
-
+
<!-- The <code>permission-tree</code> tag declares the base of a tree of
permission values: it declares that this package has ownership of
the given permission name, as well as all names underneath it
@@ -1749,6 +1756,7 @@
<attr name="relinquishTaskIdentity" />
<attr name="resumeWhilePausing" />
<attr name="resizeableActivity" />
+ <attr name="lockTaskOnLaunch" />
</declare-styleable>
<!-- The <code>activity-alias</code> tag declares a new
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 5c7daf2..754d7ebd 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2657,4 +2657,5 @@
<!--IntentFilter auto verification -->
<public type="attr" name="autoVerify" />
+ <public type="attr" name="lockTaskOnLaunch" />
</resources>
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index c318370..6543bc2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3911,9 +3911,9 @@
}
// Do not allow task to finish in Lock Task mode.
if (tr == mStackSupervisor.mLockTaskModeTask) {
- if (rootR == r) {
+ if (rootR == r && tr.getTopActivity() == r) {
Slog.i(TAG, "Not finishing task in lock task mode");
- mStackSupervisor.showLockTaskToast();
+ mStackSupervisor.showLockTaskToastLocked();
return false;
}
}
@@ -4074,7 +4074,7 @@
// Do not allow task to finish in Lock Task mode.
if (r.task == mStackSupervisor.mLockTaskModeTask) {
if (rootR == r) {
- mStackSupervisor.showLockTaskToast();
+ mStackSupervisor.showLockTaskToastLocked();
return false;
}
}
@@ -8238,7 +8238,7 @@
return;
}
if (mStackSupervisor.isLockTaskModeViolation(task)) {
- mStackSupervisor.showLockTaskToast();
+ mStackSupervisor.showLockTaskToastLocked();
Slog.e(TAG, "moveTaskToFront: Attempt to violate Lock Task Mode");
return;
}
@@ -8272,7 +8272,7 @@
if (taskId >= 0) {
if ((mStackSupervisor.mLockTaskModeTask != null)
&& (mStackSupervisor.mLockTaskModeTask.taskId == taskId)) {
- mStackSupervisor.showLockTaskToast();
+ mStackSupervisor.showLockTaskToastLocked();
return false;
}
return ActivityRecord.getStackLocked(token).moveTaskToBackLocked(taskId);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index f874244..d574571 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -154,9 +154,10 @@
static final int CONTAINER_CALLBACK_VISIBILITY = FIRST_SUPERVISOR_STACK_MSG + 8;
static final int LOCK_TASK_START_MSG = FIRST_SUPERVISOR_STACK_MSG + 9;
static final int LOCK_TASK_END_MSG = FIRST_SUPERVISOR_STACK_MSG + 10;
- static final int CONTAINER_CALLBACK_TASK_LIST_EMPTY = FIRST_SUPERVISOR_STACK_MSG + 11;
- static final int CONTAINER_TASK_LIST_EMPTY_TIMEOUT = FIRST_SUPERVISOR_STACK_MSG + 12;
- static final int LAUNCH_TASK_BEHIND_COMPLETE = FIRST_SUPERVISOR_STACK_MSG + 13;
+ static final int LOCK_TASK_SHOW_TOAST_MSG = FIRST_SUPERVISOR_STACK_MSG + 11;
+ static final int CONTAINER_CALLBACK_TASK_LIST_EMPTY = FIRST_SUPERVISOR_STACK_MSG + 12;
+ static final int CONTAINER_TASK_LIST_EMPTY_TIMEOUT = FIRST_SUPERVISOR_STACK_MSG + 13;
+ static final int LAUNCH_TASK_BEHIND_COMPLETE = FIRST_SUPERVISOR_STACK_MSG + 14;
private final static String VIRTUAL_DISPLAY_BASE_NAME = "ActivityViewVirtualDisplay";
@@ -1884,7 +1885,7 @@
findTaskLocked(r) : findActivityLocked(intent, r.info);
if (intentActivity != null) {
if (isLockTaskModeViolation(intentActivity.task)) {
- showLockTaskToast();
+ showLockTaskToastLocked();
Slog.e(TAG, "startActivityUnchecked: Attempt to violate Lock Task Mode");
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
@@ -2144,6 +2145,20 @@
} else {
r.setTask(reuseTask, taskToAffiliate);
}
+ if (r.info.lockTaskOnLaunch) {
+ try {
+ if (!AppGlobals.getPackageManager().isUidPrivileged(callingUid)) {
+ Slog.e(TAG, "Non-privileged activity " + r +
+ " using lockTaskOnLaunch attribute");
+ throw new RuntimeException(
+ "Non-privileged activity using lockTaskOnLaunch attribute.");
+ }
+ } catch (RemoteException e) {
+ // Unreachable. The package manager is in this process.
+ }
+ setLockTaskModeLocked(r.task, ActivityManager.LOCK_TASK_MODE_LOCKED,
+ "lockTaskOnLaunch attribute");
+ }
if (!movedHome) {
if ((launchFlags &
(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
@@ -3596,8 +3611,8 @@
return list;
}
- void showLockTaskToast() {
- mLockTaskNotify.showToast(mLockTaskModeState);
+ void showLockTaskToastLocked() {
+ mHandler.sendEmptyMessage(LOCK_TASK_SHOW_TOAST_MSG);
}
void setLockTaskModeLocked(TaskRecord task, int lockTaskModeState, String reason) {
@@ -3796,6 +3811,13 @@
mLockTaskModeState = ActivityManager.LOCK_TASK_MODE_NONE;
}
} break;
+ case LOCK_TASK_SHOW_TOAST_MSG: {
+ if (mLockTaskNotify == null) {
+ mLockTaskNotify = new LockTaskNotify(mService.mContext);
+ }
+ mLockTaskNotify.showToast(mLockTaskModeState);
+ break;
+ }
case CONTAINER_CALLBACK_TASK_LIST_EMPTY: {
final ActivityContainer container = (ActivityContainer) msg.obj;
final IActivityContainerCallback callback = container.mCallback;