diff options
-rw-r--r-- | api/current.txt | 2 | ||||
-rw-r--r-- | api/system-current.txt | 2 | ||||
-rw-r--r-- | cmds/am/src/com/android/commands/am/Am.java | 41 | ||||
-rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 22 | ||||
-rw-r--r-- | core/java/android/app/IActivityManager.java | 2 | ||||
-rw-r--r-- | core/java/android/content/pm/ActivityInfo.java | 9 | ||||
-rw-r--r-- | core/java/android/content/pm/PackageParser.java | 132 | ||||
-rw-r--r-- | core/res/res/values/attrs_manifest.xml | 21 | ||||
-rw-r--r-- | core/res/res/values/public.xml | 1 | ||||
-rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 12 | ||||
-rwxr-xr-x | services/core/java/com/android/server/am/ActivityRecord.java | 1 | ||||
-rw-r--r-- | services/core/java/com/android/server/am/ActivityStack.java | 29 | ||||
-rw-r--r-- | services/core/java/com/android/server/am/ActivityStackSupervisor.java | 9 | ||||
-rw-r--r-- | services/core/java/com/android/server/am/TaskRecord.java | 40 | ||||
-rw-r--r-- | services/core/java/com/android/server/wm/TaskStack.java | 45 | ||||
-rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerService.java | 26 |
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 // ------------------------------------------------------------- |