diff options
62 files changed, 1175 insertions, 328 deletions
diff --git a/api/test-current.txt b/api/test-current.txt index 5de6c2ae4c82..22b051bf8c8d 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -4860,7 +4860,9 @@ package android.view { } public final class SurfaceControl implements android.os.Parcelable { + ctor public SurfaceControl(@NonNull android.view.SurfaceControl); method public static long acquireFrameRateFlexibilityToken(); + method public boolean isSameSurface(@NonNull android.view.SurfaceControl); method public static void releaseFrameRateFlexibilityToken(long); } @@ -5213,10 +5215,10 @@ package android.window { method public void onDisplayAreaAppeared(@NonNull android.window.WindowContainerToken); method public void onDisplayAreaVanished(@NonNull android.window.WindowContainerToken); method @RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS) public void registerOrganizer(int); + field public static final int FEATURE_DEFAULT_TASK_CONTAINER = 1; // 0x1 field public static final int FEATURE_ROOT = 0; // 0x0 field public static final int FEATURE_SYSTEM_FIRST = 0; // 0x0 field public static final int FEATURE_SYSTEM_LAST = 10000; // 0x2710 - field public static final int FEATURE_TASK_CONTAINER = 1; // 0x1 field public static final int FEATURE_UNDEFINED = -1; // 0xffffffff field public static final int FEATURE_VENDOR_FIRST = 10001; // 0x2711 field public static final int FEATURE_WINDOW_TOKENS = 2; // 0x2 diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index bd15264c008f..d1995bcd5db2 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -418,7 +418,7 @@ message Atom { AppStandbyBucketChanged app_standby_bucket_changed = 258 [(module) = "framework"]; SharesheetStarted sharesheet_started = 259 [(module) = "framework"]; RankingSelected ranking_selected = 260 [(module) = "framework"]; - TvSettingsUIInteracted tvsettings_ui_interacted = 261; + TvSettingsUIInteracted tvsettings_ui_interacted = 261 [(module) = "tv_settings"]; SdkExtensionStatus sdk_extension_status = 354; } diff --git a/cmds/statsd/src/config/ConfigManager.cpp b/cmds/statsd/src/config/ConfigManager.cpp index 6d9c644bb40e..bbae3fef7934 100644 --- a/cmds/statsd/src/config/ConfigManager.cpp +++ b/cmds/statsd/src/config/ConfigManager.cpp @@ -43,20 +43,23 @@ using android::base::StringPrintf; using std::unique_ptr; struct ConfigReceiverDeathCookie { - ConfigReceiverDeathCookie(sp<ConfigManager> configManager, const ConfigKey& configKey, - const shared_ptr<IPendingIntentRef>& pir): - mConfigManager(configManager), - mConfigKey(configKey), - mPir(pir) {} + ConfigReceiverDeathCookie(const wp<ConfigManager>& configManager, const ConfigKey& configKey, + const shared_ptr<IPendingIntentRef>& pir) : + mConfigManager(configManager), mConfigKey(configKey), mPir(pir) { + } - sp<ConfigManager> mConfigManager; + wp<ConfigManager> mConfigManager; ConfigKey mConfigKey; shared_ptr<IPendingIntentRef> mPir; }; void ConfigManager::configReceiverDied(void* cookie) { auto cookie_ = static_cast<ConfigReceiverDeathCookie*>(cookie); - sp<ConfigManager>& thiz = cookie_->mConfigManager; + sp<ConfigManager> thiz = cookie_->mConfigManager.promote(); + if (!thiz) { + return; + } + ConfigKey& configKey = cookie_->mConfigKey; shared_ptr<IPendingIntentRef>& pir = cookie_->mPir; @@ -74,20 +77,23 @@ void ConfigManager::configReceiverDied(void* cookie) { } struct ActiveConfigChangedReceiverDeathCookie { - ActiveConfigChangedReceiverDeathCookie(sp<ConfigManager> configManager, const int uid, - const shared_ptr<IPendingIntentRef>& pir): - mConfigManager(configManager), - mUid(uid), - mPir(pir) {} + ActiveConfigChangedReceiverDeathCookie(const wp<ConfigManager>& configManager, const int uid, + const shared_ptr<IPendingIntentRef>& pir) : + mConfigManager(configManager), mUid(uid), mPir(pir) { + } - sp<ConfigManager> mConfigManager; + wp<ConfigManager> mConfigManager; int mUid; shared_ptr<IPendingIntentRef> mPir; }; void ConfigManager::activeConfigChangedReceiverDied(void* cookie) { auto cookie_ = static_cast<ActiveConfigChangedReceiverDeathCookie*>(cookie); - sp<ConfigManager>& thiz = cookie_->mConfigManager; + sp<ConfigManager> thiz = cookie_->mConfigManager.promote(); + if (!thiz) { + return; + } + int uid = cookie_->mUid; shared_ptr<IPendingIntentRef>& pir = cookie_->mPir; diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp index 79a7e8d318e2..ebe961014336 100644 --- a/cmds/statsd/src/external/StatsPullerManager.cpp +++ b/cmds/statsd/src/external/StatsPullerManager.cpp @@ -44,19 +44,23 @@ namespace statsd { // Stores the puller as a wp to avoid holding a reference in case it is unregistered and // pullAtomCallbackDied is never called. struct PullAtomCallbackDeathCookie { - PullAtomCallbackDeathCookie(sp<StatsPullerManager> pullerManager, const PullerKey& pullerKey, - const wp<StatsPuller>& puller) - : mPullerManager(pullerManager), mPullerKey(pullerKey), mPuller(puller) { + PullAtomCallbackDeathCookie(const wp<StatsPullerManager>& pullerManager, + const PullerKey& pullerKey, const wp<StatsPuller>& puller) : + mPullerManager(pullerManager), mPullerKey(pullerKey), mPuller(puller) { } - sp<StatsPullerManager> mPullerManager; + wp<StatsPullerManager> mPullerManager; PullerKey mPullerKey; wp<StatsPuller> mPuller; }; void StatsPullerManager::pullAtomCallbackDied(void* cookie) { PullAtomCallbackDeathCookie* cookie_ = static_cast<PullAtomCallbackDeathCookie*>(cookie); - sp<StatsPullerManager>& thiz = cookie_->mPullerManager; + sp<StatsPullerManager> thiz = cookie_->mPullerManager.promote(); + if (!thiz) { + return; + } + const PullerKey& pullerKey = cookie_->mPullerKey; wp<StatsPuller> puller = cookie_->mPuller; diff --git a/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp b/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp index 6aff9ef80a71..4b9bac127dc8 100644 --- a/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp +++ b/cmds/statsd/tests/external/StatsCallbackPuller_test.cpp @@ -190,13 +190,13 @@ TEST_F(StatsCallbackPullerTest, RegisterAndTimeout) { int32_t uid = 123; values.push_back(value); - StatsPullerManager pullerManager; - pullerManager.RegisterPullAtomCallback(uid, pullTagId, pullCoolDownNs, pullTimeoutNs, - vector<int32_t>(), cb); + sp<StatsPullerManager> pullerManager = new StatsPullerManager(); + pullerManager->RegisterPullAtomCallback(uid, pullTagId, pullCoolDownNs, pullTimeoutNs, + vector<int32_t>(), cb); vector<shared_ptr<LogEvent>> dataHolder; int64_t startTimeNs = getElapsedRealtimeNs(); // Returns false, since StatsPuller code will evaluate the timeout. - EXPECT_FALSE(pullerManager.Pull(pullTagId, {uid}, &dataHolder)); + EXPECT_FALSE(pullerManager->Pull(pullTagId, {uid}, &dataHolder)); int64_t endTimeNs = getElapsedRealtimeNs(); int64_t actualPullDurationNs = endTimeNs - startTimeNs; diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 91a857225324..e599a5ce81ef 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -1658,6 +1658,9 @@ public final class SystemServiceRegistry { public final T getService(ContextImpl ctx) { final Object[] cache = ctx.mServiceCache; final int[] gates = ctx.mServiceInitializationStateArray; + boolean interrupted = false; + + T ret = null; for (;;) { boolean doInitialize = false; @@ -1665,7 +1668,8 @@ public final class SystemServiceRegistry { // Return it if we already have a cached instance. T service = (T) cache[mCacheIndex]; if (service != null || gates[mCacheIndex] == ContextImpl.STATE_NOT_FOUND) { - return service; + ret = service; + break; // exit the for (;;) } // If we get here, there's no cached instance. @@ -1708,24 +1712,33 @@ public final class SystemServiceRegistry { cache.notifyAll(); } } - return service; + ret = service; + break; // exit the for (;;) } // The other threads will wait for the first thread to call notifyAll(), // and go back to the top and retry. synchronized (cache) { + // Repeat until the state becomes STATE_READY or STATE_NOT_FOUND. + // We can't respond to interrupts here; just like we can't in the "doInitialize" + // path, so we remember the interrupt state here and re-interrupt later. while (gates[mCacheIndex] < ContextImpl.STATE_READY) { try { + // Clear the interrupt state. + interrupted |= Thread.interrupted(); cache.wait(); } catch (InterruptedException e) { // This shouldn't normally happen, but if someone interrupts the // thread, it will. - Slog.wtf(TAG, "getService() interrupted"); - Thread.currentThread().interrupt(); - return null; + Slog.w(TAG, "getService() interrupted"); + interrupted = true; } } } } + if (interrupted) { + Thread.currentThread().interrupt(); + } + return ret; } public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException; diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index b7b3c4fc8add..5d2c9d18c00c 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -607,6 +607,9 @@ public class Process { * started. * @param pkgDataInfoMap Map from related package names to private data directory * volume UUID and inode number. + * @param whitelistedDataInfoMap Map from whitelisted package names to private data directory + * volume UUID and inode number. + * @param bindMountAppsData whether zygote needs to mount CE and DE data. * @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data. * @param zygoteArgs Additional arguments to supply to the zygote process. * @return An object that describes the result of the attempt to start the process. @@ -631,13 +634,17 @@ public class Process { @Nullable long[] disabledCompatChanges, @Nullable Map<String, Pair<String, Long>> pkgDataInfoMap, + @Nullable Map<String, Pair<String, Long>> + whitelistedDataInfoMap, + boolean bindMountAppsData, boolean bindMountAppStorageDirs, @Nullable String[] zygoteArgs) { return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges, - pkgDataInfoMap, bindMountAppStorageDirs, zygoteArgs); + pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData, + bindMountAppStorageDirs, zygoteArgs); } /** @hide */ @@ -661,7 +668,8 @@ public class Process { runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, packageName, /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, /*isTopApp=*/ false, - disabledCompatChanges, /* pkgDataInfoMap */ null, false, zygoteArgs); + disabledCompatChanges, /* pkgDataInfoMap */ null, + /* whitelistedDataInfoMap */ null, false, false, zygoteArgs); } /** diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java index 5f3f14facd75..a4c99c006d80 100644 --- a/core/java/android/os/ZygoteProcess.java +++ b/core/java/android/os/ZygoteProcess.java @@ -333,6 +333,9 @@ public class ZygoteProcess { * started. * @param pkgDataInfoMap Map from related package names to private data directory * volume UUID and inode number. + * @param whitelistedDataInfoMap Map from whitelisted package names to private data directory + * volume UUID and inode number. + * @param bindMountAppsData whether zygote needs to mount CE and DE data. * @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data. * * @param zygoteArgs Additional arguments to supply to the Zygote process. @@ -355,6 +358,9 @@ public class ZygoteProcess { @Nullable long[] disabledCompatChanges, @Nullable Map<String, Pair<String, Long>> pkgDataInfoMap, + @Nullable Map<String, Pair<String, Long>> + whitelistedDataInfoMap, + boolean bindMountAppsData, boolean bindMountAppStorageDirs, @Nullable String[] zygoteArgs) { // TODO (chriswailes): Is there a better place to check this value? @@ -367,7 +373,8 @@ public class ZygoteProcess { runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false, packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges, - pkgDataInfoMap, bindMountAppStorageDirs, zygoteArgs); + pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData, + bindMountAppStorageDirs, zygoteArgs); } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, "Starting VM process through Zygote failed"); @@ -608,6 +615,9 @@ public class ZygoteProcess { * @param disabledCompatChanges a list of disabled compat changes for the process being started. * @param pkgDataInfoMap Map from related package names to private data directory volume UUID * and inode number. + * @param whitelistedDataInfoMap Map from whitelisted package names to private data directory + * volume UUID and inode number. + * @param bindMountAppsData whether zygote needs to mount CE and DE data. * @param bindMountAppStorageDirs whether zygote needs to mount Android/obb and Android/data. * @param extraArgs Additional arguments to supply to the zygote process. * @return An object that describes the result of the attempt to start the process. @@ -631,6 +641,9 @@ public class ZygoteProcess { @Nullable long[] disabledCompatChanges, @Nullable Map<String, Pair<String, Long>> pkgDataInfoMap, + @Nullable Map<String, Pair<String, Long>> + whitelistedDataInfoMap, + boolean bindMountAppsData, boolean bindMountAppStorageDirs, @Nullable String[] extraArgs) throws ZygoteStartFailedEx { @@ -728,11 +741,33 @@ public class ZygoteProcess { } argsForZygote.add(sb.toString()); } + if (whitelistedDataInfoMap != null && whitelistedDataInfoMap.size() > 0) { + StringBuilder sb = new StringBuilder(); + sb.append(Zygote.WHITELISTED_DATA_INFO_MAP); + sb.append("="); + boolean started = false; + for (Map.Entry<String, Pair<String, Long>> entry : whitelistedDataInfoMap.entrySet()) { + if (started) { + sb.append(','); + } + started = true; + sb.append(entry.getKey()); + sb.append(','); + sb.append(entry.getValue().first); + sb.append(','); + sb.append(entry.getValue().second); + } + argsForZygote.add(sb.toString()); + } if (bindMountAppStorageDirs) { argsForZygote.add(Zygote.BIND_MOUNT_APP_STORAGE_DIRS); } + if (bindMountAppsData) { + argsForZygote.add(Zygote.BIND_MOUNT_APP_DATA_DIRS); + } + if (disabledCompatChanges != null && disabledCompatChanges.length > 0) { StringBuilder sb = new StringBuilder(); sb.append("--disabled-compat-changes="); @@ -1291,6 +1326,7 @@ public class ZygoteProcess { true /* startChildZygote */, null /* packageName */, ZYGOTE_POLICY_FLAG_SYSTEM_PROCESS /* zygotePolicyFlags */, false /* isTopApp */, null /* disabledCompatChanges */, null /* pkgDataInfoMap */, + null /* whitelistedDataInfoMap */, false /* bindMountAppsData*/, /* bindMountAppStorageDirs */ false, extraArgs); } catch (ZygoteStartFailedEx ex) { diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java index 69bab4df2cae..6cb93746a9a4 100644 --- a/core/java/android/view/InsetsSourceConsumer.java +++ b/core/java/android/view/InsetsSourceConsumer.java @@ -91,6 +91,8 @@ public class InsetsSourceConsumer { if (mSourceControl == control) { return; } + SurfaceControl oldLeash = mSourceControl != null ? mSourceControl.getLeash() : null; + final InsetsSourceControl lastControl = mSourceControl; mSourceControl = control; @@ -116,6 +118,12 @@ public class InsetsSourceConsumer { // However make sure that the leash visibility is still up to date. if (applyLocalVisibilityOverride()) { mController.notifyVisibilityChanged(); + } + + // If we have a new leash, make sure visibility is up-to-date, even though we + // didn't want to run an animation above. + SurfaceControl newLeash = mSourceControl.getLeash(); + if (oldLeash == null || newLeash == null || !oldLeash.isSameSurface(newLeash)) { applyHiddenToControl(); } } diff --git a/core/java/android/view/InsetsSourceControl.java b/core/java/android/view/InsetsSourceControl.java index f3ec65f997ba..e001b668f71a 100644 --- a/core/java/android/view/InsetsSourceControl.java +++ b/core/java/android/view/InsetsSourceControl.java @@ -44,8 +44,7 @@ public class InsetsSourceControl implements Parcelable { public InsetsSourceControl(InsetsSourceControl other) { mType = other.mType; if (other.mLeash != null) { - mLeash = new SurfaceControl(); - mLeash.copyFrom(other.mLeash); + mLeash = new SurfaceControl(other.mLeash); } else { mLeash = null; } diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index b5f9df72f756..ab65e3a5c849 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -216,6 +216,7 @@ public final class SurfaceControl implements Parcelable { private static native void nativeSetFrameRate( long transactionObj, long nativeObject, float frameRate, int compatibility); + private static native long nativeGetHandle(long nativeObject); private static native long nativeAcquireFrameRateFlexibilityToken(); private static native void nativeReleaseFrameRateFlexibilityToken(long token); @@ -226,6 +227,7 @@ public final class SurfaceControl implements Parcelable { * @hide */ public long mNativeObject; + private long mNativeHandle; // TODO: Move this to native. private final Object mSizeLock = new Object(); @@ -428,12 +430,13 @@ public final class SurfaceControl implements Parcelable { mCloseGuard.open("release"); } mNativeObject = nativeObject; + mNativeHandle = mNativeObject != 0 ? nativeGetHandle(nativeObject) : 0; } /** * @hide */ - public void copyFrom(SurfaceControl other) { + public void copyFrom(@NonNull SurfaceControl other) { mName = other.mName; mWidth = other.mWidth; mHeight = other.mHeight; @@ -853,23 +856,19 @@ public final class SurfaceControl implements Parcelable { throw new OutOfResourcesException( "Couldn't allocate SurfaceControl native object"); } - + mNativeHandle = nativeGetHandle(mNativeObject); mCloseGuard.open("release"); } - /** This is a transfer constructor, useful for transferring a live SurfaceControl native - * object to another Java wrapper which could have some different behavior, e.g. - * event logging. + /** + * Copy constructor. Creates a new native object pointing to the same surface as {@code other}. + * + * @param other The object to copy the surface from. * @hide */ - public SurfaceControl(SurfaceControl other) { - mName = other.mName; - mWidth = other.mWidth; - mHeight = other.mHeight; - mNativeObject = other.mNativeObject; - other.mCloseGuard.close(); - other.mNativeObject = 0; - mCloseGuard.open("release"); + @TestApi + public SurfaceControl(@NonNull SurfaceControl other) { + copyFrom(other); } private SurfaceControl(Parcel in) { @@ -921,6 +920,18 @@ public final class SurfaceControl implements Parcelable { } /** + * Checks whether two {@link SurfaceControl} objects represent the same surface. + * + * @param other The other object to check + * @return {@code true} if these two {@link SurfaceControl} objects represent the same surface. + * @hide + */ + @TestApi + public boolean isSameSurface(@NonNull SurfaceControl other) { + return other.mNativeHandle == mNativeHandle; + } + + /** * Write to a protocol buffer output stream. Protocol buffer message definition is at {@link * android.view.SurfaceControlProto}. * @@ -977,6 +988,7 @@ public final class SurfaceControl implements Parcelable { if (mNativeObject != 0) { nativeRelease(mNativeObject); mNativeObject = 0; + mNativeHandle = 0; mCloseGuard.close(); } } diff --git a/core/java/android/window/DisplayAreaOrganizer.java b/core/java/android/window/DisplayAreaOrganizer.java index eee222b9bf4c..6ae70b779960 100644 --- a/core/java/android/window/DisplayAreaOrganizer.java +++ b/core/java/android/window/DisplayAreaOrganizer.java @@ -33,8 +33,8 @@ public class DisplayAreaOrganizer extends WindowOrganizer { public static final int FEATURE_SYSTEM_FIRST = 0; // The Root display area on a display public static final int FEATURE_ROOT = FEATURE_SYSTEM_FIRST; - // Display area hosting the task container. - public static final int FEATURE_TASK_CONTAINER = FEATURE_SYSTEM_FIRST + 1; + // Display area hosting the default task container. + public static final int FEATURE_DEFAULT_TASK_CONTAINER = FEATURE_SYSTEM_FIRST + 1; // Display area hosting non-activity window tokens. public static final int FEATURE_WINDOW_TOKENS = FEATURE_SYSTEM_FIRST + 2; diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java index ff03f1a1a2ab..505a05eb9c23 100644 --- a/core/java/com/android/internal/os/Zygote.java +++ b/core/java/com/android/internal/os/Zygote.java @@ -205,9 +205,15 @@ public final class Zygote { /** List of packages with the same uid, and its app data info: volume uuid and inode. */ public static final String PKG_DATA_INFO_MAP = "--pkg-data-info-map"; + /** List of whitelisted packages and its app data info: volume uuid and inode. */ + public static final String WHITELISTED_DATA_INFO_MAP = "--whitelisted-data-info-map"; + /** Bind mount app storage dirs to lower fs not via fuse */ public static final String BIND_MOUNT_APP_STORAGE_DIRS = "--bind-mount-storage-dirs"; + /** Bind mount app storage dirs to lower fs not via fuse */ + public static final String BIND_MOUNT_APP_DATA_DIRS = "--bind-mount-data-dirs"; + /** * An extraArg passed when a zygote process is forking a child-zygote, specifying a name * in the abstract socket namespace. This socket name is what the new child zygote @@ -313,6 +319,8 @@ public final class Zygote { * @param isTopApp true if the process is for top (high priority) application. * @param pkgDataInfoList A list that stores related packages and its app data * info: volume uuid and inode. + * @param whitelistedDataInfoList Like pkgDataInfoList, but it's for whitelisted apps. + * @param bindMountAppDataDirs True if the zygote needs to mount data dirs. * @param bindMountAppStorageDirs True if the zygote needs to mount storage dirs. * * @return 0 if this is the child, pid of the child @@ -321,13 +329,15 @@ public final class Zygote { static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir, - boolean isTopApp, String[] pkgDataInfoList, boolean bindMountAppStorageDirs) { + boolean isTopApp, String[] pkgDataInfoList, String[] whitelistedDataInfoList, + boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) { ZygoteHooks.preFork(); int pid = nativeForkAndSpecialize( uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp, - pkgDataInfoList, bindMountAppStorageDirs); + pkgDataInfoList, whitelistedDataInfoList, bindMountAppDataDirs, + bindMountAppStorageDirs); if (pid == 0) { // Note that this event ends at the end of handleChildProc, Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork"); @@ -344,6 +354,7 @@ public final class Zygote { int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp, String[] pkgDataInfoList, + String[] whitelistedDataInfoList, boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs); /** @@ -371,15 +382,19 @@ public final class Zygote { * volume uuid and CE dir inode. For example, pkgDataInfoList = [app_a_pkg_name, * app_a_data_volume_uuid, app_a_ce_inode, app_b_pkg_name, app_b_data_volume_uuid, * app_b_ce_inode, ...]; + * @param whitelistedDataInfoList Like pkgDataInfoList, but it's for whitelisted apps. + * @param bindMountAppDataDirs True if the zygote needs to mount data dirs. * @param bindMountAppStorageDirs True if the zygote needs to mount storage dirs. */ private static void specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp, - String[] pkgDataInfoList, boolean bindMountAppStorageDirs) { + String[] pkgDataInfoList, String[] whitelistedDataInfoList, + boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) { nativeSpecializeAppProcess(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, startChildZygote, instructionSet, appDataDir, isTopApp, - pkgDataInfoList, bindMountAppStorageDirs); + pkgDataInfoList, whitelistedDataInfoList, + bindMountAppDataDirs, bindMountAppStorageDirs); // Note that this event ends at the end of handleChildProc. Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork"); @@ -399,7 +414,8 @@ public final class Zygote { private static native void nativeSpecializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, boolean startChildZygote, String instructionSet, String appDataDir, boolean isTopApp, - String[] pkgDataInfoList, boolean bindMountAppStorageDirs); + String[] pkgDataInfoList, String[] whitelistedDataInfoList, + boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs); /** * Called to do any initialization before starting an application. @@ -724,7 +740,8 @@ public final class Zygote { args.mRuntimeFlags, rlimits, args.mMountExternal, args.mSeInfo, args.mNiceName, args.mStartChildZygote, args.mInstructionSet, args.mAppDataDir, args.mIsTopApp, - args.mPkgDataInfoList, args.mBindMountAppStorageDirs); + args.mPkgDataInfoList, args.mWhitelistedDataInfoList, + args.mBindMountAppDataDirs, args.mBindMountAppStorageDirs); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); @@ -1060,4 +1077,11 @@ public final class Zygote { */ @FastNative public static native int nativeParseSigChld(byte[] in, int length, int[] out); + + /** + * Returns whether the kernel supports tagged pointers. Present in the + * Android Common Kernel from 4.14 and up. By default, you should prefer + * fully-feature Memory Tagging, rather than the static Tagged Pointers. + */ + public static native boolean nativeSupportsTaggedPointers(); } diff --git a/core/java/com/android/internal/os/ZygoteArguments.java b/core/java/com/android/internal/os/ZygoteArguments.java index 1a63765fcaa6..94c1f71a26db 100644 --- a/core/java/com/android/internal/os/ZygoteArguments.java +++ b/core/java/com/android/internal/os/ZygoteArguments.java @@ -227,11 +227,22 @@ class ZygoteArguments { String[] mPkgDataInfoList; /** + * A list that stores all whitelisted app data info: volume uuid and inode. + * Null if it does need to do app data isolation. + */ + String[] mWhitelistedDataInfoList; + + /** * @see Zygote#BIND_MOUNT_APP_STORAGE_DIRS */ boolean mBindMountAppStorageDirs; /** + * @see Zygote#BIND_MOUNT_APP_DATA_DIRS + */ + boolean mBindMountAppDataDirs; + + /** * Constructs instance and parses args * * @param args zygote command-line args @@ -452,8 +463,12 @@ class ZygoteArguments { } } else if (arg.startsWith(Zygote.PKG_DATA_INFO_MAP)) { mPkgDataInfoList = getAssignmentList(arg); + } else if (arg.startsWith(Zygote.WHITELISTED_DATA_INFO_MAP)) { + mWhitelistedDataInfoList = getAssignmentList(arg); } else if (arg.equals(Zygote.BIND_MOUNT_APP_STORAGE_DIRS)) { mBindMountAppStorageDirs = true; + } else if (arg.equals(Zygote.BIND_MOUNT_APP_DATA_DIRS)) { + mBindMountAppDataDirs = true; } else { break; } diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index bc8dfd4aa402..e6a3029c5b2b 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -258,7 +258,8 @@ class ZygoteConnection { parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote, parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mIsTopApp, - parsedArgs.mPkgDataInfoList, parsedArgs.mBindMountAppStorageDirs); + parsedArgs.mPkgDataInfoList, parsedArgs.mWhitelistedDataInfoList, + parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs); try { if (pid == 0) { diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java index ec1f516df5f3..c2b13c971020 100644 --- a/core/java/com/android/internal/os/ZygoteInit.java +++ b/core/java/com/android/internal/os/ZygoteInit.java @@ -757,9 +757,11 @@ public class ZygoteInit { Zygote.applyDebuggerSystemProperty(parsedArgs); Zygote.applyInvokeWithSystemProperty(parsedArgs); - /* Enable pointer tagging in the system server unconditionally. Hardware support for - * this is present in all ARMv8 CPUs; this flag has no effect on other platforms. */ - parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI; + if (Zygote.nativeSupportsTaggedPointers()) { + /* Enable pointer tagging in the system server. Hardware support for this is present + * in all ARMv8 CPUs. */ + parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI; + } /* Enable gwp-asan on the system server with a small probability. This is the same * policy as applied to native processes and system apps. */ diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index b11c4c92ff33..1cfa12df32ab 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -1430,6 +1430,12 @@ static void nativeSetGlobalShadowSettings(JNIEnv* env, jclass clazz, jfloatArray client->setGlobalShadowSettings(ambientColor, spotColor, lightPosY, lightPosZ, lightRadius); } + +static jlong nativeGetHandle(JNIEnv* env, jclass clazz, jlong nativeObject) { + SurfaceControl *surfaceControl = reinterpret_cast<SurfaceControl*>(nativeObject); + return reinterpret_cast<jlong>(surfaceControl->getHandle().get()); +} + // ---------------------------------------------------------------------------- static const JNINativeMethod sSurfaceControlMethods[] = { @@ -1606,6 +1612,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeMirrorSurface }, {"nativeSetGlobalShadowSettings", "([F[FFFF)V", (void*)nativeSetGlobalShadowSettings }, + {"nativeGetHandle", "(J)J", + (void*)nativeGetHandle }, }; int register_android_view_SurfaceControl(JNIEnv* env) diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp index ea3c0fa9fc3c..4b30359e671a 100644 --- a/core/jni/com_android_internal_os_Zygote.cpp +++ b/core/jni/com_android_internal_os_Zygote.cpp @@ -110,7 +110,6 @@ using android::base::StringAppendF; using android::base::StringPrintf; using android::base::WriteStringToFile; using android::base::GetBoolProperty; -using android::base::GetProperty; #define CREATE_ERROR(...) StringPrintf("%s:%d: ", __FILE__, __LINE__). \ append(StringPrintf(__VA_ARGS__)) @@ -170,18 +169,6 @@ static int gSystemServerSocketFd = -1; static constexpr int DEFAULT_DATA_DIR_PERMISSION = 0751; -/** - * Property to control if app data isolation is enabled. - */ -static const std::string ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY = - "persist.zygote.app_data_isolation"; - -/** - * Property to enable app data isolation for sdcard obb or data in vold. - */ -static const std::string ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY = - "persist.sys.vold_app_data_isolation_enabled"; - static constexpr const uint64_t UPPER_HALF_WORD_MASK = 0xFFFF'FFFF'0000'0000; static constexpr const uint64_t LOWER_HALF_WORD_MASK = 0x0000'0000'FFFF'FFFF; @@ -1319,20 +1306,13 @@ static void relabelAllDirs(const char* path, security_context_t context, fail_fn * be decrypted after storage is decrypted. * */ -static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list, - uid_t uid, const char* process_name, jstring managed_nice_name, - fail_fn_t fail_fn) { +static void isolateAppData(JNIEnv* env, const std::vector<std::string>& merged_data_info_list, + uid_t uid, const char* process_name, + jstring managed_nice_name, fail_fn_t fail_fn) { const userid_t userId = multiuser_get_user_id(uid); - auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1); - - int size = (pkg_data_info_list != nullptr) ? env->GetArrayLength(pkg_data_info_list) : 0; - // Size should be a multiple of 3, as it contains list of <package_name, volume_uuid, inode> - if ((size % 3) != 0) { - fail_fn(CREATE_ERROR("Wrong pkg_inode_list size %d", size)); - } - ensureInAppMountNamespace(fail_fn); + int size = merged_data_info_list.size(); // Mount tmpfs on all possible data directories, so app no longer see the original apps data. char internalCePath[PATH_MAX]; @@ -1377,14 +1357,10 @@ static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list, bool legacySymlinkCreated = false; for (int i = 0; i < size; i += 3) { - jstring package_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i)); - std::string packageName = extract_fn(package_str).value(); + std::string const & packageName = merged_data_info_list[i]; + std::string const & volUuid = merged_data_info_list[i + 1]; + std::string const & inode = merged_data_info_list[i + 2]; - jstring vol_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i + 1)); - std::string volUuid = extract_fn(vol_str).value(); - - jstring inode_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i + 2)); - std::string inode = extract_fn(inode_str).value(); std::string::size_type sz; long long ceDataInode = std::stoll(inode, &sz); @@ -1482,6 +1458,48 @@ static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list, freecon(dataDataContext); } +static void insertPackagesToMergedList(JNIEnv* env, + std::vector<std::string>& merged_data_info_list, + jobjectArray data_info_list, const char* process_name, + jstring managed_nice_name, fail_fn_t fail_fn) { + + auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1); + + int size = (data_info_list != nullptr) ? env->GetArrayLength(data_info_list) : 0; + // Size should be a multiple of 3, as it contains list of <package_name, volume_uuid, inode> + if ((size % 3) != 0) { + fail_fn(CREATE_ERROR("Wrong data_info_list size %d", size)); + } + + for (int i = 0; i < size; i += 3) { + jstring package_str = (jstring) (env->GetObjectArrayElement(data_info_list, i)); + std::string packageName = extract_fn(package_str).value(); + merged_data_info_list.push_back(packageName); + + jstring vol_str = (jstring) (env->GetObjectArrayElement(data_info_list, i + 1)); + std::string volUuid = extract_fn(vol_str).value(); + merged_data_info_list.push_back(volUuid); + + jstring inode_str = (jstring) (env->GetObjectArrayElement(data_info_list, i + 2)); + std::string inode = extract_fn(inode_str).value(); + merged_data_info_list.push_back(inode); + } +} + +static void isolateAppData(JNIEnv* env, jobjectArray pkg_data_info_list, + jobjectArray whitelisted_data_info_list, uid_t uid, const char* process_name, + jstring managed_nice_name, fail_fn_t fail_fn) { + + ensureInAppMountNamespace(fail_fn); + std::vector<std::string> merged_data_info_list; + insertPackagesToMergedList(env, merged_data_info_list, pkg_data_info_list, + process_name, managed_nice_name, fail_fn); + insertPackagesToMergedList(env, merged_data_info_list, whitelisted_data_info_list, + process_name, managed_nice_name, fail_fn); + + isolateAppData(env, merged_data_info_list, uid, process_name, managed_nice_name, fail_fn); +} + /** * Like isolateAppData(), isolate jit profile directories, so apps don't see what * other apps are installed by reading content inside /data/misc/profiles/cur. @@ -1594,7 +1612,9 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, jstring managed_nice_name, bool is_system_server, bool is_child_zygote, jstring managed_instruction_set, jstring managed_app_data_dir, bool is_top_app, - jobjectArray pkg_data_info_list, bool mount_storage_dirs) { + jobjectArray pkg_data_info_list, + jobjectArray whitelisted_data_info_list, + bool mount_data_dirs, bool mount_storage_dirs) { const char* process_name = is_system_server ? "system_server" : "zygote"; auto fail_fn = std::bind(ZygoteFailure, env, process_name, managed_nice_name, _1); auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1); @@ -1628,9 +1648,9 @@ static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, // give a null in same_uid_pkgs and private_volumes so they don't need app data isolation. // Isolated process / webview / app zygote should be gated by SELinux and file permission // so they can't even traverse CE / DE directories. - if (pkg_data_info_list != nullptr - && GetBoolProperty(ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY, true)) { - isolateAppData(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn); + if (mount_data_dirs) { + isolateAppData(env, pkg_data_info_list, whitelisted_data_info_list, + uid, process_name, managed_nice_name, fail_fn); isolateJitProfile(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn); } if ((mount_external != MOUNT_EXTERNAL_INSTALLER) && mount_storage_dirs) { @@ -2003,7 +2023,8 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( jint mount_external, jstring se_info, jstring nice_name, jintArray managed_fds_to_close, jintArray managed_fds_to_ignore, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app, - jobjectArray pkg_data_info_list, jboolean mount_storage_dirs) { + jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list, + jboolean mount_data_dirs, jboolean mount_storage_dirs) { jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote); if (UNLIKELY(managed_fds_to_close == nullptr)) { @@ -2041,6 +2062,8 @@ static jint com_android_internal_os_Zygote_nativeForkAndSpecialize( mount_external, se_info, nice_name, false, is_child_zygote == JNI_TRUE, instruction_set, app_data_dir, is_top_app == JNI_TRUE, pkg_data_info_list, + whitelisted_data_info_list, + mount_data_dirs == JNI_TRUE, mount_storage_dirs == JNI_TRUE); } return pid; @@ -2076,7 +2099,8 @@ static jint com_android_internal_os_Zygote_nativeForkSystemServer( permitted_capabilities, effective_capabilities, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true, false, nullptr, nullptr, /* is_top_app= */ false, - /* pkg_data_info_list */ nullptr, false); + /* pkg_data_info_list */ nullptr, + /* whitelisted_data_info_list */ nullptr, false, false); } else if (pid > 0) { // The zygote process checks whether the child process has died or not. ALOGI("System server process %d has been created", pid); @@ -2206,15 +2230,16 @@ static void com_android_internal_os_Zygote_nativeSpecializeAppProcess( jint runtime_flags, jobjectArray rlimits, jint mount_external, jstring se_info, jstring nice_name, jboolean is_child_zygote, jstring instruction_set, jstring app_data_dir, jboolean is_top_app, - jobjectArray pkg_data_info_list, jboolean mount_storage_dirs) { + jobjectArray pkg_data_info_list, jobjectArray whitelisted_data_info_list, + jboolean mount_data_dirs, jboolean mount_storage_dirs) { jlong capabilities = CalculateCapabilities(env, uid, gid, gids, is_child_zygote); SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, capabilities, capabilities, mount_external, se_info, nice_name, false, is_child_zygote == JNI_TRUE, instruction_set, app_data_dir, - is_top_app == JNI_TRUE, pkg_data_info_list, - mount_storage_dirs == JNI_TRUE); + is_top_app == JNI_TRUE, pkg_data_info_list, whitelisted_data_info_list, + mount_data_dirs == JNI_TRUE, mount_storage_dirs == JNI_TRUE); } /** @@ -2405,10 +2430,19 @@ static jint com_android_internal_os_Zygote_nativeParseSigChld(JNIEnv* env, jclas return -1; } +static jboolean com_android_internal_os_Zygote_nativeSupportsTaggedPointers(JNIEnv* env, jclass) { +#ifdef __aarch64__ + int res = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0); + return res >= 0 && res & PR_TAGGED_ADDR_ENABLE; +#else + return false; +#endif +} + static const JNINativeMethod gMethods[] = { {"nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/" - "String;Z[Ljava/lang/String;Z)I", + "String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)I", (void*)com_android_internal_os_Zygote_nativeForkAndSpecialize}, {"nativeForkSystemServer", "(II[II[[IJJ)I", (void*)com_android_internal_os_Zygote_nativeForkSystemServer}, @@ -2421,7 +2455,7 @@ static const JNINativeMethod gMethods[] = { {"nativeForkUsap", "(II[IZ)I", (void*)com_android_internal_os_Zygote_nativeForkUsap}, {"nativeSpecializeAppProcess", "(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/" - "String;Z[Ljava/lang/String;Z)V", + "String;Z[Ljava/lang/String;[Ljava/lang/String;ZZ)V", (void*)com_android_internal_os_Zygote_nativeSpecializeAppProcess}, {"nativeInitNativeState", "(Z)V", (void*)com_android_internal_os_Zygote_nativeInitNativeState}, @@ -2440,6 +2474,8 @@ static const JNINativeMethod gMethods[] = { (void*)com_android_internal_os_Zygote_nativeBoostUsapPriority}, {"nativeParseSigChld", "([BI[I)I", (void*)com_android_internal_os_Zygote_nativeParseSigChld}, + {"nativeSupportsTaggedPointers", "()Z", + (void*)com_android_internal_os_Zygote_nativeSupportsTaggedPointers}, }; int register_com_android_internal_os_Zygote(JNIEnv* env) { diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java index cbb379bf8207..d432dda4a1be 100644 --- a/core/tests/coretests/src/android/view/InsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -696,8 +696,7 @@ public class InsetsControllerTest { // Simulate binder behavior by copying SurfaceControl. Otherwise, InsetsController will // attempt to release mLeash directly. - SurfaceControl copy = new SurfaceControl(); - copy.copyFrom(mLeash); + SurfaceControl copy = new SurfaceControl(mLeash); return new InsetsSourceControl(type, copy, new Point()); } diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 59bdf3dad43e..0389639e9edb 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -137,6 +137,7 @@ applications that come with the platform <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE" /> <permission name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" /> <permission name="android.permission.PACKAGE_USAGE_STATS" /> + <permission name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" /> </privapp-permissions> <privapp-permissions package="com.android.phone"> diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index 415092623531..75ea0cbada92 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -47,10 +47,10 @@ interface ILocationManager Location getLastLocation(in LocationRequest request, String packageName, String featureId); boolean getCurrentLocation(in LocationRequest request, in ICancellationSignal cancellationSignal, in ILocationListener listener, - String packageName, String featureId); + String packageName, String featureId, String listenerId); void requestLocationUpdates(in LocationRequest request, in ILocationListener listener, - in PendingIntent intent, String packageName, String featureId); + in PendingIntent intent, String packageName, String featureId, String listenerId); void removeUpdates(in ILocationListener listener, in PendingIntent intent); void requestGeofence(in LocationRequest request, in Geofence geofence, diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index fcbd3e540291..d1b41dfccf63 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -718,7 +718,7 @@ public class LocationManager { currentLocationRequest.setExpireIn(GET_CURRENT_LOCATION_MAX_TIMEOUT_MS); } - GetCurrentLocationTransport listenerTransport = new GetCurrentLocationTransport(executor, + GetCurrentLocationTransport transport = new GetCurrentLocationTransport(executor, consumer); if (cancellationSignal != null) { @@ -729,14 +729,15 @@ public class LocationManager { try { if (mService.getCurrentLocation(currentLocationRequest, remoteCancellationSignal, - listenerTransport, mContext.getPackageName(), mContext.getAttributionTag())) { - listenerTransport.register(mContext.getSystemService(AlarmManager.class), + transport, mContext.getPackageName(), mContext.getAttributionTag(), + transport.getListenerId())) { + transport.register(mContext.getSystemService(AlarmManager.class), remoteCancellationSignal); if (cancellationSignal != null) { - cancellationSignal.setOnCancelListener(listenerTransport::cancel); + cancellationSignal.setOnCancelListener(transport::cancel); } } else { - listenerTransport.fail(); + transport.fail(); } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1175,7 +1176,8 @@ public class LocationManager { boolean registered = false; try { mService.requestLocationUpdates(locationRequest, transport, null, - mContext.getPackageName(), mContext.getAttributionTag()); + mContext.getPackageName(), mContext.getAttributionTag(), + transport.getListenerId()); registered = true; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); @@ -1220,7 +1222,7 @@ public class LocationManager { try { mService.requestLocationUpdates(locationRequest, null, pendingIntent, - mContext.getPackageName(), mContext.getAttributionTag()); + mContext.getPackageName(), mContext.getAttributionTag(), null); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2558,6 +2560,10 @@ public class LocationManager { mRemoteCancellationSignal = null; } + public String getListenerId() { + return mConsumer.getClass().getName() + "@" + System.identityHashCode(mConsumer); + } + public synchronized void register(AlarmManager alarmManager, ICancellationSignal remoteCancellationSignal) { if (mConsumer == null) { @@ -2683,6 +2689,10 @@ public class LocationManager { return mListener; } + public String getListenerId() { + return mListener.getClass().getName() + "@" + System.identityHashCode(mListener); + } + public void register(@NonNull Executor executor) { Preconditions.checkArgument(executor != null, "invalid null executor"); mExecutor = executor; diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java index 23fa645eff16..5442299881c0 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java @@ -120,7 +120,7 @@ public class ImageWallpaper extends WallpaperService { private void init(DozeParameters dozeParameters) { mIsHighEndGfx = ActivityManager.isHighEndGfx(); mDisplayNeedsBlanking = dozeParameters.getDisplayNeedsBlanking(); - mNeedTransition = mIsHighEndGfx && !mDisplayNeedsBlanking; + mNeedTransition = false; // We will preserve EGL context when we are in lock screen or aod // to avoid janking in following transition, we need to release when back to home. @@ -137,7 +137,7 @@ public class ImageWallpaper extends WallpaperService { mRenderer = getRendererInstance(); getDisplayContext().getDisplay().getDisplayInfo(mDisplayInfo); setFixedSizeAllowed(true); - setOffsetNotificationsEnabled(true); + setOffsetNotificationsEnabled(mNeedTransition); updateSurfaceSize(); } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt index d33cd94004fd..8fd840e6cf58 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt @@ -56,13 +56,12 @@ data class RenderInfo( enabled: Boolean, offset: Int = 0 ): RenderInfo { - val (fg, bg) = deviceColorMap.getValue(deviceType) - - val iconKey = if (offset > 0) { + val key = if (offset > 0) { deviceType * BUCKET_SIZE + offset } else deviceType - val iconState = deviceIconMap.getValue(iconKey) + val (fg, bg) = deviceColorMap.getValue(key) + val iconState = deviceIconMap.getValue(key) val resourceId = iconState[enabled] var icon: Drawable? if (resourceId == APP_ICON_ID) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt index 55d3e8372b01..729f934937da 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt @@ -38,6 +38,7 @@ import com.android.systemui.statusbar.phone.BiometricUnlockController import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK import com.android.systemui.statusbar.phone.NotificationShadeWindowController import com.android.systemui.statusbar.phone.PanelExpansionListener +import com.android.systemui.statusbar.phone.ScrimController import com.android.systemui.statusbar.policy.KeyguardStateController import java.io.FileDescriptor import java.io.PrintWriter @@ -107,6 +108,16 @@ class NotificationShadeDepthController @Inject constructor( } /** + * Force stop blur effect when necessary. + */ + private var scrimsVisible: Boolean = false + set(value) { + if (field == value) return + field = value + scheduleUpdate() + } + + /** * Blur radius of the wake-up animation on this frame. */ private var wakeAndUnlockBlurRadius = 0 @@ -142,7 +153,13 @@ class NotificationShadeDepthController @Inject constructor( if (showingHomeControls) { globalActionsRadius = 0 } - val blur = max(shadeRadius.toInt(), globalActionsRadius) + var blur = max(shadeRadius.toInt(), globalActionsRadius) + + // Make blur be 0 if it is necessary to stop blur effect. + if (scrimsVisible) { + blur = 0 + } + blurUtils.applyBlur(blurRoot?.viewRootImpl ?: root.viewRootImpl, blur) try { wallpaperManager.setWallpaperZoomOut(root.windowToken, @@ -202,6 +219,10 @@ class NotificationShadeDepthController @Inject constructor( brightnessMirrorSpring.finishIfRunning() } } + + override fun onDozeAmountChanged(linear: Float, eased: Float) { + wakeAndUnlockBlurRadius = blurUtils.blurRadiusOfRatio(eased) + } } init { @@ -210,6 +231,10 @@ class NotificationShadeDepthController @Inject constructor( keyguardStateController.addCallback(keyguardStateCallback) } statusBarStateController.addCallback(statusBarStateCallback) + notificationShadeWindowController.setScrimsVisibilityListener { + // Stop blur effect when scrims is opaque to avoid unnecessary GPU composition. + visibility -> scrimsVisible = visibility == ScrimController.OPAQUE + } } /** @@ -225,7 +250,8 @@ class NotificationShadeDepthController @Inject constructor( private fun updateShadeBlur() { var newBlur = 0 - if (statusBarStateController.state == StatusBarState.SHADE) { + val state = statusBarStateController.state + if (state == StatusBarState.SHADE || state == StatusBarState.SHADE_LOCKED) { val animatedBlur = Interpolators.SHADE_ANIMATION.getInterpolation( MathUtils.constrain(shadeExpansion / 0.15f, 0f, 1f)) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java index e1e679f06eef..462b42a44c17 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java @@ -61,6 +61,7 @@ import java.lang.ref.WeakReference; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; +import java.util.function.Consumer; import javax.inject.Inject; import javax.inject.Singleton; @@ -92,6 +93,7 @@ public class NotificationShadeWindowController implements Callback, Dumpable, private final State mCurrentState = new State(); private OtherwisedCollapsedListener mListener; private ForcePluginOpenListener mForcePluginOpenListener; + private Consumer<Integer> mScrimsVisibilityListener; private final ArrayList<WeakReference<StatusBarWindowCallback>> mCallbacks = Lists.newArrayList(); @@ -150,6 +152,16 @@ public class NotificationShadeWindowController implements Callback, Dumpable, mCallbacks.add(new WeakReference<StatusBarWindowCallback>(callback)); } + /** + * Register a listener to monitor scrims visibility + * @param listener A listener to monitor scrims visibility + */ + public void setScrimsVisibilityListener(Consumer<Integer> listener) { + if (listener != null && mScrimsVisibilityListener != listener) { + mScrimsVisibilityListener = listener; + } + } + private boolean shouldEnableKeyguardScreenRotation() { Resources res = mContext.getResources(); return SystemProperties.getBoolean("lockscreen.rot_override", false) @@ -477,6 +489,7 @@ public class NotificationShadeWindowController implements Callback, Dumpable, public void setScrimsVisibility(int scrimsVisibility) { mCurrentState.mScrimsVisibility = scrimsVisibility; apply(mCurrentState); + mScrimsVisibilityListener.accept(scrimsVisibility); } /** diff --git a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java index 475023e2506d..5227aaf01249 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java @@ -160,7 +160,7 @@ public class ImageWallpaperTest extends SysuiTestCase { LOW_BMP_HEIGHT /* bmpHeight */, LOW_BMP_WIDTH /* surfaceWidth */, LOW_BMP_HEIGHT /* surfaceHeight */, - true /* assertion */); + false /* assertion */); } @Test @@ -172,7 +172,7 @@ public class ImageWallpaperTest extends SysuiTestCase { INVALID_BMP_HEIGHT /* bmpHeight */, ImageWallpaper.GLEngine.MIN_SURFACE_WIDTH /* surfaceWidth */, ImageWallpaper.GLEngine.MIN_SURFACE_HEIGHT /* surfaceHeight */, - true /* assertion */); + false /* assertion */); } private void verifySurfaceSizeAndAssertTransition(int bmpWidth, int bmpHeight, diff --git a/packages/Tethering/tests/integration/Android.bp b/packages/Tethering/tests/integration/Android.bp index 1a1c30d1d5f9..620261b375d2 100644 --- a/packages/Tethering/tests/integration/Android.bp +++ b/packages/Tethering/tests/integration/Android.bp @@ -39,4 +39,9 @@ android_test { "android.test.base", "android.test.mock", ], + jni_libs: [ + // For mockito extended + "libdexmakerjvmtiagent", + "libstaticjvmtiagent", + ], } diff --git a/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java index dbd68ef77cb7..b02bb23f9807 100644 --- a/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java +++ b/packages/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java @@ -205,7 +205,7 @@ public class EthernetTetheringTest { requestWithStaticIpv4(localAddr, clientAddr)); mTetheringEventCallback.awaitInterfaceTethered(); - assertInterfaceHasIpAddress(iface, clientAddr); + assertInterfaceHasIpAddress(iface, localAddr); byte[] client1 = MacAddress.fromString("1:2:3:4:5:6").toByteArray(); byte[] client2 = MacAddress.fromString("a:b:c:d:e:f").toByteArray(); diff --git a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java index 93bffe9f54e4..52a82dd2a156 100644 --- a/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java +++ b/packages/WallpaperBackup/src/com/android/wallpaperbackup/WallpaperBackupAgent.java @@ -36,10 +36,12 @@ import android.os.FileUtils; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.os.UserHandle; +import android.provider.Settings; import android.util.Slog; import android.util.Xml; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.content.PackageMonitor; import libcore.io.IoUtils; @@ -261,22 +263,7 @@ public class WallpaperBackupAgent extends BackupAgent { // And reset to the wallpaper service we should be using ComponentName wpService = parseWallpaperComponent(infoStage, "wp"); - if (servicePackageExists(wpService)) { - Slog.i(TAG, "Using wallpaper service " + wpService); - mWm.setWallpaperComponent(wpService, UserHandle.USER_SYSTEM); - if (!lockImageStage.exists()) { - // We have a live wallpaper and no static lock image, - // allow live wallpaper to show "through" on lock screen. - mWm.clear(FLAG_LOCK); - } - } else { - // If we've restored a live wallpaper, but the component doesn't exist, - // we should log it as an error so we can easily identify the problem - // in reports from users - if (wpService != null) { - Slog.e(TAG, "Wallpaper service " + wpService + " isn't available."); - } - } + updateWallpaperComponent(wpService, !lockImageStage.exists()); } catch (Exception e) { Slog.e(TAG, "Unable to restore wallpaper: " + e.getMessage()); } finally { @@ -293,6 +280,28 @@ public class WallpaperBackupAgent extends BackupAgent { } } + @VisibleForTesting + void updateWallpaperComponent(ComponentName wpService, boolean applyToLock) throws IOException { + if (servicePackageExists(wpService)) { + Slog.i(TAG, "Using wallpaper service " + wpService); + mWm.setWallpaperComponent(wpService, UserHandle.USER_SYSTEM); + if (applyToLock) { + // We have a live wallpaper and no static lock image, + // allow live wallpaper to show "through" on lock screen. + mWm.clear(FLAG_LOCK); + } + } else { + // If we've restored a live wallpaper, but the component doesn't exist, + // we should log it as an error so we can easily identify the problem + // in reports from users + if (wpService != null) { + applyComponentAtInstall(wpService, applyToLock); + Slog.w(TAG, "Wallpaper service " + wpService + " isn't available. " + + " Will try to apply later"); + } + } + } + private void restoreFromStage(File stage, File info, String hintTag, int which) throws IOException { if (stage.exists()) { @@ -372,7 +381,8 @@ public class WallpaperBackupAgent extends BackupAgent { return (value == null) ? defValue : Integer.parseInt(value); } - private boolean servicePackageExists(ComponentName comp) { + @VisibleForTesting + boolean servicePackageExists(ComponentName comp) { try { if (comp != null) { final IPackageManager pm = AppGlobals.getPackageManager(); @@ -401,4 +411,53 @@ public class WallpaperBackupAgent extends BackupAgent { throws IOException { // Intentionally blank } + + private void applyComponentAtInstall(ComponentName componentName, boolean applyToLock) { + PackageMonitor packageMonitor = getWallpaperPackageMonitor(componentName, applyToLock); + packageMonitor.register(getBaseContext(), null, UserHandle.ALL, true); + } + + @VisibleForTesting + PackageMonitor getWallpaperPackageMonitor(ComponentName componentName, boolean applyToLock) { + return new PackageMonitor() { + @Override + public void onPackageAdded(String packageName, int uid) { + if (!isDeviceInRestore()) { + // We don't want to reapply the wallpaper outside a restore. + unregister(); + return; + } + + if (componentName.getPackageName().equals(packageName)) { + Slog.d(TAG, "Applying component " + componentName); + mWm.setWallpaperComponent(componentName); + if (applyToLock) { + try { + mWm.clear(FLAG_LOCK); + } catch (IOException e) { + Slog.w(TAG, "Failed to apply live wallpaper to lock screen: " + e); + } + } + // We're only expecting to restore the wallpaper component once. + unregister(); + } + } + }; + } + + @VisibleForTesting + boolean isDeviceInRestore() { + try { + boolean isInSetup = Settings.Secure.getInt(getBaseContext().getContentResolver(), + Settings.Secure.USER_SETUP_COMPLETE) == 0; + boolean isInDeferredSetup = Settings.Secure.getInt(getBaseContext() + .getContentResolver(), + Settings.Secure.USER_SETUP_PERSONALIZATION_STATE) == + Settings.Secure.USER_SETUP_PERSONALIZATION_STARTED; + return isInSetup || isInDeferredSetup; + } catch (Settings.SettingNotFoundException e) { + Slog.w(TAG, "Failed to check if the user is in restore: " + e); + return false; + } + } }
\ No newline at end of file diff --git a/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/tests/WallpaperBackupAgentTest.java b/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java index 255fdef36cd7..4367075abc74 100644 --- a/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/tests/WallpaperBackupAgentTest.java +++ b/packages/WallpaperBackup/test/src/com/android/wallpaperbackup/WallpaperBackupAgentTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.wallpaperbackup.tests; +package com.android.wallpaperbackup; import static android.app.WallpaperManager.FLAG_LOCK; import static android.app.WallpaperManager.FLAG_SYSTEM; @@ -26,17 +26,22 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.WallpaperManager; import android.app.backup.FullBackupDataOutput; +import android.content.ComponentName; +import android.content.Context; import android.content.SharedPreferences; import android.os.UserHandle; import androidx.test.core.app.ApplicationProvider; import androidx.test.runner.AndroidJUnit4; +import com.android.internal.content.PackageMonitor; import com.android.wallpaperbackup.WallpaperBackupAgent; import com.android.wallpaperbackup.utils.ContextWithServiceOverrides; @@ -58,6 +63,7 @@ import java.util.List; public class WallpaperBackupAgentTest { private static final String SYSTEM_GENERATION = "system_gen"; private static final String LOCK_GENERATION = "lock_gen"; + private static final String TEST_WALLPAPER_PACKAGE = "wallpaper_package"; private static final int TEST_SYSTEM_WALLPAPER_ID = 1; private static final int TEST_LOCK_WALLPAPER_ID = 2; @@ -66,11 +72,13 @@ public class WallpaperBackupAgentTest { @Mock private WallpaperManager mWallpaperManager; @Mock private SharedPreferences mSharedPreferences; @Mock private SharedPreferences.Editor mSharedPreferenceEditor; + @Mock private Context mMockContext; @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder(); private ContextWithServiceOverrides mContext; private IsolatedWallpaperBackupAgent mWallpaperBackupAgent; + private ComponentName mWallpaperComponent; @Before public void setUp() { @@ -88,6 +96,8 @@ public class WallpaperBackupAgentTest { mWallpaperBackupAgent = new IsolatedWallpaperBackupAgent(mTemporaryFolder.getRoot()); mWallpaperBackupAgent.attach(mContext); mWallpaperBackupAgent.onCreate(); + + mWallpaperComponent = new ComponentName(TEST_WALLPAPER_PACKAGE, ""); } @Test @@ -130,6 +140,69 @@ public class WallpaperBackupAgentTest { inOrder.verify(mSharedPreferenceEditor).apply(); } + @Test + public void updateWallpaperComponent_doesApplyLater() throws IOException { + mWallpaperBackupAgent.mIsDeviceInRestore = true; + + mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent, + /* applyToLock */ true); + + // Imitate wallpaper component installation. + mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(TEST_WALLPAPER_PACKAGE, + /* uid */0); + + verify(mWallpaperManager, times(1)).setWallpaperComponent(mWallpaperComponent); + verify(mWallpaperManager, times(1)).clear(eq(FLAG_LOCK)); + } + + @Test + public void updateWallpaperComponent_applyToLockFalse_doesApplyLaterOnlyToMainScreen() + throws IOException { + mWallpaperBackupAgent.mIsDeviceInRestore = true; + + mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent, + /* applyToLock */ false); + + // Imitate wallpaper component installation. + mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(TEST_WALLPAPER_PACKAGE, + /* uid */0); + + verify(mWallpaperManager, times(1)).setWallpaperComponent(mWallpaperComponent); + verify(mWallpaperManager, never()).clear(eq(FLAG_LOCK)); + } + + @Test + public void updateWallpaperComponent_deviceNotInRestore_doesNotApply() + throws IOException { + mWallpaperBackupAgent.mIsDeviceInRestore = false; + + mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent, + /* applyToLock */ true); + + // Imitate wallpaper component installation. + mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(TEST_WALLPAPER_PACKAGE, + /* uid */0); + + verify(mWallpaperManager, never()).setWallpaperComponent(mWallpaperComponent); + verify(mWallpaperManager, never()).clear(eq(FLAG_LOCK)); + } + + @Test + public void updateWallpaperComponent_differentPackageInstalled_doesNotApply() + throws IOException { + mWallpaperBackupAgent.mIsDeviceInRestore = false; + + mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent, + /* applyToLock */ true); + + // Imitate "wrong" wallpaper component installation. + mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(/* packageName */"", + /* uid */0); + + verify(mWallpaperManager, never()).setWallpaperComponent(mWallpaperComponent); + verify(mWallpaperManager, never()).clear(eq(FLAG_LOCK)); + } + private void mockUnbackedUpState() { mockCurrentWallpapers(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID); when(mSharedPreferences.getInt(eq(SYSTEM_GENERATION), eq(-1))).thenReturn(-1); @@ -162,6 +235,8 @@ public class WallpaperBackupAgentTest { private class IsolatedWallpaperBackupAgent extends WallpaperBackupAgent { File mWallpaperBaseDirectory; List<File> mBackedUpFiles = new ArrayList<>(); + PackageMonitor mWallpaperPackageMonitor; + boolean mIsDeviceInRestore = false; IsolatedWallpaperBackupAgent(File wallpaperBaseDirectory) { mWallpaperBaseDirectory = wallpaperBaseDirectory; @@ -181,5 +256,27 @@ public class WallpaperBackupAgentTest { public SharedPreferences getSharedPreferences(File file, int mode) { return mSharedPreferences; } + + @Override + boolean servicePackageExists(ComponentName comp) { + return false; + } + + @Override + boolean isDeviceInRestore() { + return mIsDeviceInRestore; + } + + @Override + PackageMonitor getWallpaperPackageMonitor(ComponentName componentName, + boolean applyToLock) { + mWallpaperPackageMonitor = super.getWallpaperPackageMonitor(componentName, applyToLock); + return mWallpaperPackageMonitor; + } + + @Override + public Context getBaseContext() { + return mMockContext; + } } } diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 192ea72224b1..3c0d880916ee 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -119,8 +119,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int MESSAGE_DISABLE = 2; private static final int MESSAGE_HANDLE_ENABLE_DELAYED = 3; private static final int MESSAGE_HANDLE_DISABLE_DELAYED = 4; - private static final int MESSAGE_REGISTER_ADAPTER = 20; - private static final int MESSAGE_UNREGISTER_ADAPTER = 21; private static final int MESSAGE_REGISTER_STATE_CHANGE_CALLBACK = 30; private static final int MESSAGE_UNREGISTER_STATE_CHANGE_CALLBACK = 31; private static final int MESSAGE_BLUETOOTH_SERVICE_CONNECTED = 40; @@ -642,10 +640,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { Slog.w(TAG, "Callback is null in registerAdapter"); return null; } - Message msg = mHandler.obtainMessage(MESSAGE_REGISTER_ADAPTER); - msg.obj = callback; - mHandler.sendMessage(msg); - + synchronized (mCallbacks) { + mCallbacks.register(callback); + } return mBluetooth; } @@ -655,9 +652,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return; } mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - Message msg = mHandler.obtainMessage(MESSAGE_UNREGISTER_ADAPTER); - msg.obj = callback; - mHandler.sendMessage(msg); + synchronized (mCallbacks) { + mCallbacks.unregister(callback); + } } public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) { @@ -1559,18 +1556,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Inform BluetoothAdapter instances that Adapter service is up */ private void sendBluetoothServiceUpCallback() { - try { - int n = mCallbacks.beginBroadcast(); - Slog.d(TAG, "Broadcasting onBluetoothServiceUp() to " + n + " receivers."); - for (int i = 0; i < n; i++) { - try { - mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth); - } catch (RemoteException e) { - Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); + synchronized (mCallbacks) { + try { + int n = mCallbacks.beginBroadcast(); + Slog.d(TAG, "Broadcasting onBluetoothServiceUp() to " + n + " receivers."); + for (int i = 0; i < n; i++) { + try { + mCallbacks.getBroadcastItem(i).onBluetoothServiceUp(mBluetooth); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); + } } + } finally { + mCallbacks.finishBroadcast(); } - } finally { - mCallbacks.finishBroadcast(); } } @@ -1578,18 +1577,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub { * Inform BluetoothAdapter instances that Adapter service is down */ private void sendBluetoothServiceDownCallback() { - try { - int n = mCallbacks.beginBroadcast(); - Slog.d(TAG, "Broadcasting onBluetoothServiceDown() to " + n + " receivers."); - for (int i = 0; i < n; i++) { - try { - mCallbacks.getBroadcastItem(i).onBluetoothServiceDown(); - } catch (RemoteException e) { - Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); + synchronized (mCallbacks) { + try { + int n = mCallbacks.beginBroadcast(); + Slog.d(TAG, "Broadcasting onBluetoothServiceDown() to " + n + " receivers."); + for (int i = 0; i < n; i++) { + try { + mCallbacks.getBroadcastItem(i).onBluetoothServiceDown(); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); + } } + } finally { + mCallbacks.finishBroadcast(); } - } finally { - mCallbacks.finishBroadcast(); } } @@ -1917,17 +1918,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext.getPackageName()); } break; - - case MESSAGE_REGISTER_ADAPTER: { - IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; - mCallbacks.register(callback); - break; - } - case MESSAGE_UNREGISTER_ADAPTER: { - IBluetoothManagerCallback callback = (IBluetoothManagerCallback) msg.obj; - mCallbacks.unregister(callback); - break; - } case MESSAGE_REGISTER_STATE_CHANGE_CALLBACK: { IBluetoothStateChangeCallback callback = (IBluetoothStateChangeCallback) msg.obj; diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index a9c3079adcc0..7f25de6b3470 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -1836,12 +1836,13 @@ public class LocationManagerService extends ILocationManager.Stub { @Override public void requestLocationUpdates(LocationRequest request, ILocationListener listener, - PendingIntent intent, String packageName, String featureId) { + PendingIntent intent, String packageName, String featureId, String listenerId) { if (request == null) { request = DEFAULT_LOCATION_REQUEST; } - CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId); + CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, featureId, + listenerId); identity.enforceLocationPermission(); WorkSource workSource = request.getWorkSource(); @@ -2027,7 +2028,7 @@ public class LocationManagerService extends ILocationManager.Stub { @Override public boolean getCurrentLocation(LocationRequest locationRequest, ICancellationSignal remoteCancellationSignal, ILocationListener listener, - String packageName, String featureId) { + String packageName, String featureId, String listenerId) { // side effect of validating locationRequest and packageName Location lastLocation = getLastLocation(locationRequest, packageName, featureId); if (lastLocation != null) { @@ -2052,7 +2053,7 @@ public class LocationManagerService extends ILocationManager.Stub { } } - requestLocationUpdates(locationRequest, listener, null, packageName, featureId); + requestLocationUpdates(locationRequest, listener, null, packageName, featureId, listenerId); CancellationSignal cancellationSignal = CancellationSignal.fromTransport( remoteCancellationSignal); if (cancellationSignal != null) { diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 067147703b0c..9aefc8dc78ec 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -4468,9 +4468,8 @@ class StorageManagerService extends IStorageManager.Stub String.format("/storage/emulated/%d/Android/data/%s/", userId, pkg); - int appUid = - UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid()); // Create package obb and data dir if it doesn't exist. + int appUid = UserHandle.getUid(userId, mPmInternal.getPackage(pkg).getUid()); File file = new File(packageObbDir); if (!file.exists()) { vold.setupAppDir(packageObbDir, appUid); diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index dbcb3da3e2f4..2d6ef81faf1c 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -231,7 +231,8 @@ public final class OomAdjuster { final ServiceThread adjusterThread = new ServiceThread(TAG, TOP_APP_PRIORITY_BOOST, false /* allowIo */); adjusterThread.start(); - Process.setThreadGroupAndCpuset(adjusterThread.getThreadId(), THREAD_GROUP_TOP_APP); + adjusterThread.getThreadHandler().post(() -> Process.setThreadGroupAndCpuset( + adjusterThread.getThreadId(), THREAD_GROUP_TOP_APP)); return adjusterThread; } diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 595275d20154..786e9cf66bfa 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -97,6 +97,7 @@ import android.os.storage.StorageManagerInternal; import android.system.Os; import android.text.TextUtils; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.EventLog; import android.util.LongSparseArray; import android.util.Pair; @@ -137,6 +138,7 @@ import java.util.BitSet; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; /** * Activity manager code dealing with processes. @@ -1846,11 +1848,13 @@ public final class ProcessList { runtimeFlags |= Zygote.USE_APP_IMAGE_STARTUP_CACHE; } - // Enable heap pointer tagging, unless disabled by the app manifest, target sdk level, - // or the compat feature. - if (app.info.allowsNativeHeapPointerTagging() - && mPlatformCompat.isChangeEnabled(NATIVE_HEAP_POINTER_TAGGING, app.info)) { - runtimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI; + if (Zygote.nativeSupportsTaggedPointers()) { + // Enable heap pointer tagging if supported by the kernel, unless disabled by the + // app manifest, target sdk level, or compat feature. + if (app.info.allowsNativeHeapPointerTagging() + && mPlatformCompat.isChangeEnabled(NATIVE_HEAP_POINTER_TAGGING, app.info)) { + runtimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI; + } } runtimeFlags |= decideGwpAsanLevel(app); @@ -2127,18 +2131,11 @@ public final class ProcessList { for (String packageName : packages) { String volumeUuid = pmInt.getPackage(packageName).getVolumeUuid(); long inode = pmInt.getCeDataInode(packageName, userId); - if (inode != 0) { - result.put(packageName, Pair.create(volumeUuid, inode)); - } - } - if (mAppDataIsolationWhitelistedApps != null) { - for (String packageName : mAppDataIsolationWhitelistedApps) { - String volumeUuid = pmInt.getPackage(packageName).getVolumeUuid(); - long inode = pmInt.getCeDataInode(packageName, userId); - if (inode != 0) { - result.put(packageName, Pair.create(volumeUuid, inode)); - } + if (inode == 0) { + Slog.w(TAG, packageName + " inode == 0 (b/152760674)"); + return null; } + result.put(packageName, Pair.create(volumeUuid, inode)); } return result; @@ -2160,35 +2157,56 @@ public final class ProcessList { app.setHasForegroundActivities(true); } - StorageManagerInternal storageManagerInternal = LocalServices.getService( - StorageManagerInternal.class); final Map<String, Pair<String, Long>> pkgDataInfoMap; + final Map<String, Pair<String, Long>> whitelistedAppDataInfoMap; boolean bindMountAppStorageDirs = false; + boolean bindMountAppsData = mAppDataIsolationEnabled + && UserHandle.isApp(app.uid) + && mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info); - if (mAppDataIsolationEnabled && UserHandle.isApp(app.uid) - && mPlatformCompat.isChangeEnabled(APP_DATA_DIRECTORY_ISOLATION, app.info)) { - // Get all packages belongs to the same shared uid. sharedPackages is empty array - // if it doesn't have shared uid. - final PackageManagerInternal pmInt = mService.getPackageManagerInternalLocked(); - final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage( - app.info.packageName, app.userId); - pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, sharedPackages.length == 0 - ? new String[]{app.info.packageName} : sharedPackages, uid); - - int userId = UserHandle.getUserId(uid); - if (mVoldAppDataIsolationEnabled - && !storageManagerInternal.isExternalStorageService(uid)) { - bindMountAppStorageDirs = true; - if (!storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(), - app.processName)) { - // Cannot prepare Android/app and Android/obb directory, - // so we won't mount it in zygote. - app.bindMountPending = true; - bindMountAppStorageDirs = false; - } + // Get all packages belongs to the same shared uid. sharedPackages is empty array + // if it doesn't have shared uid. + final PackageManagerInternal pmInt = mService.getPackageManagerInternalLocked(); + final String[] sharedPackages = pmInt.getSharedUserPackagesForPackage( + app.info.packageName, app.userId); + final String[] targetPackagesList = sharedPackages.length == 0 + ? new String[]{app.info.packageName} : sharedPackages; + + pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, targetPackagesList, uid); + if (pkgDataInfoMap == null) { + // TODO(b/152760674): Handle inode == 0 case properly, now we just give it a + // tmp free pass. + bindMountAppsData = false; + } + + // Remove all packages in pkgDataInfoMap from mAppDataIsolationWhitelistedApps, so + // it won't be mounted twice. + final Set<String> whitelistedApps = new ArraySet<>(mAppDataIsolationWhitelistedApps); + for (String pkg : targetPackagesList) { + whitelistedApps.remove(pkg); + } + + whitelistedAppDataInfoMap = getPackageAppDataInfoMap(pmInt, + whitelistedApps.toArray(new String[0]), uid); + if (whitelistedAppDataInfoMap == null) { + // TODO(b/152760674): Handle inode == 0 case properly, now we just give it a + // tmp free pass. + bindMountAppsData = false; + } + + int userId = UserHandle.getUserId(uid); + StorageManagerInternal storageManagerInternal = LocalServices.getService( + StorageManagerInternal.class); + if (mVoldAppDataIsolationEnabled && UserHandle.isApp(app.uid) + && !storageManagerInternal.isExternalStorageService(uid)) { + bindMountAppStorageDirs = true; + if (!storageManagerInternal.prepareStorageDirs(userId, pkgDataInfoMap.keySet(), + app.processName)) { + // Cannot prepare Android/app and Android/obb directory, + // so we won't mount it in zygote. + app.bindMountPending = true; + bindMountAppStorageDirs = false; } - } else { - pkgDataInfoMap = null; } final Process.ProcessStartResult startResult; @@ -2206,7 +2224,8 @@ public final class ProcessList { app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, null, app.info.packageName, /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp, - app.mDisabledCompatChanges, pkgDataInfoMap, bindMountAppStorageDirs, + app.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap, + bindMountAppsData, bindMountAppStorageDirs, new String[]{PROC_START_SEQ_IDENT + app.startSeq}); } else { startResult = Process.start(entryPoint, @@ -2214,7 +2233,7 @@ public final class ProcessList { app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags, isTopApp, app.mDisabledCompatChanges, pkgDataInfoMap, - bindMountAppStorageDirs, + whitelistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs, new String[]{PROC_START_SEQ_IDENT + app.startSeq}); } checkSlow(startTime, "startProcess: returned from zygote!"); diff --git a/services/core/java/com/android/server/display/color/AppSaturationController.java b/services/core/java/com/android/server/display/color/AppSaturationController.java index e42be02d4a9e..6a685bf187ad 100644 --- a/services/core/java/com/android/server/display/color/AppSaturationController.java +++ b/services/core/java/com/android/server/display/color/AppSaturationController.java @@ -17,6 +17,7 @@ package com.android.server.display.color; import android.annotation.UserIdInt; +import android.util.ArrayMap; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; @@ -61,11 +62,12 @@ class AppSaturationController { * Set the saturation level ({@code ColorDisplayManager#SaturationLevel} constant for a given * package name and userId. */ - public boolean setSaturationLevel(String packageName, @UserIdInt int userId, + public boolean setSaturationLevel(String callingPackageName, String affectedPackageName, + @UserIdInt int userId, int saturationLevel) { synchronized (mLock) { - return getSaturationControllerLocked(packageName, userId) - .setSaturationLevel(saturationLevel); + return getSaturationControllerLocked(affectedPackageName, userId) + .setSaturationLevel(callingPackageName, saturationLevel); } } @@ -148,13 +150,19 @@ class AppSaturationController { private static class SaturationController { + private static final int FULL_SATURATION = 100; + private final List<WeakReference<ColorTransformController>> mControllerRefs = new ArrayList<>(); - private int mSaturationLevel = 100; + private final ArrayMap<String, Integer> mSaturationLevels = new ArrayMap<>(); private float[] mTransformMatrix = new float[9]; - private boolean setSaturationLevel(int saturationLevel) { - mSaturationLevel = saturationLevel; + private boolean setSaturationLevel(String callingPackageName, int saturationLevel) { + if (saturationLevel == FULL_SATURATION) { + mSaturationLevels.remove(callingPackageName); + } else { + mSaturationLevels.put(callingPackageName, saturationLevel); + } if (!mControllerRefs.isEmpty()) { return updateState(); } @@ -163,17 +171,27 @@ class AppSaturationController { private boolean addColorTransformController( WeakReference<ColorTransformController> controller) { + clearExpiredReferences(); mControllerRefs.add(controller); - if (mSaturationLevel != 100) { + if (!mSaturationLevels.isEmpty()) { return updateState(); - } else { - clearExpiredReferences(); } return false; } + private int calculateSaturationLevel() { + int saturationLevel = FULL_SATURATION; + for (int i = 0; i < mSaturationLevels.size(); i++) { + final int level = mSaturationLevels.valueAt(i); + if (level < saturationLevel) { + saturationLevel = level; + } + } + return saturationLevel; + } + private boolean updateState() { - computeGrayscaleTransformMatrix(mSaturationLevel / 100f, mTransformMatrix); + computeGrayscaleTransformMatrix(calculateSaturationLevel() / 100f, mTransformMatrix); boolean updated = false; final Iterator<WeakReference<ColorTransformController>> iterator = mControllerRefs @@ -190,7 +208,6 @@ class AppSaturationController { } } return updated; - } private void clearExpiredReferences() { @@ -206,7 +223,7 @@ class AppSaturationController { } private void dump(PrintWriter pw) { - pw.println(" mSaturationLevel: " + mSaturationLevel); + pw.println(" mSaturationLevels: " + mSaturationLevels); pw.println(" mControllerRefs count: " + mControllerRefs.size()); } } diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java index 2dc2cf0d8e90..95a98f1e9494 100644 --- a/services/core/java/com/android/server/display/color/ColorDisplayService.java +++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java @@ -44,6 +44,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; +import android.content.pm.PackageManagerInternal; import android.content.res.Resources; import android.database.ContentObserver; import android.hardware.display.ColorDisplayManager; @@ -73,6 +74,7 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.DumpUtils; import com.android.server.DisplayThread; +import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.twilight.TwilightListener; import com.android.server.twilight.TwilightManager; @@ -817,9 +819,11 @@ public final class ColorDisplayService extends SystemService { return LocalDateTime.MIN; } - private boolean setAppSaturationLevelInternal(String packageName, int saturationLevel) { + private boolean setAppSaturationLevelInternal(String callingPackageName, + String affectedPackageName, int saturationLevel) { return mAppSaturationController - .setSaturationLevel(packageName, mCurrentUser, saturationLevel); + .setSaturationLevel(callingPackageName, affectedPackageName, mCurrentUser, + saturationLevel); } private void setColorModeInternal(@ColorMode int colorMode) { @@ -1533,9 +1537,11 @@ public final class ColorDisplayService extends SystemService { getContext().enforceCallingPermission( Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS, "Permission required to set display saturation level"); + final String callingPackageName = LocalServices.getService(PackageManagerInternal.class) + .getNameForUid(Binder.getCallingUid()); final long token = Binder.clearCallingIdentity(); try { - return setAppSaturationLevelInternal(packageName, level); + return setAppSaturationLevelInternal(callingPackageName, packageName, level); } finally { Binder.restoreCallingIdentity(token); } diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index 846d09915fba..e6cb37185d71 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -3106,14 +3106,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub MSG_SHOW_SOFT_INPUT, getImeShowFlags(), reason, mCurMethod, resultReceiver, showInputToken)); mInputShown = true; - if (mHaveConnection && !mVisibleBound) { bindCurrentInputMethodServiceLocked( mCurIntent, mVisibleConnection, IME_VISIBLE_BIND_FLAGS); mVisibleBound = true; - } else { - // Clear the show request after the input shown. - mShowRequested = false; } res = true; } else if (mHaveConnection && SystemClock.uptimeMillis() diff --git a/services/core/java/com/android/server/location/AppOpsHelper.java b/services/core/java/com/android/server/location/AppOpsHelper.java index 9c279166ac8a..cb64c50bf11d 100644 --- a/services/core/java/com/android/server/location/AppOpsHelper.java +++ b/services/core/java/com/android/server/location/AppOpsHelper.java @@ -191,7 +191,7 @@ public class AppOpsHelper { callerIdentity.uid, callerIdentity.packageName, callerIdentity.featureId, - null) == AppOpsManager.MODE_ALLOWED; + callerIdentity.listenerId) == AppOpsManager.MODE_ALLOWED; } finally { Binder.restoreCallingIdentity(identity); } @@ -210,7 +210,7 @@ public class AppOpsHelper { callerIdentity.packageName, false, callerIdentity.featureId, - null) == AppOpsManager.MODE_ALLOWED; + callerIdentity.listenerId) == AppOpsManager.MODE_ALLOWED; } finally { Binder.restoreCallingIdentity(identity); } @@ -245,7 +245,7 @@ public class AppOpsHelper { callerIdentity.uid, callerIdentity.packageName, callerIdentity.featureId, - null) == AppOpsManager.MODE_ALLOWED; + callerIdentity.listenerId) == AppOpsManager.MODE_ALLOWED; } finally { Binder.restoreCallingIdentity(identity); } diff --git a/services/core/java/com/android/server/location/CallerIdentity.java b/services/core/java/com/android/server/location/CallerIdentity.java index b84fd13415fc..8d508bb6256d 100644 --- a/services/core/java/com/android/server/location/CallerIdentity.java +++ b/services/core/java/com/android/server/location/CallerIdentity.java @@ -83,12 +83,22 @@ public final class CallerIdentity { */ public static CallerIdentity fromBinder(Context context, String packageName, @Nullable String featureId) { + return fromBinder(context, packageName, featureId, null); + } + + /** + * Creates a CallerIdentity from the current binder identity, using the given package, feature + * id, and listener id. The package will be checked to enforce it belongs to the calling uid, + * and a security exception will be thrown if it is invalid. + */ + public static CallerIdentity fromBinder(Context context, String packageName, + @Nullable String featureId, @Nullable String listenerId) { int uid = Binder.getCallingUid(); if (!ArrayUtils.contains(context.getPackageManager().getPackagesForUid(uid), packageName)) { throw new SecurityException("invalid package \"" + packageName + "\" for uid " + uid); } - return fromBinderUnsafe(context, packageName, featureId); + return fromBinderUnsafe(context, packageName, featureId, listenerId); } /** @@ -99,8 +109,19 @@ public final class CallerIdentity { */ public static CallerIdentity fromBinderUnsafe(Context context, String packageName, @Nullable String featureId) { + return fromBinderUnsafe(context, packageName, featureId, null); + } + + /** + * Creates a CallerIdentity from the current binder identity, using the given package, feature + * id, and listener id. The package will not be checked to enforce that it belongs to the + * calling uid - this method should only be used if the package will be validated by some other + * means, such as an appops call. + */ + public static CallerIdentity fromBinderUnsafe(Context context, String packageName, + @Nullable String featureId, @Nullable String listenerId) { return new CallerIdentity(Binder.getCallingUid(), Binder.getCallingPid(), - UserHandle.getCallingUserId(), packageName, featureId, + UserHandle.getCallingUserId(), packageName, featureId, listenerId, getBinderPermissionLevel(context)); } @@ -157,6 +178,9 @@ public final class CallerIdentity { /** The calling feature id. */ public final @Nullable String featureId; + /** The calling listener id. */ + public final @Nullable String listenerId; + /** * The calling location permission level. This field should only be used for validating * permissions for API access. It should not be used for validating permissions for location @@ -167,11 +191,18 @@ public final class CallerIdentity { @VisibleForTesting public CallerIdentity(int uid, int pid, int userId, String packageName, @Nullable String featureId, @PermissionLevel int permissionLevel) { + this(uid, pid, userId, packageName, featureId, null, permissionLevel); + } + + private CallerIdentity(int uid, int pid, int userId, String packageName, + @Nullable String featureId, @Nullable String listenerId, + @PermissionLevel int permissionLevel) { this.uid = uid; this.pid = pid; this.userId = userId; this.packageName = Objects.requireNonNull(packageName); this.featureId = featureId; + this.listenerId = listenerId; this.permissionLevel = Preconditions.checkArgumentInRange(permissionLevel, PERMISSION_NONE, PERMISSION_FINE, "permissionLevel"); } @@ -216,7 +247,8 @@ public final class CallerIdentity { return uid == that.uid && pid == that.pid && packageName.equals(that.packageName) - && Objects.equals(featureId, that.featureId); + && Objects.equals(featureId, that.featureId) + && Objects.equals(listenerId, that.listenerId); } @Override diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java new file mode 100644 index 000000000000..0bdf3f22ee9a --- /dev/null +++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2020 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 com.android.server.net; + +import static android.net.NetworkTemplate.getCollapsedRatType; + +import android.annotation.NonNull; +import android.content.Context; +import android.telephony.Annotation; +import android.telephony.PhoneStateListener; +import android.telephony.ServiceState; +import android.telephony.SubscriptionManager; +import android.telephony.TelephonyManager; +import android.text.TextUtils; +import android.util.Log; + +import com.android.internal.util.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.Executor; + +/** + * Helper class that watches for events that are triggered per subscription. + */ +// TODO (b/152176562): Write tests to verify subscription changes generate corresponding +// register/unregister calls. +public class NetworkStatsSubscriptionsMonitor extends + SubscriptionManager.OnSubscriptionsChangedListener { + + /** + * Interface that this monitor uses to delegate event handling to NetworkStatsService. + */ + public interface Delegate { + /** + * Notify that the collapsed RAT type has been changed for any subscription. The method + * will also be triggered for any existing sub when start and stop monitoring. + * + * @param subscriberId IMSI of the subscription. + * @param collapsedRatType collapsed RAT type. + * @see android.net.NetworkTemplate#getCollapsedRatType(int). + */ + void onCollapsedRatTypeChanged(@NonNull String subscriberId, + @Annotation.NetworkType int collapsedRatType); + } + private final Delegate mDelegate; + + /** + * Receivers that watches for {@link ServiceState} changes for each subscription, to + * monitor the transitioning between Radio Access Technology(RAT) types for each sub. + */ + @NonNull + private final CopyOnWriteArrayList<RatTypeListener> mRatListeners = + new CopyOnWriteArrayList<>(); + + @NonNull + private final SubscriptionManager mSubscriptionManager; + @NonNull + private final TelephonyManager mTeleManager; + + @NonNull + private final Executor mExecutor; + + NetworkStatsSubscriptionsMonitor(@NonNull Context context, @NonNull Executor executor, + @NonNull Delegate delegate) { + super(); + mSubscriptionManager = (SubscriptionManager) context.getSystemService( + Context.TELEPHONY_SUBSCRIPTION_SERVICE); + mTeleManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + mExecutor = executor; + mDelegate = delegate; + } + + @Override + public void onSubscriptionsChanged() { + // Collect active subId list, hidden subId such as opportunistic subscriptions are + // also needed to track CBRS. + final List<Integer> newSubs = getActiveSubIdList(mSubscriptionManager); + + for (final int subId : newSubs) { + final RatTypeListener match = CollectionUtils.find(mRatListeners, + it -> it.mSubId == subId); + if (match != null) continue; + + // Create listener for every newly added sub. Also store subscriberId into it to + // prevent binder call to telephony when querying RAT. + final String subscriberId = mTeleManager.getSubscriberId(subId); + if (TextUtils.isEmpty(subscriberId)) { + Log.wtf(NetworkStatsService.TAG, + "Empty subscriberId for newly added sub: " + subId); + } + final RatTypeListener listener = + new RatTypeListener(mExecutor, this, subId, subscriberId); + mRatListeners.add(listener); + + // Register listener to the telephony manager that associated with specific sub. + mTeleManager.createForSubscriptionId(subId) + .listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE); + } + + for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) { + // If the new list contains the subId of the listener, keeps it. + final Integer match = CollectionUtils.find(newSubs, it -> it == listener.mSubId); + if (match != null) continue; + + handleRemoveRatTypeListener(listener); + } + } + + @NonNull + private List<Integer> getActiveSubIdList(@NonNull SubscriptionManager subscriptionManager) { + final ArrayList<Integer> ret = new ArrayList<>(); + final int[] ids = subscriptionManager.getCompleteActiveSubscriptionIdList(); + for (int id : ids) ret.add(id); + return ret; + } + + /** + * Get a collapsed RatType for the given subscriberId. + * + * @param subscriberId the target subscriberId + * @return collapsed RatType for the given subscriberId + */ + public int getRatTypeForSubscriberId(@NonNull String subscriberId) { + final RatTypeListener match = CollectionUtils.find(mRatListeners, + it -> TextUtils.equals(subscriberId, it.mSubscriberId)); + return match != null ? match.mLastCollapsedRatType : TelephonyManager.NETWORK_TYPE_UNKNOWN; + } + + /** + * Start monitoring events that triggered per subscription. + */ + public void start() { + mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor, this); + } + + /** + * Unregister subscription changes and all listeners for each subscription. + */ + public void stop() { + mSubscriptionManager.removeOnSubscriptionsChangedListener(this); + + for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) { + handleRemoveRatTypeListener(listener); + } + } + + private void handleRemoveRatTypeListener(@NonNull RatTypeListener listener) { + mTeleManager.createForSubscriptionId(listener.mSubId) + .listen(listener, PhoneStateListener.LISTEN_NONE); + mRatListeners.remove(listener); + + // Removal of subscriptions doesn't generate RAT changed event, fire it for every + // RatTypeListener. + mDelegate.onCollapsedRatTypeChanged( + listener.mSubscriberId, TelephonyManager.NETWORK_TYPE_UNKNOWN); + } + + static class RatTypeListener extends PhoneStateListener { + // Unique id for the subscription. See {@link SubscriptionInfo#getSubscriptionId}. + @NonNull + private final int mSubId; + + // IMSI to identifying the corresponding network from {@link NetworkState}. + // See {@link TelephonyManager#getSubscriberId}. + @NonNull + private final String mSubscriberId; + + private volatile int mLastCollapsedRatType = TelephonyManager.NETWORK_TYPE_UNKNOWN; + @NonNull + private final NetworkStatsSubscriptionsMonitor mMonitor; + + RatTypeListener(@NonNull Executor executor, + @NonNull NetworkStatsSubscriptionsMonitor monitor, int subId, + @NonNull String subscriberId) { + super(executor); + mSubId = subId; + mSubscriberId = subscriberId; + mMonitor = monitor; + } + + @Override + public void onServiceStateChanged(@NonNull ServiceState ss) { + final int networkType = ss.getDataNetworkType(); + final int collapsedRatType = getCollapsedRatType(networkType); + if (collapsedRatType == mLastCollapsedRatType) return; + + if (NetworkStatsService.LOGD) { + Log.d(NetworkStatsService.TAG, "subtype changed for sub(" + mSubId + "): " + + mLastCollapsedRatType + " -> " + collapsedRatType); + } + mLastCollapsedRatType = collapsedRatType; + mMonitor.mDelegate.onCollapsedRatTypeChanged(mSubscriberId, mLastCollapsedRatType); + } + } +} diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java index ba7583fe7f7a..dab4bfd4df5a 100644 --- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java +++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java @@ -46,6 +46,7 @@ import com.android.server.pm.dex.DexoptOptions; import java.io.File; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -106,6 +107,8 @@ public class BackgroundDexOptService extends JobService { private static final long mDowngradeUnusedAppsThresholdInMillis = getDowngradeUnusedAppsThresholdInMillis(); + private static List<PackagesUpdatedListener> sPackagesUpdatedListeners = new ArrayList<>(); + public static void schedule(Context context) { if (isBackgroundDexoptDisabled()) { return; @@ -244,6 +247,7 @@ public class BackgroundDexOptService extends JobService { } } notifyPinService(updatedPackages); + notifyPackagesUpdated(updatedPackages); // Ran to completion, so we abandon our timeslice and do not reschedule. jobFinished(jobParams, /* reschedule */ false); } @@ -391,6 +395,7 @@ public class BackgroundDexOptService extends JobService { } finally { // Always let the pinner service know about changes. notifyPinService(updatedPackages); + notifyPackagesUpdated(updatedPackages); } } @@ -642,6 +647,32 @@ public class BackgroundDexOptService extends JobService { } } + public static interface PackagesUpdatedListener { + /** Callback when packages have been updated by the bg-dexopt service. */ + public void onPackagesUpdated(ArraySet<String> updatedPackages); + } + + public static void addPackagesUpdatedListener(PackagesUpdatedListener listener) { + synchronized (sPackagesUpdatedListeners) { + sPackagesUpdatedListeners.add(listener); + } + } + + public static void removePackagesUpdatedListener(PackagesUpdatedListener listener) { + synchronized (sPackagesUpdatedListeners) { + sPackagesUpdatedListeners.remove(listener); + } + } + + /** Notify all listeners (#addPackagesUpdatedListener) that packages have been updated. */ + private void notifyPackagesUpdated(ArraySet<String> updatedPackages) { + synchronized (sPackagesUpdatedListeners) { + for (PackagesUpdatedListener listener : sPackagesUpdatedListeners) { + listener.onPackagesUpdated(updatedPackages); + } + } + } + private static long getDowngradeUnusedAppsThresholdInMillis() { final String sysPropKey = "pm.dexopt.downgrade_after_inactive_days"; String sysPropValue = SystemProperties.get(sysPropKey); diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index f37af3aef657..9fb468e8db6e 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -724,6 +724,30 @@ public class Installer extends SystemService { } /** + * Deletes all snapshots of credential encrypted user data, where the snapshot id is not + * included in {@code retainSnapshotIds}. + * + * @param userId id of the user whose user data snapshots to delete. + * @param retainSnapshotIds ids of the snapshots that should not be deleted. + * + * @return {@code true} if the operation was successful, or {@code false} if a remote call + * shouldn't be continued. See {@link #checkBeforeRemote}. + * + * @throws InstallerException if failed to delete user data snapshot. + */ + public boolean destroyCeSnapshotsNotSpecified(@UserIdInt int userId, + int[] retainSnapshotIds) throws InstallerException { + if (!checkBeforeRemote()) return false; + + try { + mInstalld.destroyCeSnapshotsNotSpecified(null, userId, retainSnapshotIds); + return true; + } catch (Exception e) { + throw InstallerException.from(e); + } + } + + /** * Migrates obb data from its legacy location {@code /data/media/obb} to * {@code /data/media/0/Android/obb}. This call is idempotent and a fast no-op if data has * already been migrated. diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java index 5f871ad4f9e4..83e99b008b68 100644 --- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java @@ -505,6 +505,11 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { rollbackIds[i] = mRollbacks.get(i).info.getRollbackId(); } ApexManager.getInstance().destroyCeSnapshotsNotSpecified(userId, rollbackIds); + try { + mInstaller.destroyCeSnapshotsNotSpecified(userId, rollbackIds); + } catch (Installer.InstallerException ie) { + Slog.e(TAG, "Failed to delete snapshots for user: " + userId, ie); + } } @WorkerThread diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java index 1e5a924e1d4d..0470ffa6cdca 100644 --- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java @@ -1469,7 +1469,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks { if (toDisplay.getDisplayId() != stack.getDisplayId()) { stack.reparent(toDisplay.getDefaultTaskDisplayArea(), false /* onTop */); } else { - toDisplay.mTaskContainers.positionStackAtBottom(stack); + toDisplay.getDefaultTaskDisplayArea().positionStackAtBottom(stack); } mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS); diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java index edd14b7bebf3..a512337c96ec 100644 --- a/services/core/java/com/android/server/wm/DisplayArea.java +++ b/services/core/java/com/android/server/wm/DisplayArea.java @@ -54,7 +54,6 @@ import java.util.function.Predicate; * - BELOW_TASKS: Can only contain BELOW_TASK DisplayAreas and WindowTokens that go below tasks. * - ABOVE_TASKS: Can only contain ABOVE_TASK DisplayAreas and WindowTokens that go above tasks. * - ANY: Can contain any kind of DisplayArea, and any kind of WindowToken or the Task container. - * Cannot have a sibling that is of type ANY. * * @param <T> type of the children of the DisplayArea. */ @@ -274,7 +273,6 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> { ANY; static void checkSiblings(Type bottom, Type top) { - checkState(!(bottom == ANY && top == ANY), "ANY cannot be a sibling of ANY"); checkState(!(bottom != BELOW_TASKS && top == BELOW_TASKS), bottom + " must be above BELOW_TASKS"); checkState(!(bottom == ABOVE_TASKS && top != ABOVE_TASKS), diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java index 982157336295..15b6f9735bf1 100644 --- a/services/core/java/com/android/server/wm/DisplayAreaPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayAreaPolicy.java @@ -16,9 +16,14 @@ package com.android.server.wm; +import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER; + import android.content.res.Resources; import android.text.TextUtils; +import java.util.ArrayList; +import java.util.List; + /** * Policy that manages DisplayAreas. */ @@ -37,9 +42,9 @@ public abstract class DisplayAreaPolicy { protected final DisplayArea<? extends WindowContainer> mImeContainer; /** - * The Tasks container. Tasks etc. are automatically added to this container. + * The task display areas. Tasks etc. are automatically added to these containers. */ - protected final DisplayArea<? extends ActivityStack> mTaskContainers; + protected final List<TaskDisplayArea> mTaskDisplayAreas; /** * Construct a new {@link DisplayAreaPolicy} @@ -48,19 +53,19 @@ public abstract class DisplayAreaPolicy { * @param content the display content for which the policy applies * @param root the root display area under which the policy operates * @param imeContainer the ime container that the policy must attach - * @param taskDisplayArea the task container that the policy must attach + * @param taskDisplayAreas the task display areas that the policy must attach * * @see #attachDisplayAreas() */ protected DisplayAreaPolicy(WindowManagerService wmService, DisplayContent content, DisplayArea.Root root, DisplayArea<? extends WindowContainer> imeContainer, - DisplayArea<? extends ActivityStack> taskDisplayArea) { + List<TaskDisplayArea> taskDisplayAreas) { mWmService = wmService; mContent = content; mRoot = root; mImeContainer = imeContainer; - mTaskContainers = taskDisplayArea; + mTaskDisplayAreas = taskDisplayAreas; } /** @@ -80,15 +85,32 @@ public abstract class DisplayAreaPolicy { */ public abstract void addWindow(WindowToken token); + /** + * @return the number of task display areas on the display. + */ + public int getTaskDisplayAreaCount() { + return mTaskDisplayAreas.size(); + } + + /** + * @return the task display area at index. + */ + public TaskDisplayArea getTaskDisplayAreaAt(int index) { + return mTaskDisplayAreas.get(index); + } + /** Provider for platform-default display area policy. */ static final class DefaultProvider implements DisplayAreaPolicy.Provider { @Override public DisplayAreaPolicy instantiate(WindowManagerService wmService, DisplayContent content, DisplayArea.Root root, - DisplayArea<? extends WindowContainer> imeContainer, - TaskDisplayArea taskDisplayArea) { + DisplayArea<? extends WindowContainer> imeContainer) { + final TaskDisplayArea defaultTaskDisplayArea = new TaskDisplayArea(content, wmService, + "DefaultTaskDisplayArea", FEATURE_DEFAULT_TASK_CONTAINER); + final List<TaskDisplayArea> tdaList = new ArrayList<>(); + tdaList.add(defaultTaskDisplayArea); return new DisplayAreaPolicyBuilder() - .build(wmService, content, root, imeContainer, taskDisplayArea); + .build(wmService, content, root, imeContainer, tdaList); } } @@ -107,8 +129,7 @@ public abstract class DisplayAreaPolicy { */ DisplayAreaPolicy instantiate(WindowManagerService wmService, DisplayContent content, DisplayArea.Root root, - DisplayArea<? extends WindowContainer> imeContainer, - TaskDisplayArea taskDisplayArea); + DisplayArea<? extends WindowContainer> imeContainer); /** * Instantiate the device-specific {@link Provider}. diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java index e8becfa27fac..2c2f43392eca 100644 --- a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java +++ b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java @@ -201,8 +201,8 @@ class DisplayAreaPolicyBuilder { Result(WindowManagerService wmService, DisplayContent content, DisplayArea.Root root, DisplayArea<? extends WindowContainer> imeContainer, - DisplayArea<? extends ActivityStack> taskDisplayArea, ArrayList<Feature> features) { - super(wmService, content, root, imeContainer, taskDisplayArea); + List<TaskDisplayArea> taskDisplayAreas, ArrayList<Feature> features) { + super(wmService, content, root, imeContainer, taskDisplayAreas); mFeatures = features; mAreas = new HashMap<>(features.size()); for (int i = 0; i < mFeatures.size(); i++) { @@ -267,7 +267,7 @@ class DisplayAreaPolicyBuilder { areaForLayer[layer].mChildren.add(leafArea); leafType = type; if (leafType == LEAF_TYPE_TASK_CONTAINERS) { - leafArea.mExisting = mTaskContainers; + addTaskDisplayAreasToLayer(areaForLayer[layer], layer); } else if (leafType == LEAF_TYPE_IME_CONTAINERS) { leafArea.mExisting = mImeContainer; } @@ -278,6 +278,17 @@ class DisplayAreaPolicyBuilder { root.instantiateChildren(mRoot, mAreaForLayer, 0, mAreas); } + /** Adds all task display areas to the specified layer */ + private void addTaskDisplayAreasToLayer(PendingArea parentPendingArea, int layer) { + final int count = mTaskDisplayAreas.size(); + for (int i = 0; i < count; i++) { + PendingArea leafArea = new PendingArea(null, layer, parentPendingArea); + leafArea.mExisting = mTaskDisplayAreas.get(i); + leafArea.mMaxLayer = layer; + parentPendingArea.mChildren.add(leafArea); + } + } + @Override public void addWindow(WindowToken token) { DisplayArea.Tokens area = findAreaForToken(token); @@ -317,12 +328,16 @@ class DisplayAreaPolicyBuilder { return this; } + protected List<Feature> getFeatures() { + return mFeatures; + } + Result build(WindowManagerService wmService, DisplayContent content, DisplayArea.Root root, DisplayArea<? extends WindowContainer> imeContainer, - DisplayArea<? extends ActivityStack> taskDisplayArea) { + List<TaskDisplayArea> taskDisplayAreas) { - return new Result(wmService, content, root, imeContainer, taskDisplayArea, new ArrayList<>( + return new Result(wmService, content, root, imeContainer, taskDisplayAreas, new ArrayList<>( mFeatures)); } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 8111c0ef28c2..98d4b55d0c18 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -72,6 +72,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN; import static android.view.WindowManager.TRANSIT_TASK_OPEN; import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT; +import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG; @@ -268,8 +269,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo new NonAppWindowContainers("mOverlayContainers", mWmService); /** The containers below are the only child containers {@link #mWindowContainers} can have. */ - // Contains all window containers that are related to apps (Activities) - final TaskDisplayArea mTaskContainers = new TaskDisplayArea(this, mWmService); // Contains all IME window containers. Note that the z-ordering of the IME windows will depend // on the IME target. We mainly have this container grouping so we can keep track of all the IME @@ -971,7 +970,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo super.addChild(mOverlayContainers, null); mDisplayAreaPolicy = mWmService.mDisplayAreaPolicyProvider.instantiate( - mWmService, this, mRootDisplayArea, mImeWindowsContainers, mTaskContainers); + mWmService, this, mRootDisplayArea, mImeWindowsContainers); mWindowContainers.addChildren(); // Sets the display content for the children. @@ -1081,8 +1080,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo return null; } mShellRoots.put(windowType, root); - SurfaceControl out = new SurfaceControl(); - out.copyFrom(rootLeash); + SurfaceControl out = new SurfaceControl(rootLeash); return out; } @@ -2070,13 +2068,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } protected int getTaskDisplayAreaCount() { - // TODO(multi-display-area): Report actual display area count - return 1; + return mDisplayAreaPolicy.getTaskDisplayAreaCount(); } protected TaskDisplayArea getTaskDisplayAreaAt(int index) { - // TODO(multi-display-area): Report actual display area values - return mTaskContainers; + return mDisplayAreaPolicy.getTaskDisplayAreaAt(index); } ActivityStack getStack(int rootTaskId) { @@ -2402,7 +2398,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo * or for cases when multi-instance is not supported yet (like Split-screen, PiP or Recents). */ TaskDisplayArea getDefaultTaskDisplayArea() { - return mTaskContainers; + return mDisplayAreaPolicy.getTaskDisplayAreaAt(0); } @Override diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index ec3c99bf0808..11cfad263fb2 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -31,7 +31,6 @@ import static android.app.WindowConfiguration.isSplitScreenWindowingMode; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; -import static android.window.DisplayAreaOrganizer.FEATURE_TASK_CONTAINER; import static com.android.server.wm.ActivityStack.ActivityState.RESUMED; import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE; @@ -141,8 +140,9 @@ final class TaskDisplayArea extends DisplayArea<ActivityStack> { */ private boolean mRemoved; - TaskDisplayArea(DisplayContent displayContent, WindowManagerService service) { - super(service, Type.ANY, "TaskContainers", FEATURE_TASK_CONTAINER); + TaskDisplayArea(DisplayContent displayContent, WindowManagerService service, String name, + int displayAreaFeature) { + super(service, Type.ANY, name, displayAreaFeature); mDisplayContent = displayContent; mRootWindowContainer = service.mRoot; mAtmService = service.mAtmService; diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index f9955fa89bff..f6e952c4cea1 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -2510,9 +2510,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< // We need to copy the SurfaceControl instead of returning the original // because the Parcel FLAGS PARCELABLE_WRITE_RETURN_VALUE cause SurfaceControls // to release themselves. - SurfaceControl sc = new SurfaceControl(); - sc.copyFrom(wc.getSurfaceControl()); - return sc; + return new SurfaceControl(wc.getSurfaceControl()); } WindowContainerToken toWindowContainerToken() { diff --git a/services/tests/servicestests/src/com/android/server/display/color/AppSaturationControllerTest.java b/services/tests/servicestests/src/com/android/server/display/color/AppSaturationControllerTest.java index 7c9a81d2e094..a525814435ea 100644 --- a/services/tests/servicestests/src/com/android/server/display/color/AppSaturationControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/display/color/AppSaturationControllerTest.java @@ -43,7 +43,9 @@ import java.lang.ref.WeakReference; @RunWith(AndroidJUnit4.class) public class AppSaturationControllerTest { - private static final String TEST_PACKAGE_NAME = "com.android.test"; + private static final String TEST_CALLER_PACKAGE_NAME = "com.android.test.caller"; + private static final String TEST_CALLER_PACKAGE_NAME_TWO = "com.android.test.caller.two"; + private static final String TEST_AFFECTED_PACKAGE_NAME = "com.android.test.affected"; private int mUserId; private AppSaturationController mAppSaturationController; @@ -70,8 +72,11 @@ public class AppSaturationControllerTest { public void addColorTransformController_appliesExistingSaturation() { final WeakReference<ColorTransformController> ref = new WeakReference<>( mColorTransformController); - mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 30); - mAppSaturationController.addColorTransformController(TEST_PACKAGE_NAME, mUserId, ref); + mAppSaturationController + .setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId, + 30); + mAppSaturationController + .addColorTransformController(TEST_AFFECTED_PACKAGE_NAME, mUserId, ref); AppSaturationController.computeGrayscaleTransformMatrix(.3f, mMatrix); verify(mColorTransformController).applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); } @@ -80,14 +85,19 @@ public class AppSaturationControllerTest { public void setSaturationLevel_resetToDefault() { final WeakReference<ColorTransformController> ref = new WeakReference<>( mColorTransformController); - mAppSaturationController.addColorTransformController(TEST_PACKAGE_NAME, mUserId, ref); + mAppSaturationController + .addColorTransformController(TEST_AFFECTED_PACKAGE_NAME, mUserId, ref); verify(mColorTransformController, never()) .applyAppSaturation(any(), eq(TRANSLATION_VECTOR)); - mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 30); + mAppSaturationController + .setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId, + 30); AppSaturationController.computeGrayscaleTransformMatrix(.3f, mMatrix); verify(mColorTransformController, times(1)) .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); - mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 100); + mAppSaturationController + .setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId, + 100); AppSaturationController.computeGrayscaleTransformMatrix(1.0f, mMatrix); verify(mColorTransformController, times(2)) .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); @@ -97,19 +107,76 @@ public class AppSaturationControllerTest { public void setSaturationLevel_updateLevel() { final WeakReference<ColorTransformController> ref = new WeakReference<>( mColorTransformController); - mAppSaturationController.addColorTransformController(TEST_PACKAGE_NAME, mUserId, ref); + mAppSaturationController + .addColorTransformController(TEST_AFFECTED_PACKAGE_NAME, mUserId, ref); verify(mColorTransformController, never()) .applyAppSaturation(any(), eq(TRANSLATION_VECTOR)); - mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 30); + mAppSaturationController + .setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId, + 30); AppSaturationController.computeGrayscaleTransformMatrix(.3f, mMatrix); verify(mColorTransformController).applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); - mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 70); + mAppSaturationController + .setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId, + 70); AppSaturationController.computeGrayscaleTransformMatrix(.7f, mMatrix); verify(mColorTransformController, times(2)) .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); - mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 100); + mAppSaturationController + .setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId, + 100); AppSaturationController.computeGrayscaleTransformMatrix(1.0f, mMatrix); verify(mColorTransformController, times(3)) .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); } + + @Test + public void setSaturationLevel_multipleCallers_appliesStrongest() { + final WeakReference<ColorTransformController> ref = new WeakReference<>( + mColorTransformController); + mAppSaturationController + .addColorTransformController(TEST_AFFECTED_PACKAGE_NAME, mUserId, ref); + verify(mColorTransformController, never()) + .applyAppSaturation(any(), eq(TRANSLATION_VECTOR)); + mAppSaturationController + .setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId, + 30); + AppSaturationController.computeGrayscaleTransformMatrix(0.3f, mMatrix); + verify(mColorTransformController, times(1)) + .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); + mAppSaturationController + .setSaturationLevel(TEST_CALLER_PACKAGE_NAME_TWO, TEST_AFFECTED_PACKAGE_NAME, + mUserId, + 70); + verify(mColorTransformController, times(2)) + .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); + } + + @Test + public void setSaturationLevel_multipleCallers_removingOneDoesNotAffectTheOther() { + final WeakReference<ColorTransformController> ref = new WeakReference<>( + mColorTransformController); + mAppSaturationController + .addColorTransformController(TEST_AFFECTED_PACKAGE_NAME, mUserId, ref); + verify(mColorTransformController, never()) + .applyAppSaturation(any(), eq(TRANSLATION_VECTOR)); + mAppSaturationController + .setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId, + 70); + AppSaturationController.computeGrayscaleTransformMatrix(0.7f, mMatrix); + verify(mColorTransformController, times(1)) + .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); + mAppSaturationController + .setSaturationLevel(TEST_CALLER_PACKAGE_NAME_TWO, TEST_AFFECTED_PACKAGE_NAME, + mUserId, + 30); + AppSaturationController.computeGrayscaleTransformMatrix(0.3f, mMatrix); + verify(mColorTransformController, times(2)) + .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); + mAppSaturationController + .setSaturationLevel(TEST_CALLER_PACKAGE_NAME_TWO, TEST_AFFECTED_PACKAGE_NAME, + mUserId, + 100); + AppSaturationController.computeGrayscaleTransformMatrix(0.7f, mMatrix); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java index 12bdec6ec1e1..0568be8d7fa6 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java @@ -22,6 +22,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManagerPolicyConstants.APPLICATION_LAYER; +import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER; import static com.android.server.wm.DisplayArea.Type.ABOVE_TASKS; import static com.android.server.wm.DisplayArea.Type.ANY; @@ -72,7 +73,11 @@ public class DisplayAreaPolicyBuilderTest { WindowManagerService wms = mSystemServices.getWindowManagerService(); DisplayArea.Root root = new SurfacelessDisplayAreaRoot(wms); DisplayArea<WindowContainer> ime = new DisplayArea<>(wms, ABOVE_TASKS, "Ime"); - DisplayArea<ActivityStack> tasks = new DisplayArea<>(wms, ANY, "Tasks"); + DisplayContent displayContent = mock(DisplayContent.class); + TaskDisplayArea taskDisplayArea = new TaskDisplayArea(displayContent, wms, "Tasks", + FEATURE_DEFAULT_TASK_CONTAINER); + List<TaskDisplayArea> taskDisplayAreaList = new ArrayList<>(); + taskDisplayAreaList.add(taskDisplayArea); final Feature foo; final Feature bar; @@ -86,7 +91,7 @@ public class DisplayAreaPolicyBuilderTest { .all() .except(TYPE_STATUS_BAR) .build()) - .build(wms, mock(DisplayContent.class), root, ime, tasks); + .build(wms, displayContent, root, ime, taskDisplayAreaList); policy.attachDisplayAreas(); @@ -98,9 +103,9 @@ public class DisplayAreaPolicyBuilderTest { assertThat(policy.findAreaForToken(tokenOfType(TYPE_STATUS_BAR)), is(not(decendantOfOneOf(policy.getDisplayAreas(bar))))); - assertThat(tasks, + assertThat(taskDisplayArea, is(decendantOfOneOf(policy.getDisplayAreas(foo)))); - assertThat(tasks, + assertThat(taskDisplayArea, is(decendantOfOneOf(policy.getDisplayAreas(bar)))); assertThat(ime, @@ -109,7 +114,8 @@ public class DisplayAreaPolicyBuilderTest { is(decendantOfOneOf(policy.getDisplayAreas(bar)))); List<DisplayArea<?>> actualOrder = collectLeafAreas(root); - Map<DisplayArea<?>, Set<Integer>> zSets = calculateZSets(policy, root, ime, tasks); + Map<DisplayArea<?>, Set<Integer>> zSets = calculateZSets(policy, root, ime, + taskDisplayArea); actualOrder = actualOrder.stream().filter(zSets::containsKey).collect(toList()); Map<DisplayArea<?>, Integer> expectedByMinLayer = mapValues(zSets, diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaProviderTest.java index 4e4627bf7e52..6834ee5f3950 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaProviderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaProviderTest.java @@ -77,8 +77,7 @@ public class DisplayAreaProviderTest { @Override public DisplayAreaPolicy instantiate(WindowManagerService wmService, DisplayContent content, - DisplayArea.Root root, DisplayArea<? extends WindowContainer> imeContainer, - TaskDisplayArea taskDisplayArea) { + DisplayArea.Root root, DisplayArea<? extends WindowContainer> imeContainer) { throw new RuntimeException("test stub"); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java index 618e6086b582..880c486c15af 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaTest.java @@ -54,17 +54,6 @@ public class DisplayAreaTest { } @Test - public void testDisplayArea_positionChanged_throwsIfIncompatibleSibling() { - WindowManagerService wms = mWmsRule.getWindowManagerService(); - DisplayArea<WindowContainer> parent = new SurfacelessDisplayArea<>(wms, ANY, "Parent"); - DisplayArea<WindowContainer> child1 = new DisplayArea<>(wms, ANY, "Child1"); - DisplayArea<WindowContainer> child2 = new DisplayArea<>(wms, ANY, "Child2"); - - parent.addChild(child1, 0); - assertThrows(IllegalStateException.class, () -> parent.addChild(child2, 0)); - } - - @Test public void testType_typeOf() { WindowManagerService wms = mWmsRule.getWindowManagerService(); @@ -87,10 +76,10 @@ public class DisplayAreaTest { checkSiblings(BELOW_TASKS, ABOVE_TASKS); checkSiblings(ANY, ABOVE_TASKS); checkSiblings(ABOVE_TASKS, ABOVE_TASKS); + checkSiblings(ANY, ANY); assertThrows(IllegalStateException.class, () -> checkSiblings(ABOVE_TASKS, BELOW_TASKS)); assertThrows(IllegalStateException.class, () -> checkSiblings(ABOVE_TASKS, ANY)); - assertThrows(IllegalStateException.class, () -> checkSiblings(ANY, ANY)); assertThrows(IllegalStateException.class, () -> checkSiblings(ANY, BELOW_TASKS)); } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java index 9625ffdac052..a7085334bece 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java @@ -51,10 +51,10 @@ import org.junit.Test; import org.junit.runner.RunWith; /** - * Tests for the {@link DisplayContent.TaskStackContainers} container in {@link DisplayContent}. + * Tests for the {@link TaskDisplayArea} container. * * Build/Install/Run: - * atest WmTests:TaskStackContainersTests + * atest WmTests:TaskDisplayAreaTests */ @SmallTest @Presubmit @@ -154,8 +154,9 @@ public class TaskDisplayAreaTests extends WindowTestsBase { ACTIVITY_TYPE_STANDARD, mDisplayContent); final Task newStack = createTaskStackOnDisplay(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent); - doReturn(newStack).when(mDisplayContent.mTaskContainers).createStack(anyInt(), - anyInt(), anyBoolean(), any(), any(), anyBoolean()); + final TaskDisplayArea taskDisplayArea = candidateTask.getDisplayArea(); + doReturn(newStack).when(taskDisplayArea).createStack(anyInt(), anyInt(), anyBoolean(), + any(), any(), anyBoolean()); final int type = ACTIVITY_TYPE_STANDARD; assertGetOrCreateStack(WINDOWING_MODE_FULLSCREEN, type, candidateTask, @@ -186,7 +187,7 @@ public class TaskDisplayAreaTests extends WindowTestsBase { private void assertGetOrCreateStack(int windowingMode, int activityType, Task candidateTask, boolean reuseCandidate) { - final TaskDisplayArea taskDisplayArea = (TaskDisplayArea) candidateTask.getParent(); + final TaskDisplayArea taskDisplayArea = candidateTask.getDisplayArea(); final ActivityStack stack = taskDisplayArea.getOrCreateStack(windowingMode, activityType, false /* onTop */, null /* intent */, candidateTask /* candidateTask */); assertEquals(reuseCandidate, stack == candidateTask); diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java index 18737c2b4bb7..57c750449d20 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java @@ -43,7 +43,9 @@ class TestDisplayContent extends DisplayContent { // hard-code to FULLSCREEN for tests. setWindowingMode(WINDOWING_MODE_FULLSCREEN); spyOn(this); - spyOn(mTaskContainers); + for (int i = getTaskDisplayAreaCount() - 1; i >= 0; --i) { + spyOn(getTaskDisplayAreaAt(i)); + } final DisplayRotation displayRotation = getDisplayRotation(); spyOn(displayRotation); diff --git a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java index d5851d85345f..0c25cfb968fd 100644 --- a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java +++ b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java @@ -34,18 +34,21 @@ import android.os.Parcel; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemProperties; +import android.util.ArraySet; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.server.IoThread; import com.android.server.LocalServices; import com.android.server.SystemService; +import com.android.server.pm.BackgroundDexOptService; import com.android.server.wm.ActivityMetricsLaunchObserver; import com.android.server.wm.ActivityMetricsLaunchObserver.ActivityRecordProto; import com.android.server.wm.ActivityMetricsLaunchObserver.Temperature; import com.android.server.wm.ActivityMetricsLaunchObserverRegistry; import com.android.server.wm.ActivityTaskManagerInternal; +import java.util.ArrayList; import java.util.concurrent.TimeUnit; import java.util.HashMap; @@ -286,6 +289,7 @@ public class IorapForwardingService extends SystemService { private final AppLaunchObserver mAppLaunchObserver = new AppLaunchObserver(); private final EventSequenceValidator mEventSequenceValidator = new EventSequenceValidator(); + private final DexOptPackagesUpdated mDexOptPackagesUpdated = new DexOptPackagesUpdated(); private boolean mRegisteredListeners = false; private void registerInProcessListenersLocked() { @@ -308,9 +312,22 @@ public class IorapForwardingService extends SystemService { launchObserverRegistry.registerLaunchObserver(mAppLaunchObserver); launchObserverRegistry.registerLaunchObserver(mEventSequenceValidator); + BackgroundDexOptService.addPackagesUpdatedListener(mDexOptPackagesUpdated); + + mRegisteredListeners = true; } + private class DexOptPackagesUpdated implements BackgroundDexOptService.PackagesUpdatedListener { + @Override + public void onPackagesUpdated(ArraySet<String> updatedPackages) { + String[] updated = updatedPackages.toArray(new String[0]); + for (String packageName : updated) { + Log.d(TAG, "onPackagesUpdated: " + packageName); + } + } + } + private class AppLaunchObserver implements ActivityMetricsLaunchObserver { // We add a synthetic sequence ID here to make it easier to differentiate new // launch sequences on the native side. diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 327e8b344eeb..1a4b9d735977 100755 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -1147,6 +1147,21 @@ public class CarrierConfigManager { "support_ims_conference_event_package_bool"; /** + * Determines whether processing of conference event package data received on a device other + * than the conference host is supported. + * <p> + * When a device A merges calls B and C into a conference it is considered the conference host + * and B and C are considered the conference peers. + * <p> + * When {@code true}, the conference peer will display the conference state if it receives + * conference event package data from the network. When {@code false}, the conference peer will + * ignore conference event package data received from the network. + * @hide + */ + public static final String KEY_SUPPORT_IMS_CONFERENCE_EVENT_PACKAGE_ON_PEER_BOOL = + "support_ims_conference_event_package_on_peer_bool"; + + /** * Determines whether High Definition audio property is displayed in the dialer UI. * If {@code false}, remove the HD audio property from the connection so that HD audio related * UI is not displayed. If {@code true}, keep HD audio property as it is configured. @@ -3780,6 +3795,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_SUPPORT_IMS_CONFERENCE_CALL_BOOL, true); sDefaults.putBoolean(KEY_SUPPORT_MANAGE_IMS_CONFERENCE_CALL_BOOL, true); sDefaults.putBoolean(KEY_SUPPORT_IMS_CONFERENCE_EVENT_PACKAGE_BOOL, true); + sDefaults.putBoolean(KEY_SUPPORT_IMS_CONFERENCE_EVENT_PACKAGE_ON_PEER_BOOL, true); sDefaults.putBoolean(KEY_SUPPORT_VIDEO_CONFERENCE_CALL_BOOL, false); sDefaults.putBoolean(KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL, false); sDefaults.putInt(KEY_IMS_CONFERENCE_SIZE_LIMIT_INT, 5); diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java index 2b1d9e58c4d5..18e25921555a 100644 --- a/telephony/java/com/android/internal/telephony/DctConstants.java +++ b/telephony/java/com/android/internal/telephony/DctConstants.java @@ -113,6 +113,7 @@ public class DctConstants { public static final int EVENT_5G_TIMER_HYSTERESIS = BASE + 53; public static final int EVENT_5G_TIMER_WATCHDOG = BASE + 54; public static final int EVENT_CARRIER_CONFIG_CHANGED = BASE + 55; + public static final int EVENT_SIM_STATE_UPDATED = BASE + 56; /***** Constants *****/ diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java index 12d80fc2c084..3f8261d5ad7f 100644 --- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java +++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java @@ -875,6 +875,11 @@ public class NetworkCapabilitiesTest { } catch (IllegalArgumentException e) { } } + private class TestTransportInfo implements TransportInfo { + TestTransportInfo() { + } + } + @Test @IgnoreUpTo(Build.VERSION_CODES.Q) public void testBuilder() { final int ownerUid = 1001; @@ -882,6 +887,7 @@ public class NetworkCapabilitiesTest { final int requestUid = 10100; final int[] administratorUids = {ownerUid, 10001}; final TelephonyNetworkSpecifier specifier = new TelephonyNetworkSpecifier(1); + final TestTransportInfo transportInfo = new TestTransportInfo(); final String ssid = "TEST_SSID"; final String packageName = "com.google.test.networkcapabilities"; final NetworkCapabilities nc = new NetworkCapabilities.Builder() @@ -896,7 +902,7 @@ public class NetworkCapabilitiesTest { .setLinkDownstreamBandwidthKbps(512) .setLinkUpstreamBandwidthKbps(128) .setNetworkSpecifier(specifier) - .setTransportInfo(null) + .setTransportInfo(transportInfo) .setSignalStrength(signalStrength) .setSsid(ssid) .setRequestorUid(requestUid) @@ -913,7 +919,7 @@ public class NetworkCapabilitiesTest { assertEquals(128, nc.getLinkUpstreamBandwidthKbps()); assertNotEquals(512, nc.getLinkUpstreamBandwidthKbps()); assertEquals(specifier, nc.getNetworkSpecifier()); - assertNull(nc.getTransportInfo()); + assertEquals(transportInfo, nc.getTransportInfo()); assertEquals(signalStrength, nc.getSignalStrength()); assertNotEquals(-50, nc.getSignalStrength()); assertEquals(ssid, nc.getSsid()); |