summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt2
-rw-r--r--api/system-current.txt2
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java41
-rw-r--r--core/java/android/app/ActivityManagerNative.java22
-rw-r--r--core/java/android/app/IActivityManager.java2
-rw-r--r--core/java/android/content/pm/ActivityInfo.java9
-rw-r--r--core/java/android/content/pm/PackageParser.java132
-rw-r--r--core/res/res/values/attrs_manifest.xml21
-rw-r--r--core/res/res/values/public.xml1
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java12
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityRecord.java1
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java29
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java9
-rw-r--r--services/core/java/com/android/server/am/TaskRecord.java40
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java45
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java26
16 files changed, 268 insertions, 126 deletions
diff --git a/api/current.txt b/api/current.txt
index c8eefea..cd41172 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1014,6 +1014,7 @@ package android {
field public static final int resizeClip = 16843983; // 0x10104cf
field public static final int resizeMode = 16843619; // 0x1010363
field public static final int resizeable = 16843405; // 0x101028d
+ field public static final int resizeableActivity = 16843995; // 0x10104db
field public static final int resource = 16842789; // 0x1010025
field public static final int restoreAnyVersion = 16843450; // 0x10102ba
field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
@@ -8431,6 +8432,7 @@ package android.content.pm {
field public java.lang.String parentActivityName;
field public java.lang.String permission;
field public int persistableMode;
+ field public boolean resizeable;
field public int screenOrientation;
field public int softInputMode;
field public java.lang.String targetActivity;
diff --git a/api/system-current.txt b/api/system-current.txt
index 9f138e4..8086387 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1086,6 +1086,7 @@ package android {
field public static final int resizeClip = 16843983; // 0x10104cf
field public static final int resizeMode = 16843619; // 0x1010363
field public static final int resizeable = 16843405; // 0x101028d
+ field public static final int resizeableActivity = 16843995; // 0x10104db
field public static final int resource = 16842789; // 0x1010025
field public static final int restoreAnyVersion = 16843450; // 0x10102ba
field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
@@ -8639,6 +8640,7 @@ package android.content.pm {
field public java.lang.String parentActivityName;
field public java.lang.String permission;
field public int persistableMode;
+ field public boolean resizeable;
field public int screenOrientation;
field public int softInputMode;
field public java.lang.String targetActivity;
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index fb3d423..cf608a8 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -134,8 +134,9 @@ public class Am extends BaseCommand {
" am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
" am stack list\n" +
" am stack info <STACK_ID>\n" +
- " am lock-task <TASK_ID>\n" +
- " am lock-task stop\n" +
+ " am task lock <TASK_ID>\n" +
+ " am task lock stop\n" +
+ " am task resizeable <TASK_ID> [true|false]\n" +
" am get-config\n" +
"\n" +
"am start: start an Activity. Options are:\n" +
@@ -250,7 +251,11 @@ public class Am extends BaseCommand {
"\n" +
"am stack info: display the information about activity stack <STACK_ID>.\n" +
"\n" +
- "am lock-task: bring <TASK_ID> to the front and don't allow other tasks to run\n" +
+ "am task lock: bring <TASK_ID> to the front and don't allow other tasks to run\n" +
+ "\n" +
+ "am task lock stop: end the current task lock\n" +
+ "\n" +
+ "am task resizeable: change if <TASK_ID> is resizeable (true) or not (false).\n" +
"\n" +
"am get-config: retrieve the configuration and any recent configurations\n" +
" of the device\n" +
@@ -351,8 +356,8 @@ public class Am extends BaseCommand {
runStopUser();
} else if (op.equals("stack")) {
runStack();
- } else if (op.equals("lock-task")) {
- runLockTask();
+ } else if (op.equals("task")) {
+ runTask();
} else if (op.equals("get-config")) {
runGetConfig();
} else {
@@ -1778,7 +1783,19 @@ public class Am extends BaseCommand {
}
}
- private void runLockTask() throws Exception {
+ private void runTask() throws Exception {
+ String op = nextArgRequired();
+ if (op.equals("lock")) {
+ runTaskLock();
+ } else if (op.equals("resizeable")) {
+ runTaskResizeable();
+ } else {
+ showError("Error: unknown command '" + op + "'");
+ return;
+ }
+ }
+
+ private void runTaskLock() throws Exception {
String taskIdStr = nextArgRequired();
try {
if (taskIdStr.equals("stop")) {
@@ -1793,6 +1810,18 @@ public class Am extends BaseCommand {
}
}
+ private void runTaskResizeable() throws Exception {
+ final String taskIdStr = nextArgRequired();
+ final int taskId = Integer.valueOf(taskIdStr);
+ final String resizeableStr = nextArgRequired();
+ final boolean resizeable = Boolean.valueOf(resizeableStr);
+
+ try {
+ mAm.setTaskResizeable(taskId, resizeable);
+ } catch (RemoteException e) {
+ }
+ }
+
private List<Configuration> getRecentConfigurations(int days) {
IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
Context.USAGE_STATS_SERVICE));
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 97b9f4c..47f57ea 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2300,6 +2300,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case SET_TASK_RESIZEABLE_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ int taskId = data.readInt();
+ boolean resizeable = (data.readInt() == 1) ? true : false;
+ setTaskResizeable(taskId, resizeable);
+ reply.writeNoException();
+ return true;
+ }
+
case GET_TASK_DESCRIPTION_ICON_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
String filename = data.readString();
@@ -5402,6 +5411,19 @@ class ActivityManagerProxy implements IActivityManager
}
@Override
+ public void setTaskResizeable(int taskId, boolean resizeable) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeInt(taskId);
+ data.writeInt(resizeable ? 1 : 0);
+ mRemote.transact(SET_TASK_RESIZEABLE_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
+ @Override
public Bitmap getTaskDescriptionIcon(String filename) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index efc4543..467c99a 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -460,6 +460,7 @@ public interface IActivityManager extends IInterface {
public void setTaskDescription(IBinder token, ActivityManager.TaskDescription values)
throws RemoteException;
+ public void setTaskResizeable(int taskId, boolean resizeable) throws RemoteException;
public Bitmap getTaskDescriptionIcon(String filename) throws RemoteException;
public void startInPlaceAnimationOnFrontMostApplication(ActivityOptions opts)
@@ -802,4 +803,5 @@ public interface IActivityManager extends IInterface {
int NOTIFY_CLEARTEXT_NETWORK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+280;
int CREATE_STACK_ON_DISPLAY = IBinder.FIRST_CALL_TRANSACTION+281;
int GET_FOCUSED_STACK_ID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+282;
+ int SET_TASK_RESIZEABLE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+283;
}
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 641f843..452603a 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -641,6 +641,12 @@ public class ActivityInfo extends ComponentInfo
*/
public String parentActivityName;
+ /**
+ * Value indicating if the activity is resizeable to any dimension.
+ * See {@link android.R.attr#resizeableActivity}.
+ */
+ public boolean resizeable;
+
public ActivityInfo() {
}
@@ -702,6 +708,7 @@ public class ActivityInfo extends ComponentInfo
if (uiOptions != 0) {
pw.println(prefix + " uiOptions=0x" + Integer.toHexString(uiOptions));
}
+ pw.println(prefix + "resizeable=" + resizeable);
super.dumpBack(pw, prefix);
}
@@ -730,6 +737,7 @@ public class ActivityInfo extends ComponentInfo
dest.writeString(parentActivityName);
dest.writeInt(persistableMode);
dest.writeInt(maxRecents);
+ dest.writeInt(resizeable ? 1 : 0);
}
public static final Parcelable.Creator<ActivityInfo> CREATOR
@@ -757,5 +765,6 @@ public class ActivityInfo extends ComponentInfo
parentActivityName = source.readString();
persistableMode = source.readInt();
maxRecents = source.readInt();
+ resizeable = (source.readInt() == 1);
}
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 5c09b42..b76e8c0 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -49,6 +49,7 @@ import android.util.Pair;
import android.util.Slog;
import android.util.TypedValue;
+import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.XmlUtils;
@@ -2946,20 +2947,19 @@ public class PackageParser {
XmlPullParser parser, AttributeSet attrs, int flags, String[] outError,
boolean receiver, boolean hardwareAccelerated)
throws XmlPullParserException, IOException {
- TypedArray sa = res.obtainAttributes(attrs,
- com.android.internal.R.styleable.AndroidManifestActivity);
+ TypedArray sa = res.obtainAttributes(attrs, R.styleable.AndroidManifestActivity);
if (mParseActivityArgs == null) {
mParseActivityArgs = new ParseComponentArgs(owner, outError,
- com.android.internal.R.styleable.AndroidManifestActivity_name,
- com.android.internal.R.styleable.AndroidManifestActivity_label,
- com.android.internal.R.styleable.AndroidManifestActivity_icon,
- com.android.internal.R.styleable.AndroidManifestActivity_logo,
- com.android.internal.R.styleable.AndroidManifestActivity_banner,
+ R.styleable.AndroidManifestActivity_name,
+ R.styleable.AndroidManifestActivity_label,
+ R.styleable.AndroidManifestActivity_icon,
+ R.styleable.AndroidManifestActivity_logo,
+ R.styleable.AndroidManifestActivity_banner,
mSeparateProcesses,
- com.android.internal.R.styleable.AndroidManifestActivity_process,
- com.android.internal.R.styleable.AndroidManifestActivity_description,
- com.android.internal.R.styleable.AndroidManifestActivity_enabled);
+ R.styleable.AndroidManifestActivity_process,
+ R.styleable.AndroidManifestActivity_description,
+ R.styleable.AndroidManifestActivity_enabled);
}
mParseActivityArgs.tag = receiver ? "<receiver>" : "<activity>";
@@ -2972,22 +2972,18 @@ public class PackageParser {
return null;
}
- boolean setExported = sa.hasValue(
- com.android.internal.R.styleable.AndroidManifestActivity_exported);
+ boolean setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
if (setExported) {
- a.info.exported = sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_exported, false);
+ a.info.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported, false);
}
- a.info.theme = sa.getResourceId(
- com.android.internal.R.styleable.AndroidManifestActivity_theme, 0);
+ a.info.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
- a.info.uiOptions = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestActivity_uiOptions,
+ a.info.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
a.info.applicationInfo.uiOptions);
String parentName = sa.getNonConfigurationString(
- com.android.internal.R.styleable.AndroidManifestActivity_parentActivityName,
+ R.styleable.AndroidManifestActivity_parentActivityName,
Configuration.NATIVE_CONFIG_VERSION);
if (parentName != null) {
String parentClassName = buildClassName(a.info.packageName, parentName, outError);
@@ -3001,8 +2997,7 @@ public class PackageParser {
}
String str;
- str = sa.getNonConfigurationString(
- com.android.internal.R.styleable.AndroidManifestActivity_permission, 0);
+ str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
if (str == null) {
a.info.permission = owner.applicationInfo.permission;
} else {
@@ -3010,146 +3005,111 @@ public class PackageParser {
}
str = sa.getNonConfigurationString(
- com.android.internal.R.styleable.AndroidManifestActivity_taskAffinity,
+ R.styleable.AndroidManifestActivity_taskAffinity,
Configuration.NATIVE_CONFIG_VERSION);
a.info.taskAffinity = buildTaskAffinityName(owner.applicationInfo.packageName,
owner.applicationInfo.taskAffinity, str, outError);
a.info.flags = 0;
if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_multiprocess,
- false)) {
+ R.styleable.AndroidManifestActivity_multiprocess, false)) {
a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
}
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_finishOnTaskLaunch,
- false)) {
+ if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
a.info.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
}
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_clearTaskOnLaunch,
- false)) {
+ if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
a.info.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
}
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_noHistory,
- false)) {
+ if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
a.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
}
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_alwaysRetainTaskState,
- false)) {
+ if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
a.info.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
}
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_stateNotNeeded,
- false)) {
+ if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
a.info.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
}
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_excludeFromRecents,
- false)) {
+ if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
a.info.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
}
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_allowTaskReparenting,
+ if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
(owner.applicationInfo.flags&ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING) != 0)) {
a.info.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
}
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs,
- false)) {
+ if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, false)) {
a.info.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
}
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_showOnLockScreen,
- false)) {
+ if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)) {
a.info.flags |= ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN;
}
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_immersive,
- false)) {
+ if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
a.info.flags |= ActivityInfo.FLAG_IMMERSIVE;
}
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_primaryUserOnly,
- false)) {
+ if (sa.getBoolean(R.styleable.AndroidManifestActivity_primaryUserOnly, false)) {
a.info.flags |= ActivityInfo.FLAG_PRIMARY_USER_ONLY;
}
if (!receiver) {
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_hardwareAccelerated,
+ if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
hardwareAccelerated)) {
a.info.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
}
a.info.launchMode = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestActivity_launchMode,
- ActivityInfo.LAUNCH_MULTIPLE);
+ R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
a.info.documentLaunchMode = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestActivity_documentLaunchMode,
+ R.styleable.AndroidManifestActivity_documentLaunchMode,
ActivityInfo.DOCUMENT_LAUNCH_NONE);
a.info.maxRecents = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestActivity_maxRecents,
+ R.styleable.AndroidManifestActivity_maxRecents,
ActivityManager.getDefaultAppRecentsLimitStatic());
a.info.screenOrientation = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestActivity_screenOrientation,
+ R.styleable.AndroidManifestActivity_screenOrientation,
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
- a.info.configChanges = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestActivity_configChanges,
- 0);
+ a.info.configChanges = sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0);
a.info.softInputMode = sa.getInt(
- com.android.internal.R.styleable.AndroidManifestActivity_windowSoftInputMode,
- 0);
+ R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
a.info.persistableMode = sa.getInteger(
- com.android.internal.R.styleable.AndroidManifestActivity_persistableMode,
+ R.styleable.AndroidManifestActivity_persistableMode,
ActivityInfo.PERSIST_ROOT_ONLY);
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_allowEmbedded,
- false)) {
+ if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
}
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_autoRemoveFromRecents,
- false)) {
+ if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents, false)) {
a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
}
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_relinquishTaskIdentity,
- false)) {
+ if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity, false)) {
a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
}
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_resumeWhilePausing,
- false)) {
+ if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
a.info.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
}
+
+ a.info.resizeable = sa.getBoolean(
+ R.styleable.AndroidManifestActivity_resizeableActivity,
+ owner.applicationInfo.targetSdkVersion >= Build.VERSION_CODES.MNC);
} else {
a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
a.info.configChanges = 0;
- }
- if (receiver) {
- if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestActivity_singleUser,
- false)) {
+ if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
a.info.flags |= ActivityInfo.FLAG_SINGLE_USER;
if (a.info.exported && (flags & PARSE_IS_PRIVILEGED) == 0) {
Slog.w(TAG, "Activity exported request ignored due to singleUser: "
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 0c3fb9a..b9ed78a 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1012,6 +1012,20 @@
<p>The default value of this attribute is <code>false</code>. -->
<attr name="resumeWhilePausing" format="boolean" />
+ <!-- Indicates that it is okay for this activity to be resized to any dimension. Intended for a
+ multi-window device where there can be multiple activities of various sizes on the screen
+ at the same time.
+
+ <p>The default value is <code>false</code> for applications with
+ <code>targetSdkVersion</code> lesser than {@link android.os.Build.VERSION_CODE#MNC} and
+ <code>true</code> otherwise.
+
+ <p>NOTE: A task's root activity value is applied to all additional activities launched in
+ the task. That is if the root activity of a task is resizeable then the system will treat
+ all other activities in the task as resizeable and will not if the root activity isn't
+ resizeable. -->
+ <attr name="resizeableActivity" format="boolean" />
+
<!-- The <code>manifest</code> tag is the root of an
<code>AndroidManifest.xml</code> file,
describing the contents of an Android package (.apk) file. One
@@ -1020,7 +1034,7 @@
to avoid name collisions. For example, applications published
by Google could have names of the form
<code>com.google.app.<em>appname</em></code>
-
+
<p>Inside of the manifest tag, may appear the following tags
in any order: {@link #AndroidManifestPermission permission},
{@link #AndroidManifestPermissionGroup permission-group},
@@ -1039,7 +1053,7 @@
<attr name="sharedUserLabel" />
<attr name="installLocation" />
</declare-styleable>
-
+
<!-- The <code>application</code> tag describes application-level components
contained in the package, as well as general application
attributes. Many of the attributes you can supply here (such
@@ -1047,7 +1061,7 @@
and allowTaskReparenting) serve
as default values for the corresponding attributes of components
declared inside of the application.
-
+
<p>Inside of this element you specify what the application contains,
using the elements {@link #AndroidManifestProvider provider},
{@link #AndroidManifestService service},
@@ -1698,6 +1712,7 @@
<attr name="autoRemoveFromRecents" />
<attr name="relinquishTaskIdentity" />
<attr name="resumeWhilePausing" />
+ <attr name="resizeableActivity" />
</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 461f9a0..11cc181 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2610,6 +2610,7 @@
<public type="attr" name="trackTint" />
<public type="attr" name="trackTintMode" />
+ <public type="attr" name="resizeableActivity" />
<public type="style" name="Widget.Material.Button.Colored" />
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 287cd6f..d857d9c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7830,6 +7830,18 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
+ public void setTaskResizeable(int taskId, boolean resizeable) {
+ synchronized (this) {
+ TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
+ if (task == null) {
+ Slog.w(TAG, "setTaskResizeable: taskId=" + taskId + " not found");
+ return;
+ }
+ task.mResizeable = resizeable;
+ }
+ }
+
+ @Override
public Bitmap getTaskDescriptionIcon(String filename) {
if (!FileUtils.isValidExtFilename(filename)
|| !filename.contains(ActivityRecord.ACTIVITY_ICON_SUFFIX)) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index a3676f9..b3f47e9 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -75,7 +75,6 @@ final class ActivityRecord {
static final boolean DEBUG_SAVED_STATE = ActivityStackSupervisor.DEBUG_SAVED_STATE;
final public static String RECENTS_PACKAGE_NAME = "com.android.systemui.recents";
- private static final String TAG_ACTIVITY = "activity";
private static final String ATTR_ID = "id";
private static final String TAG_INTENT = "intent";
private static final String ATTR_USERID = "user_id";
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 91013ef..73c8439 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -239,6 +239,9 @@ final class ActivityStack {
final ActivityStackSupervisor mStackSupervisor;
Configuration mOverrideConfig;
+ /** True if the stack was forced to full screen because {@link TaskRecord#mResizeable} is false
+ * and the stack was previously resized. */
+ private boolean mForcedFullscreen = false;
static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
@@ -3646,6 +3649,24 @@ final class ActivityStack {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
"Ensuring correct configuration: " + r);
+ // Make sure the current stack override configuration is supported by the top task
+ // before continuing.
+ final TaskRecord topTask = topTask();
+ if (topTask != null && ((topTask.mResizeable && mForcedFullscreen)
+ || (!topTask.mResizeable && !mFullscreen))) {
+ final boolean prevFullscreen = mFullscreen;
+ final Configuration newOverrideConfig =
+ mWindowManager.forceStackToFullscreen(mStackId, !topTask.mResizeable);
+ updateOverrideConfiguration(newOverrideConfig);
+ mForcedFullscreen = !prevFullscreen && mFullscreen;
+ if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
+ "Updated stack config to support task=" + topTask
+ + " resizeable=" + topTask.mResizeable
+ + " mForcedFullscreen=" + mForcedFullscreen
+ + " prevFullscreen=" + prevFullscreen
+ + " mFullscreen=" + mFullscreen);
+ }
+
// Short circuit: if the two configurations are the exact same
// object (the common case), then there is nothing to do.
Configuration newConfig = mService.mConfiguration;
@@ -4121,7 +4142,7 @@ final class ActivityStack {
}
ArrayList<TaskRecord> getAllTasks() {
- return new ArrayList<TaskRecord>(mTaskHistory);
+ return new ArrayList<>(mTaskHistory);
}
void addTask(final TaskRecord task, final boolean toTop, boolean moving) {
@@ -4153,9 +4174,9 @@ final class ActivityStack {
boolean updateOverrideConfiguration(Configuration newConfig) {
Configuration oldConfig = mOverrideConfig;
mOverrideConfig = (newConfig == null) ? Configuration.EMPTY : newConfig;
- // we override the configuration only when the stack's dimensions are different from
- // the display. in this manner, we know that if the override configuration is empty,
- // the stack is necessarily full screen
+ // We override the configuration only when the stack's dimensions are different from
+ // the display. In this manner, we know that if the override configuration is empty,
+ // the stack is necessarily full screen.
mFullscreen = Configuration.EMPTY.equals(mOverrideConfig);
return !mOverrideConfig.equals(oldConfig);
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index b4455b6..b989bc6 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2604,9 +2604,16 @@ public final class ActivityStackSupervisor implements DisplayListener {
Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
return;
}
+
+ final ActivityRecord r = stack.topRunningActivityLocked(null);
+ final TaskRecord topTask = r.task;
+ if (!topTask.mResizeable) {
+ Slog.w(TAG, "resizeStack: top task " + topTask + " not resizeable.");
+ return;
+ }
+
final Configuration overrideConfig = mWindowManager.resizeStack(stackId, bounds);
if (stack.updateOverrideConfiguration(overrideConfig)) {
- final ActivityRecord r = stack.topRunningActivityLocked(null);
if (r != null) {
final boolean updated = stack.ensureActivityConfigurationLocked(r, 0);
// And we need to make sure at this point that all other activities
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 3011148..76bb498 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -79,6 +79,7 @@ final class TaskRecord {
private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color";
private static final String ATTR_CALLING_UID = "calling_uid";
private static final String ATTR_CALLING_PACKAGE = "calling_package";
+ private static final String ATTR_RESIZEABLE = "resizeable";
private static final String TASK_THUMBNAIL_SUFFIX = "_task_thumbnail";
@@ -109,10 +110,12 @@ final class TaskRecord {
String stringName; // caching of toString() result.
int userId; // user for which this task was created
- int creatorUid; // The app uid that originally created the task
int numFullscreen; // Number of fullscreen activities.
+ boolean mResizeable; // Activities in the task resizeable. Based on the resizable setting of
+ // the root activity.
+
// This represents the last resolved activity values for this task
// NOTE: This value needs to be persisted with each task
TaskDescription lastTaskDescription = new TaskDescription();
@@ -176,7 +179,7 @@ final class TaskRecord {
voiceSession = _voiceSession;
voiceInteractor = _voiceInteractor;
isAvailable = true;
- mActivities = new ArrayList<ActivityRecord>();
+ mActivities = new ArrayList<>();
setIntent(_intent, info);
}
@@ -191,7 +194,7 @@ final class TaskRecord {
voiceSession = null;
voiceInteractor = null;
isAvailable = true;
- mActivities = new ArrayList<ActivityRecord>();
+ mActivities = new ArrayList<>();
setIntent(_intent, info);
taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE;
@@ -210,15 +213,15 @@ final class TaskRecord {
mCallingPackage = info.packageName;
}
- TaskRecord(ActivityManagerService service, int _taskId, Intent _intent, Intent _affinityIntent,
- String _affinity, String _rootAffinity, ComponentName _realActivity,
- ComponentName _origActivity, boolean _rootWasReset, boolean _autoRemoveRecents,
- boolean _askedCompatMode, int _taskType, int _userId, int _effectiveUid,
- String _lastDescription, ArrayList<ActivityRecord> activities, long _firstActiveTime,
- long _lastActiveTime, long lastTimeMoved, boolean neverRelinquishIdentity,
- TaskDescription _lastTaskDescription, int taskAffiliation,
- int prevTaskId, int nextTaskId, int taskAffiliationColor, int callingUid,
- String callingPackage) {
+ private TaskRecord(ActivityManagerService service, int _taskId, Intent _intent,
+ Intent _affinityIntent, String _affinity, String _rootAffinity,
+ ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
+ boolean _autoRemoveRecents, boolean _askedCompatMode, int _taskType, int _userId,
+ int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities,
+ long _firstActiveTime, long _lastActiveTime, long lastTimeMoved,
+ boolean neverRelinquishIdentity, TaskDescription _lastTaskDescription,
+ int taskAffiliation, int prevTaskId, int nextTaskId, int taskAffiliationColor,
+ int callingUid, String callingPackage, boolean resizeable) {
mService = service;
mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
TaskPersister.IMAGE_EXTENSION;
@@ -227,7 +230,7 @@ final class TaskRecord {
intent = _intent;
affinityIntent = _affinityIntent;
affinity = _affinity;
- rootAffinity = _affinity;
+ rootAffinity = _rootAffinity;
voiceSession = null;
voiceInteractor = null;
realActivity = _realActivity;
@@ -253,6 +256,7 @@ final class TaskRecord {
mNextAffiliateTaskId = nextTaskId;
mCallingUid = callingUid;
mCallingPackage = callingPackage;
+ mResizeable = resizeable;
}
void touchActiveTime() {
@@ -352,6 +356,7 @@ final class TaskRecord {
} else {
autoRemoveRecents = false;
}
+ mResizeable = info.resizeable;
}
void setTaskToReturnTo(int taskToReturnTo) {
@@ -850,6 +855,7 @@ final class TaskRecord {
out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
+ out.attribute(null, ATTR_RESIZEABLE, String.valueOf(mResizeable));
if (affinityIntent != null) {
out.startTag(null, TAG_AFFINITYINTENT);
@@ -911,6 +917,7 @@ final class TaskRecord {
int nextTaskId = INVALID_TASK_ID;
int callingUid = -1;
String callingPackage = "";
+ boolean resizeable = false;
for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
final String attrName = in.getAttributeName(attrNdx);
@@ -964,6 +971,8 @@ final class TaskRecord {
callingUid = Integer.valueOf(attrValue);
} else if (ATTR_CALLING_PACKAGE.equals(attrName)) {
callingPackage = attrValue;
+ } else if (ATTR_RESIZEABLE.equals(attrName)) {
+ resizeable = Boolean.valueOf(attrValue);
} else {
Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName);
}
@@ -993,13 +1002,11 @@ final class TaskRecord {
}
}
}
-
if (!hasRootAffinity) {
rootAffinity = affinity;
} else if ("@".equals(rootAffinity)) {
rootAffinity = null;
}
-
if (effectiveUid <= 0) {
Intent checkIntent = intent != null ? intent : affinityIntent;
effectiveUid = 0;
@@ -1025,7 +1032,7 @@ final class TaskRecord {
autoRemoveRecents, askedCompatMode, taskType, userId, effectiveUid, lastDescription,
activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
taskDescription, taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor,
- callingUid, callingPackage);
+ callingUid, callingPackage, resizeable);
for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
activities.get(activityNdx).task = task;
@@ -1121,6 +1128,7 @@ final class TaskRecord {
pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
}
pw.print(prefix); pw.print("hasBeenVisible="); pw.print(hasBeenVisible);
+ pw.print(" mResizeable="); pw.print(mResizeable);
pw.print(" firstActiveTime="); pw.print(lastActiveTime);
pw.print(" lastActiveTime="); pw.print(lastActiveTime);
pw.print(" (inactive for ");
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 6660843..59dab08 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -84,11 +84,18 @@ public class TaskStack {
// Contains configurations settings that are different from the global configuration due to
// stack specific operations. E.g. {@link #setBounds}.
Configuration mOverrideConfig;
+ // True if the stack was forced to fullscreen disregarding the override configuration.
+ private boolean mForceFullscreen;
+ // The {@link #mBounds} before the stack was forced to fullscreen. Will be restored as the
+ // stack bounds once the stack is no longer forced to fullscreen.
+ final private Rect mPreForceFullscreenBounds;
TaskStack(WindowManagerService service, int stackId) {
mService = service;
mStackId = stackId;
mOverrideConfig = Configuration.EMPTY;
+ mForceFullscreen = false;
+ mPreForceFullscreenBounds = new Rect();
// TODO: remove bounds from log, they are always 0.
EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId, mBounds.left, mBounds.top,
mBounds.right, mBounds.bottom);
@@ -123,14 +130,24 @@ public class TaskStack {
}
}
+ /** Set the stack bounds. Passing in null sets the bounds to fullscreen. */
boolean setBounds(Rect bounds) {
boolean oldFullscreen = mFullscreen;
if (mDisplayContent != null) {
mDisplayContent.getLogicalDisplayRect(mTmpRect);
- bounds.intersect(mTmpRect); // ensure bounds are entirely within the display rect
- mFullscreen = mTmpRect.equals(bounds);
+ if (bounds == null) {
+ bounds = mTmpRect;
+ mFullscreen = true;
+ } else {
+ bounds.intersect(mTmpRect); // ensure bounds are entirely within the display rect
+ mFullscreen = mTmpRect.equals(bounds);
+ }
}
+ if (bounds == null) {
+ // Can set to fullscreen if we don't have a display to get bounds from...
+ return false;
+ }
if (mBounds.equals(bounds) && oldFullscreen == mFullscreen) {
return false;
}
@@ -146,7 +163,7 @@ public class TaskStack {
out.set(mBounds);
}
- void updateOverrideConfiguration() {
+ private void updateOverrideConfiguration() {
final Configuration serviceConfig = mService.mCurConfiguration;
if (mFullscreen) {
mOverrideConfig = Configuration.EMPTY;
@@ -178,6 +195,28 @@ public class TaskStack {
return mFullscreen;
}
+ /** Forces the stack to fullscreen if input is true, else un-forces the stack from fullscreen.
+ * Returns true if something happened.
+ */
+ boolean forceFullscreen(boolean forceFullscreen) {
+ if (mForceFullscreen == forceFullscreen) {
+ return false;
+ }
+ mForceFullscreen = forceFullscreen;
+ if (forceFullscreen) {
+ if (mFullscreen) {
+ return false;
+ }
+ mPreForceFullscreenBounds.set(mBounds);
+ return setBounds(null);
+ } else {
+ if (!mFullscreen || mPreForceFullscreenBounds.isEmpty()) {
+ return false;
+ }
+ return setBounds(mPreForceFullscreenBounds);
+ }
+ }
+
boolean isAnimating() {
for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 66bef41..a5fee97 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -284,12 +284,6 @@ public class WindowManagerService extends IWindowManager.Stub
// The name of the boot animation service in init.rc.
private static final String BOOT_ANIMATION_SERVICE = "bootanim";
- /** Minimum value for attachStack and resizeStack weight value */
- public static final float STACK_WEIGHT_MIN = 0.2f;
-
- /** Maximum value for attachStack and resizeStack weight value */
- public static final float STACK_WEIGHT_MAX = 0.8f;
-
static final int UPDATE_FOCUS_NORMAL = 0;
static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
@@ -5123,6 +5117,26 @@ public class WindowManagerService extends IWindowManager.Stub
bounds.setEmpty();
}
+ /** Forces the stack to fullscreen if input is true, else un-forces the stack from fullscreen.
+ * Returns a {@link Configuration} object that contains configurations settings
+ * that should be overridden due to the operation.
+ */
+ public Configuration forceStackToFullscreen(int stackId, boolean forceFullscreen) {
+ synchronized (mWindowMap) {
+ final TaskStack stack = mStackIdToStack.get(stackId);
+ if (stack == null) {
+ throw new IllegalArgumentException("resizeStack: stackId " + stackId
+ + " not found.");
+ }
+ if (stack.forceFullscreen(forceFullscreen)) {
+ stack.resizeWindows();
+ stack.getDisplayContent().layoutNeeded = true;
+ performLayoutAndPlaceSurfacesLocked();
+ }
+ return new Configuration(stack.mOverrideConfig);
+ }
+ }
+
// -------------------------------------------------------------
// Misc IWindowSession methods
// -------------------------------------------------------------