Loading core/java/android/app/PropertyInvalidatedCache.java +17 −4 Original line number Diff line number Diff line Loading @@ -313,6 +313,7 @@ public class PropertyInvalidatedCache<Query, Result> { * one of the permitted values above. The API is a string that is a legal Java simple * identifier. The api is modified to conform to the system property style guide by * replacing every upper case letter with an underscore and the lower case equivalent. * (An initial upper case letter is not prefixed with an underscore). * There is no requirement that the apiName be the name of an actual API. * * Be aware that SystemProperties has a maximum length which is private to the Loading @@ -326,7 +327,7 @@ public class PropertyInvalidatedCache<Query, Result> { @NonNull String apiName) { char[] api = apiName.toCharArray(); int upper = 0; for (int i = 0; i < api.length; i++) { for (int i = 1; i < api.length; i++) { if (Character.isUpperCase(api[i])) { upper++; } Loading @@ -336,7 +337,9 @@ public class PropertyInvalidatedCache<Query, Result> { for (int i = 0; i < api.length; i++) { if (Character.isJavaIdentifierPart(api[i])) { if (Character.isUpperCase(api[i])) { if (i > 0) { suffix[j++] = '_'; } suffix[j++] = Character.toLowerCase(api[i]); } else { suffix[j++] = api[i]; Loading Loading @@ -1286,12 +1289,22 @@ public class PropertyInvalidatedCache<Query, Result> { } /** * Return the name of the cache, to be used in debug messages. * Return the name of the cache, to be used in debug messages. This is exposed * primarily for testing. * @hide */ private final @NonNull String cacheName() { public final @NonNull String cacheName() { return mCacheName; } /** * Return the property used by the cache. This is primarily for test purposes. * @hide */ public final @NonNull String propertyName() { return mPropertyName; } /** * Return the query as a string, to be used in debug messages. New clients should not * override this, but should instead add the necessary toString() method to the Query Loading core/java/android/app/admin/DevicePolicyManager.java +57 −192 Original line number Diff line number Diff line Loading @@ -185,6 +185,30 @@ public class DevicePolicyManager { mResourcesManager = new DevicePolicyResourcesManager(context, service); } /** * Fetch the current value of mService. This is used in the binder cache lambda * expressions. */ private final IDevicePolicyManager getService() { return mService; } /** * Fetch the current value of mParentInstance. This is used in the binder cache * lambda expressions. */ private final boolean isParentInstance() { return mParentInstance; } /** * Fetch the current value of mContext. This is used in the binder cache lambda * expressions. */ private final Context getContext() { return mContext; } /** @hide test will override it. */ @VisibleForTesting protected int myUserId() { Loading Loading @@ -3783,57 +3807,21 @@ public class DevicePolicyManager { "android.app.extra.RESOURCE_IDS"; /** * A convenience class that wraps some IpcDataCache methods. Instantiate it with an * API string. Instances can and should be final static. All instances of this class * use the same key for invalidation. * This object is a single place to tack on invalidation and disable calls. All * binder caches in this class derive from this Config, so all can be invalidated or * disabled through this Config. */ private static class BinderApi { private final static String KEY = "DevicePolicyManager"; private final String mApi; BinderApi(String api) { mApi = api; } final String api() { return mApi; } final String key() { return KEY; } final static void invalidate() { IpcDataCache.invalidateCache(IpcDataCache.MODULE_SYSTEM, KEY); } final void disable() { IpcDataCache.disableForCurrentProcess(mApi); } } private static final IpcDataCache.Config sDpmCaches = new IpcDataCache.Config(8, IpcDataCache.MODULE_SYSTEM, "DevicePolicyManagerCaches"); /** @hide */ public static void invalidateBinderCaches() { BinderApi.invalidate(); } /** * A simple wrapper for binder caches in this class. All caches are created with a * maximum of 8 entries, the SYSTEM module, and a cache name that is the same as the api. */ private static class BinderCache<Q,R> extends IpcDataCache<Q,R> { BinderCache(BinderApi api, IpcDataCache.QueryHandler<Q,R> handler) { super(8, IpcDataCache.MODULE_SYSTEM, api.key(), api.api(), handler); } sDpmCaches.invalidateCache(); } /** * Disable all caches in the local process. * @hide */ public static void disableLocalProcessCaches() { disableGetKeyguardDisabledFeaturesCache(); disableHasDeviceOwnerCache(); disableGetProfileOwnerOrDeviceOwnerSupervisionComponentCache(); disableIsOrganizationOwnedDeviceWithManagedProfileCache(); disableGetDeviceOwnerOrganizationNameCache(); disableGetOrganizationNameForUserCache(); disableIsNetworkLoggingEnabled(); /** @hide */ public static void disableLocalCaches() { sDpmCaches.disableAllForCurrentProcess(); } /** @hide */ Loading Loading @@ -8435,54 +8423,16 @@ public class DevicePolicyManager { return getKeyguardDisabledFeatures(admin, myUserId()); } // A key into the keyguard cache. private static class KeyguardQuery { private final ComponentName mAdmin; private final int mUserHandle; KeyguardQuery(@Nullable ComponentName admin, int userHandle) { mAdmin = admin; mUserHandle = userHandle; } public boolean equals(Object o) { if (o instanceof KeyguardQuery) { KeyguardQuery r = (KeyguardQuery) o; return Objects.equals(mAdmin, r.mAdmin) && mUserHandle == r.mUserHandle; } else { return false; } } public int hashCode() { return ((mAdmin != null) ? mAdmin.hashCode() : 0) * 13 + mUserHandle; } } // The query handler does not cache wildcard user IDs, although they should never // appear in the query. private static final BinderApi sGetKeyguardDisabledFeatures = new BinderApi("getKeyguardDisabledFeatures"); private BinderCache<KeyguardQuery, Integer> mGetKeyGuardDisabledFeaturesCache = new BinderCache<>(sGetKeyguardDisabledFeatures, new IpcDataCache.QueryHandler<KeyguardQuery, Integer>() { @Override public Integer apply(KeyguardQuery query) { try { return mService.getKeyguardDisabledFeatures( query.mAdmin, query.mUserHandle, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }}); /** @hide */ public static void disableGetKeyguardDisabledFeaturesCache() { sGetKeyguardDisabledFeatures.disable(); } private IpcDataCache<Pair<ComponentName, Integer>, Integer> mGetKeyGuardDisabledFeaturesCache = new IpcDataCache<>(sDpmCaches.child("getKeyguardDisabledFeatures"), (query) -> getService().getKeyguardDisabledFeatures( query.first, query.second, isParentInstance())); /** @hide per-user version */ @UnsupportedAppUsage public int getKeyguardDisabledFeatures(@Nullable ComponentName admin, int userHandle) { if (mService != null) { return mGetKeyGuardDisabledFeaturesCache.query(new KeyguardQuery(admin, userHandle)); return mGetKeyGuardDisabledFeaturesCache.query(new Pair<>(admin, userHandle)); } else { return KEYGUARD_DISABLE_FEATURES_NONE; } Loading Loading @@ -8864,23 +8814,9 @@ public class DevicePolicyManager { return name != null ? name.getPackageName() : null; } private static final BinderApi sHasDeviceOwner = new BinderApi("hasDeviceOwner"); private BinderCache<Void, Boolean> mHasDeviceOwnerCache = new BinderCache<>(sHasDeviceOwner, new IpcDataCache.QueryHandler<Void, Boolean>() { @Override public Boolean apply(Void query) { try { return mService.hasDeviceOwner(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }}); /** @hide */ public static void disableHasDeviceOwnerCache() { sHasDeviceOwner.disable(); } private IpcDataCache<Void, Boolean> mHasDeviceOwnerCache = new IpcDataCache<>(sDpmCaches.child("hasDeviceOwner"), (query) -> getService().hasDeviceOwner()); /** * Called by the system to find out whether the device is managed by a Device Owner. Loading Loading @@ -9256,25 +9192,10 @@ public class DevicePolicyManager { return null; } private final static BinderApi sGetProfileOwnerOrDeviceOwnerSupervisionComponent = new BinderApi("getProfileOwnerOrDeviceOwnerSupervisionComponent"); private final BinderCache<UserHandle, ComponentName> private final IpcDataCache<UserHandle, ComponentName> mGetProfileOwnerOrDeviceOwnerSupervisionComponentCache = new BinderCache(sGetProfileOwnerOrDeviceOwnerSupervisionComponent, new IpcDataCache.QueryHandler<UserHandle, ComponentName>() { @Override public ComponentName apply(UserHandle user) { try { return mService.getProfileOwnerOrDeviceOwnerSupervisionComponent( user); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } }}); /** @hide */ public static void disableGetProfileOwnerOrDeviceOwnerSupervisionComponentCache() { sGetProfileOwnerOrDeviceOwnerSupervisionComponent.disable(); } new IpcDataCache<>(sDpmCaches.child("getProfileOwnerOrDeviceOwnerSupervisionComponent"), (arg) -> getService().getProfileOwnerOrDeviceOwnerSupervisionComponent(arg)); /** * Returns the configured supervision app if it exists and is the device owner or policy owner. Loading Loading @@ -9329,23 +9250,9 @@ public class DevicePolicyManager { return null; } private final static BinderApi sIsOrganizationOwnedDeviceWithManagedProfile = new BinderApi("isOrganizationOwnedDeviceWithManagedProfile"); private final BinderCache<Void, Boolean> mIsOrganizationOwnedDeviceWithManagedProfileCache = new BinderCache(sIsOrganizationOwnedDeviceWithManagedProfile, new IpcDataCache.QueryHandler<Void, Boolean>() { @Override public Boolean apply(Void query) { try { return mService.isOrganizationOwnedDeviceWithManagedProfile(); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } }}); /** @hide */ public static void disableIsOrganizationOwnedDeviceWithManagedProfileCache() { sIsOrganizationOwnedDeviceWithManagedProfile.disable(); } private final IpcDataCache<Void, Boolean> mIsOrganizationOwnedDeviceWithManagedProfileCache = new IpcDataCache(sDpmCaches.child("isOrganizationOwnedDeviceWithManagedProfile"), (query) -> getService().isOrganizationOwnedDeviceWithManagedProfile()); /** * Apps can use this method to find out if the device was provisioned as Loading Loading @@ -12927,23 +12834,9 @@ public class DevicePolicyManager { } } private final static BinderApi sGetDeviceOwnerOrganizationName = new BinderApi("getDeviceOwnerOrganizationName"); private final BinderCache<Void, CharSequence> mGetDeviceOwnerOrganizationNameCache = new BinderCache(sGetDeviceOwnerOrganizationName, new IpcDataCache.QueryHandler<Void, CharSequence>() { @Override public CharSequence apply(Void query) { try { return mService.getDeviceOwnerOrganizationName(); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } }}); /** @hide */ public static void disableGetDeviceOwnerOrganizationNameCache() { sGetDeviceOwnerOrganizationName.disable(); } private final IpcDataCache<Void, CharSequence> mGetDeviceOwnerOrganizationNameCache = new IpcDataCache(sDpmCaches.child("getDeviceOwnerOrganizationName"), (query) -> getService().getDeviceOwnerOrganizationName()); /** * Called by the system to retrieve the name of the organization managing the device. Loading @@ -12960,23 +12853,9 @@ public class DevicePolicyManager { return mGetDeviceOwnerOrganizationNameCache.query(null); } private final static BinderApi sGetOrganizationNameForUser = new BinderApi("getOrganizationNameForUser"); private final BinderCache<Integer, CharSequence> mGetOrganizationNameForUserCache = new BinderCache(sGetOrganizationNameForUser, new IpcDataCache.QueryHandler<Integer, CharSequence>() { @Override public CharSequence apply(Integer userHandle) { try { return mService.getOrganizationNameForUser(userHandle); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } }}); /** @hide */ public static void disableGetOrganizationNameForUserCache() { sGetOrganizationNameForUser.disable(); } private final IpcDataCache<Integer, CharSequence> mGetOrganizationNameForUserCache = new IpcDataCache<>(sDpmCaches.child("getOrganizationNameForUser"), (query) -> getService().getOrganizationNameForUser(query)); /** * Retrieve the default title message used in the confirm credentials screen for a given user. Loading Loading @@ -13372,24 +13251,10 @@ public class DevicePolicyManager { } } private final static BinderApi sNetworkLoggingApi = new BinderApi("isNetworkLoggingEnabled"); private BinderCache<ComponentName, Boolean> mIsNetworkLoggingEnabledCache = new BinderCache<>(sNetworkLoggingApi, new IpcDataCache.QueryHandler<ComponentName, Boolean>() { @Override public Boolean apply(ComponentName admin) { try { return mService.isNetworkLoggingEnabled( admin, mContext.getPackageName()); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } }}); /** @hide */ public static void disableIsNetworkLoggingEnabled() { sNetworkLoggingApi.disable(); } private IpcDataCache<ComponentName, Boolean> mIsNetworkLoggingEnabledCache = new IpcDataCache<>(sDpmCaches.child("isNetworkLoggingEnabled"), (admin) -> getService().isNetworkLoggingEnabled(admin, getContext().getPackageName())); /** * Return whether network logging is enabled by a device owner or profile owner of core/java/android/os/IpcDataCache.java +209 −4 Original line number Diff line number Diff line Loading @@ -23,7 +23,7 @@ import android.annotation.SystemApi; import android.annotation.TestApi; import android.app.PropertyInvalidatedCache; import android.text.TextUtils; import android.util.Log; import android.util.ArraySet; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.FastPrintWriter; Loading @@ -35,7 +35,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; Loading Loading @@ -324,8 +323,8 @@ public class IpcDataCache<Query, Result> extends PropertyInvalidatedCache<Query, @SystemApi(client=SystemApi.Client.MODULE_LIBRARIES) @TestApi public IpcDataCache(int maxEntries, @NonNull @IpcDataCacheModule String module, @NonNull String api, @NonNull String cacheName, @NonNull QueryHandler<Query, Result> computer) { @NonNull String api, @NonNull String cacheName, @NonNull QueryHandler<Query, Result> computer) { super(maxEntries, module, api, cacheName, computer); } Loading Loading @@ -382,4 +381,210 @@ public class IpcDataCache<Query, Result> extends PropertyInvalidatedCache<Query, @NonNull String api) { PropertyInvalidatedCache.invalidateCache(module, api); } /** * This is a convenience class that encapsulates configuration information for a * cache. It may be supplied to the cache constructors in lieu of the other * parameters. The class captures maximum entry count, the module, the key, and the * api. * * There are three specific use cases supported by this class. * * 1. Instance-per-cache: create a static instance of this class using the same * parameters as would have been given to IpcDataCache (or * PropertyInvalidatedCache). This static instance provides a hook for the * invalidateCache() and disableForLocalProcess() calls, which, generally, must * also be static. * * 2. Short-hand for shared configuration parameters: create an instance of this class * to capture the maximum number of entries and the module to be used by more than * one cache in the class. Refer to this instance when creating new configs. Only * the api and (optionally key) for the new cache must be supplied. * * 3. Tied caches: create a static instance of this class to capture the maximum * number of entries, the module, and the key. Refer to this instance when * creating a new config that differs in only the api. The new config can be * created as part of the cache constructor. All caches that trace back to the * root config share the same key and are invalidated by the invalidateCache() * method of the root config. All caches that trace back to the root config can be * disabled in the local process by the disableAllForCurrentProcess() method of the * root config. * * @hide */ public static class Config { private final int mMaxEntries; @IpcDataCacheModule private final String mModule; private final String mApi; private final String mName; /** * The list of cache names that were created extending this Config. If * disableForCurrentProcess() is invoked on this config then all children will be * disabled. Furthermore, any new children based off of this config will be * disabled. The construction order guarantees that new caches will be disabled * before they are created (the Config must be created before the IpcDataCache is * created). */ private ArraySet<String> mChildren; /** * True if registered children are disabled in the current process. If this is * true then all new children are disabled as they are registered. */ private boolean mDisabled = false; public Config(int maxEntries, @NonNull @IpcDataCacheModule String module, @NonNull String api, @NonNull String name) { mMaxEntries = maxEntries; mModule = module; mApi = api; mName = name; } /** * A short-hand constructor that makes the name the same as the api. */ public Config(int maxEntries, @NonNull @IpcDataCacheModule String module, @NonNull String api) { this(maxEntries, module, api, api); } /** * Copy the module and max entries from the Config and take the api and name from * the parameter list. */ public Config(@NonNull Config root, @NonNull String api, @NonNull String name) { this(root.maxEntries(), root.module(), api, name); } /** * Copy the module and max entries from the Config and take the api and name from * the parameter list. */ public Config(@NonNull Config root, @NonNull String api) { this(root.maxEntries(), root.module(), api, api); } /** * Fetch a config that is a child of <this>. The child shares the same api as the * parent and is registered with the parent for the purposes of disabling in the * current process. */ public Config child(@NonNull String name) { final Config result = new Config(this, api(), name); registerChild(name); return result; } public final int maxEntries() { return mMaxEntries; } @IpcDataCacheModule public final @NonNull String module() { return mModule; } public final @NonNull String api() { return mApi; } public final @NonNull String name() { return mName; } /** * Register a child cache name. If disableForCurrentProcess() has been called * against this cache, disable th new child. */ private final void registerChild(String name) { synchronized (this) { if (mChildren == null) { mChildren = new ArraySet<>(); } mChildren.add(name); if (mDisabled) { IpcDataCache.disableForCurrentProcess(name); } } } /** * Invalidate all caches that share this Config's module and api. */ public void invalidateCache() { IpcDataCache.invalidateCache(mModule, mApi); } /** * Disable all caches that share this Config's name. */ public void disableForCurrentProcess() { IpcDataCache.disableForCurrentProcess(mName); } /** * Disable this cache and all children. Any child that is added in the future * will alwo be disabled. */ public void disableAllForCurrentProcess() { synchronized (this) { mDisabled = true; disableForCurrentProcess(); if (mChildren != null) { for (String c : mChildren) { IpcDataCache.disableForCurrentProcess(c); } } } } } /** * Create a new cache using a config. * @hide */ public IpcDataCache(@NonNull Config config, @NonNull QueryHandler<Query, Result> computer) { super(config.maxEntries(), config.module(), config.api(), config.name(), computer); } /** * An interface suitable for a lambda expression instead of a QueryHandler. * @hide */ public interface RemoteCall<Query, Result> { Result apply(Query query) throws RemoteException; } /** * This is a query handler that is created with a lambda expression that is invoked * every time the handler is called. The handler is specifically meant for services * hosted by system_server; the handler automatically rethrows RemoteException as a * RuntimeException, which is the usual handling for failed binder calls. */ private static class SystemServerCallHandler<Query, Result> extends IpcDataCache.QueryHandler<Query, Result> { private final RemoteCall<Query, Result> mHandler; public SystemServerCallHandler(RemoteCall handler) { mHandler = handler; } @Override public Result apply(Query query) { try { return mHandler.apply(query); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } /** * Create a cache using a config and a lambda expression. * @hide */ public IpcDataCache(@NonNull Config config, @NonNull RemoteCall<Query, Result> computer) { this(config, new SystemServerCallHandler<>(computer)); } } core/tests/coretests/src/android/os/IpcDataCacheTest.java +104 −0 File changed.Preview size limit exceeded, changes collapsed. Show changes services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +1 −1 Original line number Diff line number Diff line Loading @@ -1781,7 +1781,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @VisibleForTesting DevicePolicyManagerService(Injector injector) { DevicePolicyManager.disableGetKeyguardDisabledFeaturesCache(); DevicePolicyManager.disableLocalCaches(); mInjector = injector; mContext = Objects.requireNonNull(injector.mContext); Loading Loading
core/java/android/app/PropertyInvalidatedCache.java +17 −4 Original line number Diff line number Diff line Loading @@ -313,6 +313,7 @@ public class PropertyInvalidatedCache<Query, Result> { * one of the permitted values above. The API is a string that is a legal Java simple * identifier. The api is modified to conform to the system property style guide by * replacing every upper case letter with an underscore and the lower case equivalent. * (An initial upper case letter is not prefixed with an underscore). * There is no requirement that the apiName be the name of an actual API. * * Be aware that SystemProperties has a maximum length which is private to the Loading @@ -326,7 +327,7 @@ public class PropertyInvalidatedCache<Query, Result> { @NonNull String apiName) { char[] api = apiName.toCharArray(); int upper = 0; for (int i = 0; i < api.length; i++) { for (int i = 1; i < api.length; i++) { if (Character.isUpperCase(api[i])) { upper++; } Loading @@ -336,7 +337,9 @@ public class PropertyInvalidatedCache<Query, Result> { for (int i = 0; i < api.length; i++) { if (Character.isJavaIdentifierPart(api[i])) { if (Character.isUpperCase(api[i])) { if (i > 0) { suffix[j++] = '_'; } suffix[j++] = Character.toLowerCase(api[i]); } else { suffix[j++] = api[i]; Loading Loading @@ -1286,12 +1289,22 @@ public class PropertyInvalidatedCache<Query, Result> { } /** * Return the name of the cache, to be used in debug messages. * Return the name of the cache, to be used in debug messages. This is exposed * primarily for testing. * @hide */ private final @NonNull String cacheName() { public final @NonNull String cacheName() { return mCacheName; } /** * Return the property used by the cache. This is primarily for test purposes. * @hide */ public final @NonNull String propertyName() { return mPropertyName; } /** * Return the query as a string, to be used in debug messages. New clients should not * override this, but should instead add the necessary toString() method to the Query Loading
core/java/android/app/admin/DevicePolicyManager.java +57 −192 Original line number Diff line number Diff line Loading @@ -185,6 +185,30 @@ public class DevicePolicyManager { mResourcesManager = new DevicePolicyResourcesManager(context, service); } /** * Fetch the current value of mService. This is used in the binder cache lambda * expressions. */ private final IDevicePolicyManager getService() { return mService; } /** * Fetch the current value of mParentInstance. This is used in the binder cache * lambda expressions. */ private final boolean isParentInstance() { return mParentInstance; } /** * Fetch the current value of mContext. This is used in the binder cache lambda * expressions. */ private final Context getContext() { return mContext; } /** @hide test will override it. */ @VisibleForTesting protected int myUserId() { Loading Loading @@ -3783,57 +3807,21 @@ public class DevicePolicyManager { "android.app.extra.RESOURCE_IDS"; /** * A convenience class that wraps some IpcDataCache methods. Instantiate it with an * API string. Instances can and should be final static. All instances of this class * use the same key for invalidation. * This object is a single place to tack on invalidation and disable calls. All * binder caches in this class derive from this Config, so all can be invalidated or * disabled through this Config. */ private static class BinderApi { private final static String KEY = "DevicePolicyManager"; private final String mApi; BinderApi(String api) { mApi = api; } final String api() { return mApi; } final String key() { return KEY; } final static void invalidate() { IpcDataCache.invalidateCache(IpcDataCache.MODULE_SYSTEM, KEY); } final void disable() { IpcDataCache.disableForCurrentProcess(mApi); } } private static final IpcDataCache.Config sDpmCaches = new IpcDataCache.Config(8, IpcDataCache.MODULE_SYSTEM, "DevicePolicyManagerCaches"); /** @hide */ public static void invalidateBinderCaches() { BinderApi.invalidate(); } /** * A simple wrapper for binder caches in this class. All caches are created with a * maximum of 8 entries, the SYSTEM module, and a cache name that is the same as the api. */ private static class BinderCache<Q,R> extends IpcDataCache<Q,R> { BinderCache(BinderApi api, IpcDataCache.QueryHandler<Q,R> handler) { super(8, IpcDataCache.MODULE_SYSTEM, api.key(), api.api(), handler); } sDpmCaches.invalidateCache(); } /** * Disable all caches in the local process. * @hide */ public static void disableLocalProcessCaches() { disableGetKeyguardDisabledFeaturesCache(); disableHasDeviceOwnerCache(); disableGetProfileOwnerOrDeviceOwnerSupervisionComponentCache(); disableIsOrganizationOwnedDeviceWithManagedProfileCache(); disableGetDeviceOwnerOrganizationNameCache(); disableGetOrganizationNameForUserCache(); disableIsNetworkLoggingEnabled(); /** @hide */ public static void disableLocalCaches() { sDpmCaches.disableAllForCurrentProcess(); } /** @hide */ Loading Loading @@ -8435,54 +8423,16 @@ public class DevicePolicyManager { return getKeyguardDisabledFeatures(admin, myUserId()); } // A key into the keyguard cache. private static class KeyguardQuery { private final ComponentName mAdmin; private final int mUserHandle; KeyguardQuery(@Nullable ComponentName admin, int userHandle) { mAdmin = admin; mUserHandle = userHandle; } public boolean equals(Object o) { if (o instanceof KeyguardQuery) { KeyguardQuery r = (KeyguardQuery) o; return Objects.equals(mAdmin, r.mAdmin) && mUserHandle == r.mUserHandle; } else { return false; } } public int hashCode() { return ((mAdmin != null) ? mAdmin.hashCode() : 0) * 13 + mUserHandle; } } // The query handler does not cache wildcard user IDs, although they should never // appear in the query. private static final BinderApi sGetKeyguardDisabledFeatures = new BinderApi("getKeyguardDisabledFeatures"); private BinderCache<KeyguardQuery, Integer> mGetKeyGuardDisabledFeaturesCache = new BinderCache<>(sGetKeyguardDisabledFeatures, new IpcDataCache.QueryHandler<KeyguardQuery, Integer>() { @Override public Integer apply(KeyguardQuery query) { try { return mService.getKeyguardDisabledFeatures( query.mAdmin, query.mUserHandle, mParentInstance); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }}); /** @hide */ public static void disableGetKeyguardDisabledFeaturesCache() { sGetKeyguardDisabledFeatures.disable(); } private IpcDataCache<Pair<ComponentName, Integer>, Integer> mGetKeyGuardDisabledFeaturesCache = new IpcDataCache<>(sDpmCaches.child("getKeyguardDisabledFeatures"), (query) -> getService().getKeyguardDisabledFeatures( query.first, query.second, isParentInstance())); /** @hide per-user version */ @UnsupportedAppUsage public int getKeyguardDisabledFeatures(@Nullable ComponentName admin, int userHandle) { if (mService != null) { return mGetKeyGuardDisabledFeaturesCache.query(new KeyguardQuery(admin, userHandle)); return mGetKeyGuardDisabledFeaturesCache.query(new Pair<>(admin, userHandle)); } else { return KEYGUARD_DISABLE_FEATURES_NONE; } Loading Loading @@ -8864,23 +8814,9 @@ public class DevicePolicyManager { return name != null ? name.getPackageName() : null; } private static final BinderApi sHasDeviceOwner = new BinderApi("hasDeviceOwner"); private BinderCache<Void, Boolean> mHasDeviceOwnerCache = new BinderCache<>(sHasDeviceOwner, new IpcDataCache.QueryHandler<Void, Boolean>() { @Override public Boolean apply(Void query) { try { return mService.hasDeviceOwner(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } }}); /** @hide */ public static void disableHasDeviceOwnerCache() { sHasDeviceOwner.disable(); } private IpcDataCache<Void, Boolean> mHasDeviceOwnerCache = new IpcDataCache<>(sDpmCaches.child("hasDeviceOwner"), (query) -> getService().hasDeviceOwner()); /** * Called by the system to find out whether the device is managed by a Device Owner. Loading Loading @@ -9256,25 +9192,10 @@ public class DevicePolicyManager { return null; } private final static BinderApi sGetProfileOwnerOrDeviceOwnerSupervisionComponent = new BinderApi("getProfileOwnerOrDeviceOwnerSupervisionComponent"); private final BinderCache<UserHandle, ComponentName> private final IpcDataCache<UserHandle, ComponentName> mGetProfileOwnerOrDeviceOwnerSupervisionComponentCache = new BinderCache(sGetProfileOwnerOrDeviceOwnerSupervisionComponent, new IpcDataCache.QueryHandler<UserHandle, ComponentName>() { @Override public ComponentName apply(UserHandle user) { try { return mService.getProfileOwnerOrDeviceOwnerSupervisionComponent( user); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } }}); /** @hide */ public static void disableGetProfileOwnerOrDeviceOwnerSupervisionComponentCache() { sGetProfileOwnerOrDeviceOwnerSupervisionComponent.disable(); } new IpcDataCache<>(sDpmCaches.child("getProfileOwnerOrDeviceOwnerSupervisionComponent"), (arg) -> getService().getProfileOwnerOrDeviceOwnerSupervisionComponent(arg)); /** * Returns the configured supervision app if it exists and is the device owner or policy owner. Loading Loading @@ -9329,23 +9250,9 @@ public class DevicePolicyManager { return null; } private final static BinderApi sIsOrganizationOwnedDeviceWithManagedProfile = new BinderApi("isOrganizationOwnedDeviceWithManagedProfile"); private final BinderCache<Void, Boolean> mIsOrganizationOwnedDeviceWithManagedProfileCache = new BinderCache(sIsOrganizationOwnedDeviceWithManagedProfile, new IpcDataCache.QueryHandler<Void, Boolean>() { @Override public Boolean apply(Void query) { try { return mService.isOrganizationOwnedDeviceWithManagedProfile(); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } }}); /** @hide */ public static void disableIsOrganizationOwnedDeviceWithManagedProfileCache() { sIsOrganizationOwnedDeviceWithManagedProfile.disable(); } private final IpcDataCache<Void, Boolean> mIsOrganizationOwnedDeviceWithManagedProfileCache = new IpcDataCache(sDpmCaches.child("isOrganizationOwnedDeviceWithManagedProfile"), (query) -> getService().isOrganizationOwnedDeviceWithManagedProfile()); /** * Apps can use this method to find out if the device was provisioned as Loading Loading @@ -12927,23 +12834,9 @@ public class DevicePolicyManager { } } private final static BinderApi sGetDeviceOwnerOrganizationName = new BinderApi("getDeviceOwnerOrganizationName"); private final BinderCache<Void, CharSequence> mGetDeviceOwnerOrganizationNameCache = new BinderCache(sGetDeviceOwnerOrganizationName, new IpcDataCache.QueryHandler<Void, CharSequence>() { @Override public CharSequence apply(Void query) { try { return mService.getDeviceOwnerOrganizationName(); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } }}); /** @hide */ public static void disableGetDeviceOwnerOrganizationNameCache() { sGetDeviceOwnerOrganizationName.disable(); } private final IpcDataCache<Void, CharSequence> mGetDeviceOwnerOrganizationNameCache = new IpcDataCache(sDpmCaches.child("getDeviceOwnerOrganizationName"), (query) -> getService().getDeviceOwnerOrganizationName()); /** * Called by the system to retrieve the name of the organization managing the device. Loading @@ -12960,23 +12853,9 @@ public class DevicePolicyManager { return mGetDeviceOwnerOrganizationNameCache.query(null); } private final static BinderApi sGetOrganizationNameForUser = new BinderApi("getOrganizationNameForUser"); private final BinderCache<Integer, CharSequence> mGetOrganizationNameForUserCache = new BinderCache(sGetOrganizationNameForUser, new IpcDataCache.QueryHandler<Integer, CharSequence>() { @Override public CharSequence apply(Integer userHandle) { try { return mService.getOrganizationNameForUser(userHandle); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } }}); /** @hide */ public static void disableGetOrganizationNameForUserCache() { sGetOrganizationNameForUser.disable(); } private final IpcDataCache<Integer, CharSequence> mGetOrganizationNameForUserCache = new IpcDataCache<>(sDpmCaches.child("getOrganizationNameForUser"), (query) -> getService().getOrganizationNameForUser(query)); /** * Retrieve the default title message used in the confirm credentials screen for a given user. Loading Loading @@ -13372,24 +13251,10 @@ public class DevicePolicyManager { } } private final static BinderApi sNetworkLoggingApi = new BinderApi("isNetworkLoggingEnabled"); private BinderCache<ComponentName, Boolean> mIsNetworkLoggingEnabledCache = new BinderCache<>(sNetworkLoggingApi, new IpcDataCache.QueryHandler<ComponentName, Boolean>() { @Override public Boolean apply(ComponentName admin) { try { return mService.isNetworkLoggingEnabled( admin, mContext.getPackageName()); } catch (RemoteException re) { throw re.rethrowFromSystemServer(); } }}); /** @hide */ public static void disableIsNetworkLoggingEnabled() { sNetworkLoggingApi.disable(); } private IpcDataCache<ComponentName, Boolean> mIsNetworkLoggingEnabledCache = new IpcDataCache<>(sDpmCaches.child("isNetworkLoggingEnabled"), (admin) -> getService().isNetworkLoggingEnabled(admin, getContext().getPackageName())); /** * Return whether network logging is enabled by a device owner or profile owner of
core/java/android/os/IpcDataCache.java +209 −4 Original line number Diff line number Diff line Loading @@ -23,7 +23,7 @@ import android.annotation.SystemApi; import android.annotation.TestApi; import android.app.PropertyInvalidatedCache; import android.text.TextUtils; import android.util.Log; import android.util.ArraySet; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.FastPrintWriter; Loading @@ -35,7 +35,6 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; Loading Loading @@ -324,8 +323,8 @@ public class IpcDataCache<Query, Result> extends PropertyInvalidatedCache<Query, @SystemApi(client=SystemApi.Client.MODULE_LIBRARIES) @TestApi public IpcDataCache(int maxEntries, @NonNull @IpcDataCacheModule String module, @NonNull String api, @NonNull String cacheName, @NonNull QueryHandler<Query, Result> computer) { @NonNull String api, @NonNull String cacheName, @NonNull QueryHandler<Query, Result> computer) { super(maxEntries, module, api, cacheName, computer); } Loading Loading @@ -382,4 +381,210 @@ public class IpcDataCache<Query, Result> extends PropertyInvalidatedCache<Query, @NonNull String api) { PropertyInvalidatedCache.invalidateCache(module, api); } /** * This is a convenience class that encapsulates configuration information for a * cache. It may be supplied to the cache constructors in lieu of the other * parameters. The class captures maximum entry count, the module, the key, and the * api. * * There are three specific use cases supported by this class. * * 1. Instance-per-cache: create a static instance of this class using the same * parameters as would have been given to IpcDataCache (or * PropertyInvalidatedCache). This static instance provides a hook for the * invalidateCache() and disableForLocalProcess() calls, which, generally, must * also be static. * * 2. Short-hand for shared configuration parameters: create an instance of this class * to capture the maximum number of entries and the module to be used by more than * one cache in the class. Refer to this instance when creating new configs. Only * the api and (optionally key) for the new cache must be supplied. * * 3. Tied caches: create a static instance of this class to capture the maximum * number of entries, the module, and the key. Refer to this instance when * creating a new config that differs in only the api. The new config can be * created as part of the cache constructor. All caches that trace back to the * root config share the same key and are invalidated by the invalidateCache() * method of the root config. All caches that trace back to the root config can be * disabled in the local process by the disableAllForCurrentProcess() method of the * root config. * * @hide */ public static class Config { private final int mMaxEntries; @IpcDataCacheModule private final String mModule; private final String mApi; private final String mName; /** * The list of cache names that were created extending this Config. If * disableForCurrentProcess() is invoked on this config then all children will be * disabled. Furthermore, any new children based off of this config will be * disabled. The construction order guarantees that new caches will be disabled * before they are created (the Config must be created before the IpcDataCache is * created). */ private ArraySet<String> mChildren; /** * True if registered children are disabled in the current process. If this is * true then all new children are disabled as they are registered. */ private boolean mDisabled = false; public Config(int maxEntries, @NonNull @IpcDataCacheModule String module, @NonNull String api, @NonNull String name) { mMaxEntries = maxEntries; mModule = module; mApi = api; mName = name; } /** * A short-hand constructor that makes the name the same as the api. */ public Config(int maxEntries, @NonNull @IpcDataCacheModule String module, @NonNull String api) { this(maxEntries, module, api, api); } /** * Copy the module and max entries from the Config and take the api and name from * the parameter list. */ public Config(@NonNull Config root, @NonNull String api, @NonNull String name) { this(root.maxEntries(), root.module(), api, name); } /** * Copy the module and max entries from the Config and take the api and name from * the parameter list. */ public Config(@NonNull Config root, @NonNull String api) { this(root.maxEntries(), root.module(), api, api); } /** * Fetch a config that is a child of <this>. The child shares the same api as the * parent and is registered with the parent for the purposes of disabling in the * current process. */ public Config child(@NonNull String name) { final Config result = new Config(this, api(), name); registerChild(name); return result; } public final int maxEntries() { return mMaxEntries; } @IpcDataCacheModule public final @NonNull String module() { return mModule; } public final @NonNull String api() { return mApi; } public final @NonNull String name() { return mName; } /** * Register a child cache name. If disableForCurrentProcess() has been called * against this cache, disable th new child. */ private final void registerChild(String name) { synchronized (this) { if (mChildren == null) { mChildren = new ArraySet<>(); } mChildren.add(name); if (mDisabled) { IpcDataCache.disableForCurrentProcess(name); } } } /** * Invalidate all caches that share this Config's module and api. */ public void invalidateCache() { IpcDataCache.invalidateCache(mModule, mApi); } /** * Disable all caches that share this Config's name. */ public void disableForCurrentProcess() { IpcDataCache.disableForCurrentProcess(mName); } /** * Disable this cache and all children. Any child that is added in the future * will alwo be disabled. */ public void disableAllForCurrentProcess() { synchronized (this) { mDisabled = true; disableForCurrentProcess(); if (mChildren != null) { for (String c : mChildren) { IpcDataCache.disableForCurrentProcess(c); } } } } } /** * Create a new cache using a config. * @hide */ public IpcDataCache(@NonNull Config config, @NonNull QueryHandler<Query, Result> computer) { super(config.maxEntries(), config.module(), config.api(), config.name(), computer); } /** * An interface suitable for a lambda expression instead of a QueryHandler. * @hide */ public interface RemoteCall<Query, Result> { Result apply(Query query) throws RemoteException; } /** * This is a query handler that is created with a lambda expression that is invoked * every time the handler is called. The handler is specifically meant for services * hosted by system_server; the handler automatically rethrows RemoteException as a * RuntimeException, which is the usual handling for failed binder calls. */ private static class SystemServerCallHandler<Query, Result> extends IpcDataCache.QueryHandler<Query, Result> { private final RemoteCall<Query, Result> mHandler; public SystemServerCallHandler(RemoteCall handler) { mHandler = handler; } @Override public Result apply(Query query) { try { return mHandler.apply(query); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } /** * Create a cache using a config and a lambda expression. * @hide */ public IpcDataCache(@NonNull Config config, @NonNull RemoteCall<Query, Result> computer) { this(config, new SystemServerCallHandler<>(computer)); } }
core/tests/coretests/src/android/os/IpcDataCacheTest.java +104 −0 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +1 −1 Original line number Diff line number Diff line Loading @@ -1781,7 +1781,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { @VisibleForTesting DevicePolicyManagerService(Injector injector) { DevicePolicyManager.disableGetKeyguardDisabledFeaturesCache(); DevicePolicyManager.disableLocalCaches(); mInjector = injector; mContext = Objects.requireNonNull(injector.mContext); Loading