summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/sm/src/com/android/commands/sm/Sm.java27
-rw-r--r--cmds/statsd/src/atoms.proto2
-rw-r--r--cmds/statsd/src/metrics/CountMetricProducer.cpp2
-rw-r--r--cmds/statsd/src/metrics/DurationMetricProducer.cpp2
-rw-r--r--cmds/statsd/src/metrics/EventMetricProducer.cpp2
-rw-r--r--cmds/statsd/src/metrics/GaugeMetricProducer.cpp2
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.cpp2
-rw-r--r--cmds/statsd/src/stats_log.proto4
-rw-r--r--config/dirty-image-objects2
-rw-r--r--config/preloaded-classes6
-rw-r--r--core/java/android/app/ActivityThread.java42
-rw-r--r--core/java/android/os/FileUtils.java30
-rw-r--r--core/java/android/os/SystemProperties.java28
-rw-r--r--core/java/android/os/storage/StorageManager.java4
-rw-r--r--core/java/android/provider/Settings.java5
-rw-r--r--core/java/android/widget/TextView.java19
-rw-r--r--core/java/com/android/internal/util/ArrayUtils.java7
-rw-r--r--core/jni/fd_utils.cpp6
-rw-r--r--core/tests/coretests/src/android/os/OsTests.java1
-rw-r--r--core/tests/coretests/src/android/os/SystemPropertiesTest.java51
-rw-r--r--core/tests/coretests/src/android/provider/SettingsBackupTest.java4
-rw-r--r--core/tests/systemproperties/src/android/os/SystemPropertiesTest.java29
-rw-r--r--media/java/android/media/session/ISession.aidl2
-rw-r--r--media/java/android/media/session/MediaSession.java14
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java4
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java73
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java3
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecord.java28
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java39
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java22
-rw-r--r--services/core/java/com/android/server/stats/StatsCompanionService.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java43
-rw-r--r--services/core/java/com/android/server/wm/LaunchParamsController.java31
-rw-r--r--services/core/java/com/android/server/wm/RootActivityContainer.java38
-rw-r--r--services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java35
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java25
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java8
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java69
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java17
40 files changed, 441 insertions, 297 deletions
diff --git a/cmds/sm/src/com/android/commands/sm/Sm.java b/cmds/sm/src/com/android/commands/sm/Sm.java
index 783c8c45d603..be5a5bf6c35a 100644
--- a/cmds/sm/src/com/android/commands/sm/Sm.java
+++ b/cmds/sm/src/com/android/commands/sm/Sm.java
@@ -282,14 +282,31 @@ public final class Sm {
StorageManager.DEBUG_VIRTUAL_DISK);
}
- public void runIsolatedStorage() throws RemoteException {
- final boolean enableIsolatedStorage = Boolean.parseBoolean(nextArg());
+ public void runIsolatedStorage() {
+ final int value;
+ final int mask = StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON
+ | StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF;
+ switch (nextArg()) {
+ case "on":
+ case "true":
+ value = StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON;
+ break;
+ case "off":
+ value = StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF;
+ break;
+ case "default":
+ case "false":
+ value = 0;
+ break;
+ default:
+ return;
+ }
+
// Toggling isolated-storage state will result in a device reboot. So to avoid this command
// from erroring out (DeadSystemException), call setDebugFlags() in a separate thread.
new Thread(() -> {
try {
- mSm.setDebugFlags(enableIsolatedStorage ? StorageManager.DEBUG_ISOLATED_STORAGE : 0,
- StorageManager.DEBUG_ISOLATED_STORAGE);
+ mSm.setDebugFlags(value, mask);
} catch (RemoteException e) {
Log.e(TAG, "Encountered an error!", e);
}
@@ -334,7 +351,7 @@ public final class Sm {
System.err.println("");
System.err.println(" sm set-emulate-fbe [true|false]");
System.err.println("");
- System.err.println(" sm set-isolated-storage [true|false]");
+ System.err.println(" sm set-isolated-storage [on|off|default]");
System.err.println("");
return 1;
}
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 9ee078696196..2d0e8bcae5f1 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -2627,6 +2627,8 @@ message NativeProcessMemoryState {
*
* Pulled from StatsCompanionService for all managed processes (from ActivityManagerServie)
* and for selected native processes.
+ *
+ * Pulling this atom resets high-water mark counters for all processes.
*/
message ProcessMemoryHighWaterMark {
// The uid if available. -1 means not available.
diff --git a/cmds/statsd/src/metrics/CountMetricProducer.cpp b/cmds/statsd/src/metrics/CountMetricProducer.cpp
index 14f2de0b1a48..13579d283de0 100644
--- a/cmds/statsd/src/metrics/CountMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/CountMetricProducer.cpp
@@ -49,7 +49,7 @@ const int FIELD_ID_TIME_BASE = 9;
const int FIELD_ID_BUCKET_SIZE = 10;
const int FIELD_ID_DIMENSION_PATH_IN_WHAT = 11;
const int FIELD_ID_DIMENSION_PATH_IN_CONDITION = 12;
-const int FIELD_ID_IS_ACTIVE = 13;
+const int FIELD_ID_IS_ACTIVE = 14;
// for CountMetricDataWrapper
const int FIELD_ID_DATA = 1;
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index 7797bd98961d..0425671b6367 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -48,7 +48,7 @@ const int FIELD_ID_TIME_BASE = 9;
const int FIELD_ID_BUCKET_SIZE = 10;
const int FIELD_ID_DIMENSION_PATH_IN_WHAT = 11;
const int FIELD_ID_DIMENSION_PATH_IN_CONDITION = 12;
-const int FIELD_ID_IS_ACTIVE = 13;
+const int FIELD_ID_IS_ACTIVE = 14;
// for DurationMetricDataWrapper
const int FIELD_ID_DATA = 1;
// for DurationMetricData
diff --git a/cmds/statsd/src/metrics/EventMetricProducer.cpp b/cmds/statsd/src/metrics/EventMetricProducer.cpp
index 31a4361f353d..ea125d02f337 100644
--- a/cmds/statsd/src/metrics/EventMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/EventMetricProducer.cpp
@@ -44,7 +44,7 @@ namespace statsd {
// for StatsLogReport
const int FIELD_ID_ID = 1;
const int FIELD_ID_EVENT_METRICS = 4;
-const int FIELD_ID_IS_ACTIVE = 13;
+const int FIELD_ID_IS_ACTIVE = 14;
// for EventMetricDataWrapper
const int FIELD_ID_DATA = 1;
// for EventMetricData
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 03e42ce76460..98a33f5280e6 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -49,7 +49,7 @@ const int FIELD_ID_TIME_BASE = 9;
const int FIELD_ID_BUCKET_SIZE = 10;
const int FIELD_ID_DIMENSION_PATH_IN_WHAT = 11;
const int FIELD_ID_DIMENSION_PATH_IN_CONDITION = 12;
-const int FIELD_ID_IS_ACTIVE = 13;
+const int FIELD_ID_IS_ACTIVE = 14;
// for GaugeMetricDataWrapper
const int FIELD_ID_DATA = 1;
const int FIELD_ID_SKIPPED = 2;
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index 1f22a6af3a3d..7475b53c0a84 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -52,7 +52,7 @@ const int FIELD_ID_TIME_BASE = 9;
const int FIELD_ID_BUCKET_SIZE = 10;
const int FIELD_ID_DIMENSION_PATH_IN_WHAT = 11;
const int FIELD_ID_DIMENSION_PATH_IN_CONDITION = 12;
-const int FIELD_ID_IS_ACTIVE = 13;
+const int FIELD_ID_IS_ACTIVE = 14;
// for ValueMetricDataWrapper
const int FIELD_ID_DATA = 1;
const int FIELD_ID_SKIPPED = 2;
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index a6f27c8aa535..5a87e46097ae 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -220,7 +220,9 @@ message StatsLogReport {
optional DimensionsValue dimensions_path_in_condition = 12;
- optional bool is_active = 13;
+ // DO NOT USE field 13.
+
+ optional bool is_active = 14;
}
message UidMapping {
diff --git a/config/dirty-image-objects b/config/dirty-image-objects
index 9b4d199dc723..9e2230b288c8 100644
--- a/config/dirty-image-objects
+++ b/config/dirty-image-objects
@@ -44,7 +44,6 @@ java.util.function.ToIntFunction
sun.misc.FormattedFloatingDecimal
java.util.stream.IntStream
android.icu.util.TimeZone
-libcore.io.DropBox
org.apache.harmony.luni.internal.util.TimezoneGetter
dalvik.system.SocketTagger
dalvik.system.CloseGuard
@@ -137,7 +136,6 @@ java.lang.CharSequence
android.icu.util.ULocale
dalvik.system.BaseDexClassLoader
android.icu.text.BreakIterator
-libcore.io.EventLogger
libcore.net.NetworkSecurityPolicy
android.icu.text.UnicodeSet
com.android.org.conscrypt.TrustedCertificateStore$PreloadHolder
diff --git a/config/preloaded-classes b/config/preloaded-classes
index 30959256c922..c8a2a9c19b28 100644
--- a/config/preloaded-classes
+++ b/config/preloaded-classes
@@ -6137,12 +6137,6 @@ libcore.io.BufferIterator
libcore.io.ClassPathURLStreamHandler
libcore.io.ClassPathURLStreamHandler$ClassPathURLConnection
libcore.io.ClassPathURLStreamHandler$ClassPathURLConnection$1
-libcore.io.DropBox
-libcore.io.DropBox$DefaultReporter
-libcore.io.DropBox$Reporter
-libcore.io.EventLogger
-libcore.io.EventLogger$DefaultReporter
-libcore.io.EventLogger$Reporter
libcore.io.ForwardingOs
libcore.io.IoBridge
libcore.io.IoTracker
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index fe9b1ffb378f..1b45d172cb89 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -86,7 +86,6 @@ import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Debug;
-import android.os.DropBoxManager;
import android.os.Environment;
import android.os.FileUtils;
import android.os.GraphicsEnvironment;
@@ -166,8 +165,6 @@ import dalvik.system.CloseGuard;
import dalvik.system.VMDebug;
import dalvik.system.VMRuntime;
-import libcore.io.DropBox;
-import libcore.io.EventLogger;
import libcore.io.ForwardingOs;
import libcore.io.IoUtils;
import libcore.io.Os;
@@ -6726,9 +6723,6 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
- // add dropbox logging to libcore
- DropBox.setReporter(new DropBoxReporter());
-
ViewRootImpl.ConfigChangedCallback configChangedCallback
= (Configuration globalConfig) -> {
synchronized (mResourcesManager) {
@@ -6782,39 +6776,6 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
- private static class EventLoggingReporter implements EventLogger.Reporter {
- @Override
- public void report (int code, Object... list) {
- EventLog.writeEvent(code, list);
- }
- }
-
- private static class DropBoxReporter implements DropBox.Reporter {
-
- private DropBoxManager dropBox;
-
- public DropBoxReporter() {}
-
- @Override
- public void addData(String tag, byte[] data, int flags) {
- ensureInitialized();
- dropBox.addData(tag, data, flags);
- }
-
- @Override
- public void addText(String tag, String data) {
- ensureInitialized();
- dropBox.addText(tag, data);
- }
-
- private synchronized void ensureInitialized() {
- if (dropBox == null) {
- dropBox = currentActivityThread().getApplication()
- .getSystemService(DropBoxManager.class);
- }
- }
- }
-
private static class AndroidOs extends ForwardingOs {
/**
* Install selective syscall interception. For example, this is used to
@@ -6904,9 +6865,6 @@ public final class ActivityThread extends ClientTransactionHandler {
Environment.initForCurrentUser();
- // Set the reporter for event logging in libcore
- EventLogger.setReporter(new EventLoggingReporter());
-
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 567efa7b7afb..428d9e156e37 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -49,6 +49,7 @@ import android.util.Slog;
import android.webkit.MimeTypeMap;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.SizedInputStream;
import libcore.io.IoUtils;
@@ -110,8 +111,6 @@ public class FileUtils {
public static final Pattern SAFE_FILENAME_PATTERN = Pattern.compile("[\\w%+,./=_-]+");
}
- private static final File[] EMPTY = new File[0];
-
// non-final so it can be toggled by Robolectric's ShadowFileUtils
private static boolean sEnableCopyOptimizations = true;
@@ -1164,35 +1163,20 @@ public class FileUtils {
/** {@hide} */
public static @NonNull String[] listOrEmpty(@Nullable File dir) {
- if (dir == null) return EmptyArray.STRING;
- final String[] res = dir.list();
- if (res != null) {
- return res;
- } else {
- return EmptyArray.STRING;
- }
+ return (dir != null) ? ArrayUtils.defeatNullable(dir.list())
+ : EmptyArray.STRING;
}
/** {@hide} */
public static @NonNull File[] listFilesOrEmpty(@Nullable File dir) {
- if (dir == null) return EMPTY;
- final File[] res = dir.listFiles();
- if (res != null) {
- return res;
- } else {
- return EMPTY;
- }
+ return (dir != null) ? ArrayUtils.defeatNullable(dir.listFiles())
+ : ArrayUtils.EMPTY_FILE;
}
/** {@hide} */
public static @NonNull File[] listFilesOrEmpty(@Nullable File dir, FilenameFilter filter) {
- if (dir == null) return EMPTY;
- final File[] res = dir.listFiles(filter);
- if (res != null) {
- return res;
- } else {
- return EMPTY;
- }
+ return (dir != null) ? ArrayUtils.defeatNullable(dir.listFiles(filter))
+ : ArrayUtils.EMPTY_FILE;
}
/** {@hide} */
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index bdc776dd3702..cbcf600f0fb8 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -25,10 +25,15 @@ import android.util.MutableInt;
import com.android.internal.annotations.GuardedBy;
+import libcore.util.HexEncoding;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
-
/**
* Gives access to the system properties store. The system properties
* store contains a list of string key-value pairs.
@@ -232,6 +237,27 @@ public class SystemProperties {
native_report_sysprop_change();
}
+ /**
+ * Return a {@code SHA-1} digest of the given keys and their values as a
+ * hex-encoded string. The ordering of the incoming keys doesn't change the
+ * digest result.
+ *
+ * @hide
+ */
+ public static @NonNull String digestOf(@NonNull String... keys) {
+ Arrays.sort(keys);
+ try {
+ final MessageDigest digest = MessageDigest.getInstance("SHA-1");
+ for (String key : keys) {
+ final String item = key + "=" + get(key) + "\n";
+ digest.update(item.getBytes(StandardCharsets.UTF_8));
+ }
+ return HexEncoding.encodeToString(digest.digest()).toLowerCase();
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
private SystemProperties() {
}
}
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index d315383a5775..8b1d3c6c839f 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -226,7 +226,9 @@ public class StorageManager {
/** {@hide} */
public static final int DEBUG_VIRTUAL_DISK = 1 << 5;
/** {@hide} */
- public static final int DEBUG_ISOLATED_STORAGE = 1 << 6;
+ public static final int DEBUG_ISOLATED_STORAGE_FORCE_ON = 1 << 6;
+ /** {@hide} */
+ public static final int DEBUG_ISOLATED_STORAGE_FORCE_OFF = 1 << 7;
/** {@hide} */
public static final int FLAG_STORAGE_DE = IInstalld.FLAG_STORAGE_DE;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index be304b554043..7f135fb8abb4 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -12964,6 +12964,11 @@ public final class Settings {
public static final String CONTENT_CAPTURE_SERVICE_EXPLICITLY_ENABLED =
"content_capture_service_explicitly_enabled";
+ /** {@hide} */
+ public static final String ISOLATED_STORAGE_LOCAL = "isolated_storage_local";
+ /** {@hide} */
+ public static final String ISOLATED_STORAGE_REMOTE = "isolated_storage_remote";
+
/**
* Settings to backup. This is here so that it's in the same place as the settings
* keys and easy to update.
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index ddf119097027..4574f636306c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -10823,6 +10823,25 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return onTextContextMenuItem(ID_PASTE);
}
break;
+ case KeyEvent.KEYCODE_INSERT:
+ if (canCopy()) {
+ return onTextContextMenuItem(ID_COPY);
+ }
+ break;
+ }
+ } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
+ // Handle Shift-only shortcuts.
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_FORWARD_DEL:
+ if (canCut()) {
+ return onTextContextMenuItem(ID_CUT);
+ }
+ break;
+ case KeyEvent.KEYCODE_INSERT:
+ if (canPaste()) {
+ return onTextContextMenuItem(ID_PASTE);
+ }
+ break;
}
} else if (event.hasModifiers(KeyEvent.META_CTRL_ON | KeyEvent.META_SHIFT_ON)) {
// Handle Ctrl-Shift shortcuts.
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index f669e94c1779..226b8db1540b 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -24,6 +24,7 @@ import dalvik.system.VMRuntime;
import libcore.util.EmptyArray;
+import java.io.File;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
@@ -42,6 +43,8 @@ public class ArrayUtils {
private static final int CACHE_SIZE = 73;
private static Object[] sCache = new Object[CACHE_SIZE];
+ public static final File[] EMPTY_FILE = new File[0];
+
private ArrayUtils() { /* cannot be instantiated */ }
public static byte[] newUnpaddedByteArray(int minLen) {
@@ -645,6 +648,10 @@ public class ArrayUtils {
return (val != null) ? val : EmptyArray.STRING;
}
+ public static @NonNull File[] defeatNullable(@Nullable File[] val) {
+ return (val != null) ? val : EMPTY_FILE;
+ }
+
/**
* Throws {@link ArrayIndexOutOfBoundsException} if the index is out of bounds.
*
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index a398e498a301..33b26899fe81 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -331,11 +331,13 @@ bool FileDescriptorInfo::ReopenOrDetach(std::string* error_msg) const {
return false;
}
- if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) {
+ int dupFlags = (fd_flags & FD_CLOEXEC) ? O_CLOEXEC : 0;
+ if (TEMP_FAILURE_RETRY(dup3(new_fd, fd, dupFlags)) == -1) {
close(new_fd);
- *error_msg = android::base::StringPrintf("Failed dup2(%d, %d) (%s): %s",
+ *error_msg = android::base::StringPrintf("Failed dup3(%d, %d, %d) (%s): %s",
fd,
new_fd,
+ dupFlags,
file_path.c_str(),
strerror(errno));
return false;
diff --git a/core/tests/coretests/src/android/os/OsTests.java b/core/tests/coretests/src/android/os/OsTests.java
index 985fa4f3cfc8..2b841269e5ae 100644
--- a/core/tests/coretests/src/android/os/OsTests.java
+++ b/core/tests/coretests/src/android/os/OsTests.java
@@ -33,7 +33,6 @@ public class OsTests {
suite.addTestSuite(MessageQueueTest.class);
suite.addTestSuite(MessengerTest.class);
suite.addTestSuite(PatternMatcherTest.class);
- suite.addTestSuite(SystemPropertiesTest.class);
return suite;
}
diff --git a/core/tests/coretests/src/android/os/SystemPropertiesTest.java b/core/tests/coretests/src/android/os/SystemPropertiesTest.java
deleted file mode 100644
index 25868ce0b702..000000000000
--- a/core/tests/coretests/src/android/os/SystemPropertiesTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.os;
-
-import static junit.framework.Assert.assertEquals;
-import junit.framework.TestCase;
-
-import android.os.SystemProperties;
-import android.test.suitebuilder.annotation.SmallTest;
-
-public class SystemPropertiesTest extends TestCase {
- private static final String KEY = "com.android.frameworks.coretests";
- @SmallTest
- public void testProperties() throws Exception {
- if (false) {
- String value;
-
- SystemProperties.set(KEY, "");
- value = SystemProperties.get(KEY, "default");
- assertEquals("default", value);
-
- SystemProperties.set(KEY, "AAA");
- value = SystemProperties.get(KEY, "default");
- assertEquals("AAA", value);
-
- value = SystemProperties.get(KEY);
- assertEquals("AAA", value);
-
- SystemProperties.set(KEY, "");
- value = SystemProperties.get(KEY, "default");
- assertEquals("default", value);
-
- value = SystemProperties.get(KEY);
- assertEquals("", value);
- }
- }
-}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 29bc4c4af5d2..6d1aae12d858 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -543,7 +543,9 @@ public class SettingsBackupTest {
Settings.Global.CHAINED_BATTERY_ATTRIBUTION_ENABLED,
Settings.Global.HIDDEN_API_BLACKLIST_EXEMPTIONS,
Settings.Global.BACKUP_AGENT_TIMEOUT_PARAMETERS,
- Settings.Global.BACKUP_MULTI_USER_ENABLED);
+ Settings.Global.BACKUP_MULTI_USER_ENABLED,
+ Settings.Global.ISOLATED_STORAGE_LOCAL,
+ Settings.Global.ISOLATED_STORAGE_REMOTE);
private static final Set<String> BACKUP_BLACKLISTED_SECURE_SETTINGS =
newHashSet(
Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE,
diff --git a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
index 933e54e840c5..928351e7de8c 100644
--- a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
+++ b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
@@ -16,13 +16,13 @@
package android.os;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
+import android.test.suitebuilder.annotation.SmallTest;
import junit.framework.TestCase;
-import android.os.SystemProperties;
-import android.test.suitebuilder.annotation.SmallTest;
+import java.util.Objects;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
public class SystemPropertiesTest extends TestCase {
private static final String KEY = "sys.testkey";
@@ -188,4 +188,25 @@ public class SystemPropertiesTest extends TestCase {
fail("InterruptedException");
}
}
+
+ @SmallTest
+ public void testDigestOf() {
+ final String empty = SystemProperties.digestOf();
+ final String finger = SystemProperties.digestOf("ro.build.fingerprint");
+ final String fingerBrand = SystemProperties.digestOf(
+ "ro.build.fingerprint", "ro.product.brand");
+ final String brandFinger = SystemProperties.digestOf(
+ "ro.product.brand", "ro.build.fingerprint");
+
+ // Shouldn't change over time
+ assertTrue(Objects.equals(finger, SystemProperties.digestOf("ro.build.fingerprint")));
+
+ // Different properties means different results
+ assertFalse(Objects.equals(empty, finger));
+ assertFalse(Objects.equals(empty, fingerBrand));
+ assertFalse(Objects.equals(finger, fingerBrand));
+
+ // Same properties means same result
+ assertTrue(Objects.equals(fingerBrand, brandFinger));
+ }
}
diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl
index bd0019f0f1d8..bfc05fa4e3a4 100644
--- a/media/java/android/media/session/ISession.aidl
+++ b/media/java/android/media/session/ISession.aidl
@@ -39,7 +39,7 @@ interface ISession {
void destroy();
// These commands are for the TransportPerformer
- void setMetadata(in MediaMetadata metadata);
+ void setMetadata(in MediaMetadata metadata, long duration, String metadataDescription);
void setPlaybackState(in PlaybackState state);
void setQueue(in ParceledListSlice queue);
void setQueueTitle(CharSequence title);
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index d43cd309d157..8962bb7fb4c4 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -30,6 +30,7 @@ import android.media.MediaDescription;
import android.media.MediaMetadata;
import android.media.Rating;
import android.media.VolumeProvider;
+import android.media.session.MediaSessionManager.RemoteUserInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -40,7 +41,6 @@ import android.os.Parcelable;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.UserHandle;
-import android.media.session.MediaSessionManager.RemoteUserInfo;
import android.service.media.MediaBrowserService;
import android.text.TextUtils;
import android.util.Log;
@@ -434,11 +434,21 @@ public final class MediaSession {
* @see android.media.MediaMetadata.Builder#putBitmap
*/
public void setMetadata(@Nullable MediaMetadata metadata) {
+ long duration = -1;
+ int fields = 0;
+ MediaDescription description = null;
if (metadata != null) {
metadata = (new MediaMetadata.Builder(metadata, mMaxBitmapSize)).build();
+ if (metadata.containsKey(MediaMetadata.METADATA_KEY_DURATION)) {
+ duration = metadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
+ }
+ fields = metadata.size();
+ description = metadata.getDescription();
}
+ String metadataDescription = "size=" + fields + ", description=" + description;
+
try {
- mBinder.setMetadata(metadata);
+ mBinder.setMetadata(metadata, duration, metadataDescription);
} catch (RemoteException e) {
Log.wtf(TAG, "Dead object in setPlaybackState.", e);
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
index 5c126b1d839b..120acd3bcc52 100644
--- a/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/inputmethod/InputMethodPreference.java
@@ -263,6 +263,10 @@ public class InputMethodPreference extends RestrictedSwitchPreference implements
// The user canceled to enable a 3rd party IME.
setCheckedInternal(false);
});
+ builder.setOnCancelListener((dialog) -> {
+ // The user canceled to enable a 3rd party IME.
+ setCheckedInternal(false);
+ });
mDialog = builder.create();
mDialog.show();
}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 581d4350d28d..6c62725bb5bd 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -57,6 +57,7 @@ import android.app.KeyguardManager;
import android.app.admin.SecurityLog;
import android.app.usage.StorageStatsManager;
import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -777,6 +778,18 @@ class StorageManagerService extends IStorageManager.Stub
}
});
refreshZramSettings();
+
+ // Toggle isolated-enable system property in response to settings
+ mContext.getContentResolver().registerContentObserver(
+ Settings.Global.getUriFor(Settings.Global.ISOLATED_STORAGE_REMOTE),
+ false /*notifyForDescendants*/,
+ new ContentObserver(null /* current thread */) {
+ @Override
+ public void onChange(boolean selfChange) {
+ refreshIsolatedStorageSettings();
+ }
+ });
+ refreshIsolatedStorageSettings();
}
/**
@@ -802,6 +815,32 @@ class StorageManagerService extends IStorageManager.Stub
}
}
+ private void refreshIsolatedStorageSettings() {
+ final int local = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.ISOLATED_STORAGE_LOCAL, 0);
+ final int remote = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.ISOLATED_STORAGE_REMOTE, 0);
+
+ // Walk down precedence chain; we prefer local settings first, then
+ // remote settings, before finally falling back to hard-coded default.
+ final boolean res;
+ if (local == -1) {
+ res = false;
+ } else if (local == 1) {
+ res = true;
+ } else if (remote == -1) {
+ res = false;
+ } else if (remote == 1) {
+ res = true;
+ } else {
+ res = false;
+ }
+
+ Slog.d(TAG, "Isolated storage local flag " + local + " and remote flag "
+ + remote + " resolved to " + res);
+ SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE, Boolean.toString(res));
+ }
+
/**
* MediaProvider has a ton of code that makes assumptions about storage
* paths never changing, so we outright kill them to pick up new state.
@@ -2208,18 +2247,22 @@ class StorageManagerService extends IStorageManager.Stub
}
}
- if ((mask & StorageManager.DEBUG_ISOLATED_STORAGE) != 0) {
- final boolean enabled = (flags & StorageManager.DEBUG_ISOLATED_STORAGE) != 0;
+ if ((mask & (StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON
+ | StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF)) != 0) {
+ final int value;
+ if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_ON) != 0) {
+ value = 1;
+ } else if ((flags & StorageManager.DEBUG_ISOLATED_STORAGE_FORCE_OFF) != 0) {
+ value = -1;
+ } else {
+ value = 0;
+ }
final long token = Binder.clearCallingIdentity();
try {
- SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE,
- Boolean.toString(enabled));
-
- // Some of the storage related permissions get fiddled with during
- // package scanning. So, delete the package cache to force PackageManagerService
- // to do package scanning.
- FileUtils.deleteContents(Environment.getPackageCacheDirectory());
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.ISOLATED_STORAGE_LOCAL, value);
+ refreshIsolatedStorageSettings();
// Perform hard reboot to kick policy into place
mContext.getSystemService(PowerManager.class).reboot(null);
@@ -3758,6 +3801,8 @@ class StorageManagerService extends IStorageManager.Stub
pw.println();
pw.println("Primary storage UUID: " + mPrimaryStorageUuid);
+
+ pw.println();
final Pair<String, Long> pair = StorageManager.getPrimaryStoragePathAndSize();
if (pair == null) {
pw.println("Internal storage total size: N/A");
@@ -3770,8 +3815,18 @@ class StorageManagerService extends IStorageManager.Stub
pw.print(DataUnit.MEBIBYTES.toBytes(pair.second));
pw.println(" MiB)");
}
+
+ pw.println();
pw.println("Local unlocked users: " + Arrays.toString(mLocalUnlockedUsers));
pw.println("System unlocked users: " + Arrays.toString(mSystemUnlockedUsers));
+
+ final ContentResolver cr = mContext.getContentResolver();
+ pw.println();
+ pw.println("Isolated storage, local feature flag: "
+ + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_LOCAL, 0));
+ pw.println("Isolated storage, remote feature flag: "
+ + Settings.Global.getInt(cr, Settings.Global.ISOLATED_STORAGE_REMOTE, 0));
+ pw.println("Isolated storage, resolved: " + StorageManager.hasIsolatedStorage());
}
synchronized (mObbMounts) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 8751d24bcf67..5afb90d681af 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1964,7 +1964,8 @@ public final class ActiveServices {
+ " type=" + resolvedType + " callingUid=" + callingUid);
userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
- ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE, "service", null);
+ ActivityManagerInternal.ALLOW_NON_FULL_IN_PROFILE, "service",
+ callingPackage);
ServiceMap smap = getServiceMapLocked(userId);
final ComponentName comp;
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index c938f5eec94d..c1f3468627cb 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -20,10 +20,10 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
+import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.AudioManagerInternal;
import android.media.AudioSystem;
-import android.media.MediaDescription;
import android.media.MediaMetadata;
import android.media.Rating;
import android.media.VolumeProvider;
@@ -36,7 +36,6 @@ import android.media.session.MediaController.PlaybackInfo;
import android.media.session.MediaSession;
import android.media.session.ParcelableVolumeInfo;
import android.media.session.PlaybackState;
-import android.media.AudioAttributes;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -94,8 +93,9 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
private PendingIntent mLaunchIntent;
// TransportPerformer fields
-
private Bundle mExtras;
+ // Note: Avoid unparceling the bundle inside MediaMetadata since unparceling in system process
+ // may result in throwing an exception.
private MediaMetadata mMetadata;
private PlaybackState mPlaybackState;
private ParceledListSlice mQueue;
@@ -117,6 +117,9 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
private boolean mIsActive = false;
private boolean mDestroyed = false;
+ private long mDuration;
+ private String mMetadataDescription;
+
public MediaSessionRecord(int ownerPid, int ownerUid, int userId, String ownerPackageName,
ISessionCallback cb, String tag, MediaSessionService service, Looper handlerLooper) {
mOwnerPid = ownerPid;
@@ -451,7 +454,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
pw.println(indent + "audioAttrs=" + mAudioAttrs);
pw.println(indent + "volumeType=" + mVolumeType + ", controlType=" + mVolumeControlType
+ ", max=" + mMaxVolume + ", current=" + mCurrentVolume);
- pw.println(indent + "metadata:" + getShortMetadataString());
+ pw.println(indent + "metadata: " + mMetadataDescription);
pw.println(indent + "queueTitle=" + mQueueTitle + ", size="
+ (mQueue == null ? 0 : mQueue.getList().size()));
}
@@ -494,13 +497,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
});
}
- private String getShortMetadataString() {
- int fields = mMetadata == null ? 0 : mMetadata.size();
- MediaDescription description = mMetadata == null ? null : mMetadata
- .getDescription();
- return "size=" + fields + ", description=" + description;
- }
-
private void logCallbackException(
String msg, ISessionControllerCallbackHolder holder, Exception e) {
Log.v(TAG, msg + ", this=" + this + ", callback package=" + holder.mPackageName
@@ -670,12 +666,10 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
private PlaybackState getStateWithUpdatedPosition() {
PlaybackState state;
- long duration = -1;
+ long duration;
synchronized (mLock) {
state = mPlaybackState;
- if (mMetadata != null && mMetadata.containsKey(MediaMetadata.METADATA_KEY_DURATION)) {
- duration = mMetadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
- }
+ duration = mDuration;
}
PlaybackState result = null;
if (state != null) {
@@ -793,7 +787,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
@Override
- public void setMetadata(MediaMetadata metadata) {
+ public void setMetadata(MediaMetadata metadata, long duration, String metadataDescription) {
synchronized (mLock) {
MediaMetadata temp = metadata == null ? null : new MediaMetadata.Builder(metadata)
.build();
@@ -804,6 +798,8 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
temp.size();
}
mMetadata = temp;
+ mDuration = duration;
+ mMetadataDescription = metadataDescription;
}
mHandler.post(MessageHandler.MSG_UPDATE_METADATA);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ae29180a8043..2826e7b8fe2b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -323,6 +323,7 @@ import dalvik.system.VMRuntime;
import libcore.io.IoUtils;
import libcore.util.EmptyArray;
+import libcore.util.HexEncoding;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -591,12 +592,6 @@ public class PackageManagerService extends IPackageManager.Stub
public static final int REASON_LAST = REASON_SHARED;
/**
- * Version number for the package parser cache. Increment this whenever the format or
- * extent of cached data changes. See {@code PackageParser#setCacheDir}.
- */
- private static final String PACKAGE_PARSER_CACHE_VERSION = "1";
-
- /**
* Whether the package parser cache is enabled.
*/
private static final boolean DEFAULT_PACKAGE_PARSER_CACHE_ENABLED = true;
@@ -2329,7 +2324,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- mCacheDir = preparePackageParserCache(mIsUpgrade);
+ mCacheDir = preparePackageParserCache();
// Set flag to monitor and not change apk file paths when
// scanning install directories.
@@ -3196,7 +3191,7 @@ public class PackageManagerService extends IPackageManager.Stub
setUpInstantAppInstallerActivityLP(getInstantAppInstallerLPr());
}
- private static File preparePackageParserCache(boolean isUpgrade) {
+ private static @Nullable File preparePackageParserCache() {
if (!DEFAULT_PACKAGE_PARSER_CACHE_ENABLED) {
return null;
}
@@ -3217,17 +3212,25 @@ public class PackageManagerService extends IPackageManager.Stub
return null;
}
- // If this is a system upgrade scenario, delete the contents of the package cache dir.
- // This also serves to "GC" unused entries when the package cache version changes (which
- // can only happen during upgrades).
- if (isUpgrade) {
- FileUtils.deleteContents(cacheBaseDir);
- }
+ // There are several items that need to be combined together to safely
+ // identify cached items. In particular, changing the value of certain
+ // feature flags should cause us to invalidate any caches.
+ final String cacheName = SystemProperties.digestOf(
+ "ro.build.fingerprint",
+ "persist.sys.isolated_storage");
+ // Reconcile cache directories, keeping only what we'd actually use.
+ for (File cacheDir : FileUtils.listFilesOrEmpty(cacheBaseDir)) {
+ if (Objects.equals(cacheName, cacheDir.getName())) {
+ Slog.d(TAG, "Keeping known cache " + cacheDir.getName());
+ } else {
+ Slog.d(TAG, "Destroying unknown cache " + cacheDir.getName());
+ FileUtils.deleteContentsAndDir(cacheDir);
+ }
+ }
- // Return the versioned package cache directory. This is something like
- // "/data/system/package_cache/1"
- File cacheDir = FileUtils.createDir(cacheBaseDir, PACKAGE_PARSER_CACHE_VERSION);
+ // Return the versioned package cache directory.
+ File cacheDir = FileUtils.createDir(cacheBaseDir, cacheName);
if (cacheDir == null) {
// Something went wrong. Attempt to delete everything and return.
@@ -3253,7 +3256,7 @@ public class PackageManagerService extends IPackageManager.Stub
File frameworkDir = new File(Environment.getRootDirectory(), "framework");
if (cacheDir.lastModified() < frameworkDir.lastModified()) {
FileUtils.deleteContents(cacheBaseDir);
- cacheDir = FileUtils.createDir(cacheBaseDir, PACKAGE_PARSER_CACHE_VERSION);
+ cacheDir = FileUtils.createDir(cacheBaseDir, cacheName);
}
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index d1d5818b8c46..4f20590a47ff 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2691,10 +2691,12 @@ public class UserManagerService extends IUserManager.Stub {
if (!isGuest && !isManagedProfile && !isDemo && isUserLimitReached()) {
// If we're not adding a guest/demo user or a managed profile and the limit has
// been reached, cannot add a user.
+ Log.e(LOG_TAG, "Cannot add user. Maximum user limit is reached.");
return null;
}
// If we're adding a guest and there already exists one, bail.
if (isGuest && findCurrentGuestUser() != null) {
+ Log.e(LOG_TAG, "Cannot add guest user. Guest user already exists.");
return null;
}
// In legacy mode, restricted profile's parent can only be the owner user
@@ -2937,13 +2939,26 @@ public class UserManagerService extends IUserManager.Stub {
final UserData userData;
int currentUser = ActivityManager.getCurrentUser();
if (currentUser == userHandle) {
- Log.w(LOG_TAG, "Current user cannot be removed");
+ Log.w(LOG_TAG, "Current user cannot be removed.");
return false;
}
synchronized (mPackagesLock) {
synchronized (mUsersLock) {
userData = mUsers.get(userHandle);
- if (userHandle == 0 || userData == null || mRemovingUserIds.get(userHandle)) {
+ if (userHandle == UserHandle.USER_SYSTEM) {
+ Log.e(LOG_TAG, "System user cannot be removed.");
+ return false;
+ }
+
+ if (userData == null) {
+ Log.e(LOG_TAG, String.format(
+ "Cannot remove user %d, invalid user id provided.", userHandle));
+ return false;
+ }
+
+ if (mRemovingUserIds.get(userHandle)) {
+ Log.e(LOG_TAG, String.format(
+ "User %d is already scheduled for removal.", userHandle));
return false;
}
@@ -2962,7 +2977,7 @@ public class UserManagerService extends IUserManager.Stub {
try {
mAppOpsService.removeUser(userHandle);
} catch (RemoteException e) {
- Log.w(LOG_TAG, "Unable to notify AppOpsService of removing user", e);
+ Log.w(LOG_TAG, "Unable to notify AppOpsService of removing user.", e);
}
if (userData.info.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
@@ -2986,6 +3001,7 @@ public class UserManagerService extends IUserManager.Stub {
}
});
} catch (RemoteException e) {
+ Log.w(LOG_TAG, "Failed to stop user during removal.", e);
return false;
}
return res == ActivityManager.USER_OP_SUCCESS;
diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java
index f0ebb7512015..4ec8b87be3ac 100644
--- a/services/core/java/com/android/server/stats/StatsCompanionService.java
+++ b/services/core/java/com/android/server/stats/StatsCompanionService.java
@@ -74,6 +74,7 @@ import android.os.StatsDimensionsValue;
import android.os.StatsLogEventWrapper;
import android.os.SynchronousResultReceiver;
import android.os.SystemClock;
+import android.os.SystemProperties;
import android.os.Temperature;
import android.os.UserHandle;
import android.os.UserManager;
@@ -1140,7 +1141,8 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
e.writeLong(rssHighWaterMarkInBytes);
pulledData.add(e);
}
- // TODO(b/119598534): Reset HWM counters here.
+ // Invoke rss_hwm_reset binary to reset RSS HWM counters for all processes.
+ SystemProperties.set("sys.rss_hwm_reset.on", "1");
}
private void pullBinderCallsStats(
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 57bfc2979636..36701ea599dc 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -73,6 +73,8 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_USER_
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
+import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS;
+import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_DISPLAY;
import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.wm.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
@@ -1339,6 +1341,21 @@ class ActivityStarter {
voiceInteractor);
final int preferredWindowingMode = mLaunchParams.mWindowingMode;
+ computeLaunchingTaskFlags();
+
+ computeSourceStack();
+
+ mIntent.setFlags(mLaunchFlags);
+
+ ActivityRecord reusedActivity = getReusableIntentActivity();
+
+ mSupervisor.getLaunchParamsController().calculate(
+ reusedActivity != null ? reusedActivity.getTaskRecord() : mInTask,
+ r.info.windowLayout, r, sourceRecord, options, PHASE_BOUNDS, mLaunchParams);
+ mPreferredDisplayId =
+ mLaunchParams.hasPreferredDisplay() ? mLaunchParams.mPreferredDisplayId
+ : DEFAULT_DISPLAY;
+
// Do not start home activity if it cannot be launched on preferred display. We are not
// doing this in ActivityStackSupervisor#canPlaceEntityOnDisplay because it might
// fallback to launch on other displays.
@@ -1348,14 +1365,6 @@ class ActivityStarter {
return START_CANCELED;
}
- computeLaunchingTaskFlags();
-
- computeSourceStack();
-
- mIntent.setFlags(mLaunchFlags);
-
- ActivityRecord reusedActivity = getReusableIntentActivity();
-
if (reusedActivity != null) {
// When the flags NEW_TASK and CLEAR_TASK are set, then the task gets reused but
// still needs to be a lock task mode violation since the task gets cleared out and
@@ -1651,14 +1660,13 @@ class ActivityStarter {
mLaunchParams.reset();
+ // Preferred display id is the only state we need for now and it could be updated again
+ // after we located a reusable task (which might be resided in another display).
mSupervisor.getLaunchParamsController().calculate(inTask, r.info.windowLayout, r,
- sourceRecord, options, mLaunchParams);
-
- if (mLaunchParams.hasPreferredDisplay()) {
- mPreferredDisplayId = mLaunchParams.mPreferredDisplayId;
- } else {
- mPreferredDisplayId = DEFAULT_DISPLAY;
- }
+ sourceRecord, options, PHASE_DISPLAY, mLaunchParams);
+ mPreferredDisplayId =
+ mLaunchParams.hasPreferredDisplay() ? mLaunchParams.mPreferredDisplayId
+ : DEFAULT_DISPLAY;
mLaunchMode = r.launchMode;
@@ -2502,14 +2510,9 @@ class ActivityStarter {
if (((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) == 0)
|| mPreferredDisplayId != DEFAULT_DISPLAY) {
- // We don't pass in the default display id into the get launch stack call so it can do a
- // full resolution.
- mLaunchParams.mPreferredDisplayId =
- mPreferredDisplayId != DEFAULT_DISPLAY ? mPreferredDisplayId : INVALID_DISPLAY;
final boolean onTop = aOptions == null || !aOptions.getAvoidMoveToFront();
final ActivityStack stack =
mRootActivityContainer.getLaunchStack(r, aOptions, task, onTop, mLaunchParams);
- mLaunchParams.mPreferredDisplayId = mPreferredDisplayId;
return stack;
}
// Otherwise handle adjacent launch.
diff --git a/services/core/java/com/android/server/wm/LaunchParamsController.java b/services/core/java/com/android/server/wm/LaunchParamsController.java
index 09475777cb6e..59c02f736513 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsController.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsController.java
@@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
+import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
@@ -74,7 +75,7 @@ class LaunchParamsController {
* @param result The resulting params.
*/
void calculate(TaskRecord task, WindowLayout layout, ActivityRecord activity,
- ActivityRecord source, ActivityOptions options, LaunchParams result) {
+ ActivityRecord source, ActivityOptions options, int phase, LaunchParams result) {
result.reset();
if (task != null || activity != null) {
@@ -89,7 +90,7 @@ class LaunchParamsController {
mTmpResult.reset();
final LaunchParamsModifier modifier = mModifiers.get(i);
- switch(modifier.onCalculate(task, layout, activity, source, options, mTmpCurrent,
+ switch(modifier.onCalculate(task, layout, activity, source, options, phase, mTmpCurrent,
mTmpResult)) {
case RESULT_SKIP:
// Do not apply any results when we are told to skip
@@ -125,7 +126,7 @@ class LaunchParamsController {
boolean layoutTask(TaskRecord task, WindowLayout layout, ActivityRecord activity,
ActivityRecord source, ActivityOptions options) {
- calculate(task, layout, activity, source, options, mTmpParams);
+ calculate(task, layout, activity, source, options, PHASE_BOUNDS, mTmpParams);
// No changes, return.
if (mTmpParams.isEmpty()) {
@@ -259,6 +260,25 @@ class LaunchParamsController {
*/
int RESULT_CONTINUE = 2;
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({PHASE_DISPLAY, PHASE_WINDOWING_MODE, PHASE_BOUNDS})
+ @interface Phase {}
+
+ /**
+ * Stops once we are done with preferred display calculation.
+ */
+ int PHASE_DISPLAY = 0;
+
+ /**
+ * Stops once we are done with windowing mode calculation.
+ */
+ int PHASE_WINDOWING_MODE = 1;
+
+ /**
+ * Stops once we are done with window bounds calculation.
+ */
+ int PHASE_BOUNDS = 2;
+
/**
* Returns the launch params that the provided activity launch params should be overridden
* to. {@link LaunchParamsModifier} can use this for various purposes, including: 1)
@@ -277,6 +297,7 @@ class LaunchParamsController {
* launched should have this be non-null.
* @param source the Activity that launched a new task. Could be {@code null}.
* @param options {@link ActivityOptions} used to start the activity with.
+ * @param phase the calculation phase, see {@link LaunchParamsModifier.Phase}
* @param currentParams launching params after the process of last {@link
* LaunchParamsModifier}.
* @param outParams the result params to be set.
@@ -284,7 +305,7 @@ class LaunchParamsController {
*/
@Result
int onCalculate(TaskRecord task, WindowLayout layout, ActivityRecord activity,
- ActivityRecord source, ActivityOptions options, LaunchParams currentParams,
- LaunchParams outParams);
+ ActivityRecord source, ActivityOptions options, @Phase int phase,
+ LaunchParams currentParams, LaunchParams outParams);
}
}
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 84a32fc44c53..d0144fdf670a 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -1615,33 +1615,35 @@ class RootActivityContainer extends ConfigurationContainer
return candidateTask.getStack();
}
+ int windowingMode;
+ if (launchParams != null) {
+ // When launch params is not null, we always defer to its windowing mode. Sometimes
+ // it could be unspecified, which indicates it should inherit windowing mode from
+ // display.
+ windowingMode = launchParams.mWindowingMode;
+ } else {
+ windowingMode = options != null ? options.getLaunchWindowingMode()
+ : r.getWindowingMode();
+ }
+ windowingMode = activityDisplay.validateWindowingMode(windowingMode, r, candidateTask,
+ r.getActivityType());
+
// Return the topmost valid stack on the display.
for (int i = activityDisplay.getChildCount() - 1; i >= 0; --i) {
final ActivityStack stack = activityDisplay.getChildAt(i);
- if (isValidLaunchStack(stack, r)) {
+ if (isValidLaunchStack(stack, r, windowingMode)) {
return stack;
}
}
// If there is no valid stack on the external display - check if new dynamic stack will do.
if (displayId != DEFAULT_DISPLAY) {
- final int windowingMode;
- if (launchParams != null) {
- // When launch params is not null, we always defer to its windowing mode. Sometimes
- // it could be unspecified, which indicates it should inherit windowing mode from
- // display.
- windowingMode = launchParams.mWindowingMode;
- } else {
- windowingMode = options != null ? options.getLaunchWindowingMode()
- : r.getWindowingMode();
- }
final int activityType =
options != null && options.getLaunchActivityType() != ACTIVITY_TYPE_UNDEFINED
? options.getLaunchActivityType() : r.getActivityType();
return activityDisplay.createStack(windowingMode, activityType, true /*onTop*/);
}
- Slog.w(TAG, "getValidLaunchStackOnDisplay: can't launch on displayId " + displayId);
return null;
}
@@ -1653,7 +1655,7 @@ class RootActivityContainer extends ConfigurationContainer
}
// TODO: Can probably be consolidated into getLaunchStack()...
- private boolean isValidLaunchStack(ActivityStack stack, ActivityRecord r) {
+ private boolean isValidLaunchStack(ActivityStack stack, ActivityRecord r, int windowingMode) {
switch (stack.getActivityType()) {
case ACTIVITY_TYPE_HOME: return r.isActivityTypeHome();
case ACTIVITY_TYPE_RECENTS: return r.isActivityTypeRecents();
@@ -1661,11 +1663,13 @@ class RootActivityContainer extends ConfigurationContainer
}
// There is a 1-to-1 relationship between stack and task when not in
// primary split-windowing mode.
- if (stack.getWindowingMode() != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
- return false;
- } else {
- return r.supportsSplitScreenWindowingMode();
+ if (stack.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ && r.supportsSplitScreenWindowingMode()
+ && (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ || windowingMode == WINDOWING_MODE_UNDEFINED)) {
+ return true;
}
+ return false;
}
int resolveActivityType(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index 1fb7979fa3e2..5107b522c33b 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -51,6 +51,7 @@ import android.util.Slog;
import android.view.Gravity;
import android.view.View;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wm.LaunchParamsController.LaunchParams;
import com.android.server.wm.LaunchParamsController.LaunchParamsModifier;
@@ -102,19 +103,27 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
mSupervisor = supervisor;
}
+ @VisibleForTesting
+ int onCalculate(TaskRecord task, ActivityInfo.WindowLayout layout, ActivityRecord activity,
+ ActivityRecord source, ActivityOptions options, LaunchParams currentParams,
+ LaunchParams outParams) {
+ return onCalculate(task, layout, activity, source, options, PHASE_BOUNDS, currentParams,
+ outParams);
+ }
+
@Override
public int onCalculate(TaskRecord task, ActivityInfo.WindowLayout layout,
ActivityRecord activity, ActivityRecord source, ActivityOptions options,
- LaunchParams currentParams, LaunchParams outParams) {
+ int phase, LaunchParams currentParams, LaunchParams outParams) {
initLogBuilder(task, activity);
- final int result = calculate(task, layout, activity, source, options, currentParams,
+ final int result = calculate(task, layout, activity, source, options, phase, currentParams,
outParams);
outputLog();
return result;
}
private int calculate(TaskRecord task, ActivityInfo.WindowLayout layout,
- ActivityRecord activity, ActivityRecord source, ActivityOptions options,
+ ActivityRecord activity, ActivityRecord source, ActivityOptions options, int phase,
LaunchParams currentParams, LaunchParams outParams) {
final ActivityRecord root;
if (task != null) {
@@ -145,6 +154,10 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
+ display.getWindowingMode());
}
+ if (phase == PHASE_DISPLAY) {
+ return RESULT_CONTINUE;
+ }
+
// STEP 2: Resolve launch windowing mode.
// STEP 2.1: Determine if any parameter has specified initial bounds. That might be the
// launch bounds from activity options, or size/gravity passed in layout. It also treats the
@@ -247,6 +260,10 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
outParams.mWindowingMode = launchMode == display.getWindowingMode()
? WINDOWING_MODE_UNDEFINED : launchMode;
+ if (phase == PHASE_WINDOWING_MODE) {
+ return RESULT_CONTINUE;
+ }
+
// STEP 3: Determine final launch bounds based on resolved windowing mode and activity
// requested orientation. We set bounds to empty for fullscreen mode and keep bounds as is
// for all other windowing modes that's not freeform mode. One can read comments in
@@ -288,12 +305,6 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
displayId = optionLaunchId;
}
- if (displayId == INVALID_DISPLAY && source != null) {
- final int sourceDisplayId = source.getDisplayId();
- if (DEBUG) appendLog("display-from-source=" + sourceDisplayId);
- displayId = sourceDisplayId;
- }
-
ActivityStack stack =
(displayId == INVALID_DISPLAY && task != null) ? task.getStack() : null;
if (stack != null) {
@@ -301,6 +312,12 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier {
displayId = stack.mDisplayId;
}
+ if (displayId == INVALID_DISPLAY && source != null) {
+ final int sourceDisplayId = source.getDisplayId();
+ if (DEBUG) appendLog("display-from-source=" + sourceDisplayId);
+ displayId = sourceDisplayId;
+ }
+
if (displayId != INVALID_DISPLAY
&& mSupervisor.mRootActivityContainer.getActivityDisplay(displayId) == null) {
displayId = currentParams.mPreferredDisplayId;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index f86d08965e32..e78c12cfcc78 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2168,11 +2168,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mTmpRect.inset(-delta, -delta);
}
region.set(mTmpRect);
- region.translate(-mWindowFrames.mFrame.left, -mWindowFrames.mFrame.top);
+ cropRegionToStackBoundsIfNeeded(region);
} else {
// Not modal or full screen modal
- getTouchableRegion(region, true /* forSurface */);
+ getTouchableRegion(region);
}
+ // Translate to surface based coordinates.
+ region.translate(-mWindowFrames.mFrame.left, -mWindowFrames.mFrame.top);
return flags;
}
@@ -2809,16 +2811,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
/** Get the touchable region in global coordinates. */
void getTouchableRegion(Region outRegion) {
- getTouchableRegion(outRegion, false /* forSurface */);
- }
-
- /** If {@param forSuface} is {@code true}, the region will be translated to surface based. */
- private void getTouchableRegion(Region outRegion, boolean forSurface) {
- if (inPinnedWindowingMode() && !isFocused()) {
- outRegion.setEmpty();
- return;
- }
-
final Rect frame = mWindowFrames.mFrame;
switch (mTouchableInsets) {
default:
@@ -2833,18 +2825,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
break;
case TOUCHABLE_INSETS_REGION: {
outRegion.set(mGivenTouchableRegion);
+ outRegion.translate(frame.left, frame.top);
break;
}
}
cropRegionToStackBoundsIfNeeded(outRegion);
-
- if (forSurface) {
- if (mTouchableInsets != TOUCHABLE_INSETS_REGION) {
- outRegion.translate(-frame.left, -frame.top);
- }
- outRegion.getBounds(mTmpRect);
- applyInsets(outRegion, mTmpRect, mAttrs.surfaceInsets);
- }
}
private void cropRegionToStackBoundsIfNeeded(Region region) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b3afacbf15ec..bd3dfe96a67e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -5968,9 +5968,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// If set, remove exclusive scopes from all other delegates
if (exclusiveScopes != null && !exclusiveScopes.isEmpty()) {
- for (Map.Entry<String, List<String>> entry : policy.mDelegationMap.entrySet()) {
- final String currentPackage = entry.getKey();
- final List<String> currentScopes = entry.getValue();
+ for (int i = policy.mDelegationMap.size() - 1; i >= 0; --i) {
+ final String currentPackage = policy.mDelegationMap.keyAt(i);
+ final List<String> currentScopes = policy.mDelegationMap.valueAt(i);
if (!currentPackage.equals(delegatePackage)) {
// Iterate through all other delegates
@@ -5978,7 +5978,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// And if this delegate had some exclusive scopes which are now moved
// to the new delegate, notify about its delegation changes.
if (currentScopes.isEmpty()) {
- policy.mDelegationMap.remove(currentPackage);
+ policy.mDelegationMap.removeAt(i);
}
sendDelegationChangedBroadcast(currentPackage,
new ArrayList<>(currentScopes), userId);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index 7c43cf3fba83..61e968d6da00 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -414,10 +414,10 @@ public class ActivityStarterTests extends ActivityTestsBase {
.setActivityOptions(new SafeActivityOptions(options))
.execute();
- // verify that values are passed to the modifier. Values are passed twice -- once for
+ // verify that values are passed to the modifier. Values are passed thrice -- two for
// setting initial state, another when task is created.
- verify(modifier, times(2)).onCalculate(any(), eq(windowLayout), any(), any(), eq(options),
- any(), any());
+ verify(modifier, times(3)).onCalculate(any(), eq(windowLayout), any(), any(), eq(options),
+ anyInt(), any(), any());
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
index 3720c8566e74..8c3dec7f1e75 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LaunchParamsControllerTests.java
@@ -31,6 +31,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_DONE;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
@@ -89,10 +90,10 @@ public class LaunchParamsControllerTests extends ActivityTestsBase {
final WindowLayout layout = new WindowLayout(0, 0, 0, 0, 0, 0, 0);
final ActivityOptions options = mock(ActivityOptions.class);
- mController.calculate(record.getTaskRecord(), layout, record, source, options,
+ mController.calculate(record.getTaskRecord(), layout, record, source, options, PHASE_BOUNDS,
new LaunchParams());
verify(positioner, times(1)).onCalculate(eq(record.getTaskRecord()), eq(layout), eq(record),
- eq(source), eq(options), any(), any());
+ eq(source), eq(options), anyInt(), any(), any());
}
/**
@@ -115,9 +116,9 @@ public class LaunchParamsControllerTests extends ActivityTestsBase {
mPersister.putLaunchParams(userId, name, expected);
mController.calculate(activity.getTaskRecord(), null /*layout*/, activity, null /*source*/,
- null /*options*/, new LaunchParams());
- verify(positioner, times(1)).onCalculate(any(), any(), any(), any(), any(), eq(expected),
- any());
+ null /*options*/, PHASE_BOUNDS, new LaunchParams());
+ verify(positioner, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(),
+ eq(expected), any());
}
/**
@@ -128,14 +129,15 @@ public class LaunchParamsControllerTests extends ActivityTestsBase {
final LaunchParamsModifier
ignoredPositioner = mock(LaunchParamsModifier.class);
final LaunchParamsModifier earlyExitPositioner =
- (task, layout, activity, source, options, currentParams, outParams) -> RESULT_DONE;
+ (task, layout, activity, source, options, phase, currentParams, outParams)
+ -> RESULT_DONE;
mController.registerModifier(ignoredPositioner);
mController.registerModifier(earlyExitPositioner);
mController.calculate(null /*task*/, null /*layout*/, null /*activity*/,
- null /*source*/, null /*options*/, new LaunchParams());
- verify(ignoredPositioner, never()).onCalculate(any(), any(), any(), any(), any(),
+ null /*source*/, null /*options*/, PHASE_BOUNDS, new LaunchParams());
+ verify(ignoredPositioner, never()).onCalculate(any(), any(), any(), any(), any(), anyInt(),
any(), any());
}
@@ -152,20 +154,20 @@ public class LaunchParamsControllerTests extends ActivityTestsBase {
mController.registerModifier(firstPositioner);
mController.calculate(null /*task*/, null /*layout*/, null /*activity*/,
- null /*source*/, null /*options*/, new LaunchParams());
- verify(firstPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), any(),
- any());
+ null /*source*/, null /*options*/, PHASE_BOUNDS, new LaunchParams());
+ verify(firstPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(),
+ any(), any());
final LaunchParamsModifier secondPositioner = spy(earlyExitPositioner);
mController.registerModifier(secondPositioner);
mController.calculate(null /*task*/, null /*layout*/, null /*activity*/,
- null /*source*/, null /*options*/, new LaunchParams());
- verify(firstPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), any(),
- any());
- verify(secondPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), any(),
- any());
+ null /*source*/, null /*options*/, PHASE_BOUNDS, new LaunchParams());
+ verify(firstPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(),
+ any(), any());
+ verify(secondPositioner, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(),
+ any(), any());
}
/**
@@ -187,9 +189,9 @@ public class LaunchParamsControllerTests extends ActivityTestsBase {
mController.registerModifier(positioner2);
mController.calculate(null /*task*/, null /*layout*/, null /*activity*/, null /*source*/,
- null /*options*/, new LaunchParams());
+ null /*options*/, PHASE_BOUNDS, new LaunchParams());
- verify(positioner1, times(1)).onCalculate(any(), any(), any(), any(), any(),
+ verify(positioner1, times(1)).onCalculate(any(), any(), any(), any(), any(), anyInt(),
eq(positioner2.getLaunchParams()), any());
}
@@ -213,7 +215,7 @@ public class LaunchParamsControllerTests extends ActivityTestsBase {
final LaunchParams result = new LaunchParams();
mController.calculate(null /*task*/, null /*layout*/, null /*activity*/, null /*source*/,
- null /*options*/, result);
+ null /*options*/, PHASE_BOUNDS, result);
assertEquals(result, positioner2.getLaunchParams());
}
@@ -232,21 +234,42 @@ public class LaunchParamsControllerTests extends ActivityTestsBase {
// VR activities should always land on default display.
mController.calculate(null /*task*/, null /*layout*/, vrActivity /*activity*/,
- null /*source*/, null /*options*/, result);
+ null /*source*/, null /*options*/, PHASE_BOUNDS, result);
assertEquals(DEFAULT_DISPLAY, result.mPreferredDisplayId);
// Otherwise, always lands on VR 2D display.
final ActivityRecord vr2dActivity = new ActivityBuilder(mService).build();
mController.calculate(null /*task*/, null /*layout*/, vr2dActivity /*activity*/,
- null /*source*/, null /*options*/, result);
+ null /*source*/, null /*options*/, PHASE_BOUNDS, result);
assertEquals(vr2dDisplayId, result.mPreferredDisplayId);
mController.calculate(null /*task*/, null /*layout*/, null /*activity*/, null /*source*/,
- null /*options*/, result);
+ null /*options*/, PHASE_BOUNDS, result);
assertEquals(vr2dDisplayId, result.mPreferredDisplayId);
mService.mVr2dDisplayId = INVALID_DISPLAY;
}
+
+ /**
+ * Ensures that {@link LaunchParamsController} calculates to {@link PHASE_BOUNDS} phase by
+ * default.
+ */
+ @Test
+ public void testCalculatePhase() {
+ final LaunchParamsModifier positioner = mock(LaunchParamsModifier.class);
+ mController.registerModifier(positioner);
+
+ final ActivityRecord record = new ActivityBuilder(mService).build();
+ final ActivityRecord source = new ActivityBuilder(mService).build();
+ final WindowLayout layout = new WindowLayout(0, 0, 0, 0, 0, 0, 0);
+ final ActivityOptions options = mock(ActivityOptions.class);
+
+ mController.calculate(record.getTaskRecord(), layout, record, source, options, PHASE_BOUNDS,
+ new LaunchParams());
+ verify(positioner, times(1)).onCalculate(eq(record.getTaskRecord()), eq(layout), eq(record),
+ eq(source), eq(options), eq(PHASE_BOUNDS), any(), any());
+ }
+
/**
* Ensures that {@link LaunchParamsModifier} requests specifying display id during
* layout are honored.
@@ -348,7 +371,7 @@ public class LaunchParamsControllerTests extends ActivityTestsBase {
@Override
public int onCalculate(TaskRecord task, WindowLayout layout, ActivityRecord activity,
- ActivityRecord source, ActivityOptions options,
+ ActivityRecord source, ActivityOptions options, int phase,
LaunchParams currentParams, LaunchParams outParams) {
outParams.set(mParams);
return mReturnVal;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
index fe632d4ab01e..0bd681bd69a2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -173,6 +173,23 @@ public class TaskLaunchParamsModifierTests extends ActivityTestsBase {
}
@Test
+ public void testUsesTasksDisplayIdPriorToSourceIfSet() {
+ final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FREEFORM);
+ final TestActivityDisplay fullscreenDisplay = createNewActivityDisplay(
+ WINDOWING_MODE_FULLSCREEN);
+
+ mCurrent.mPreferredDisplayId = freeformDisplay.mDisplayId;
+ ActivityRecord reusableActivity = createSourceActivity(fullscreenDisplay);
+ ActivityRecord source = createSourceActivity(freeformDisplay);
+
+ assertEquals(RESULT_CONTINUE, mTarget.onCalculate(reusableActivity.getTaskRecord(),
+ /* layout */ null, mActivity, source, /* options */ null, mCurrent, mResult));
+
+ assertEquals(fullscreenDisplay.mDisplayId, mResult.mPreferredDisplayId);
+ }
+
+ @Test
public void testUsesTaskDisplayIdIfSet() {
final TestActivityDisplay freeformDisplay = createNewActivityDisplay(
WINDOWING_MODE_FREEFORM);