• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.app.compat;
18 
19 import android.annotation.NonNull;
20 import android.app.PropertyInvalidatedCache;
21 import android.content.Context;
22 import android.os.Binder;
23 import android.os.RemoteException;
24 import android.os.ServiceManager;
25 
26 import com.android.internal.compat.IPlatformCompat;
27 
28 /**
29  * Handles caching of calls to {@link com.android.internal.compat.IPlatformCompat}
30  * @hide
31  */
32 @android.ravenwood.annotation.RavenwoodKeepWholeClass
33 public final class ChangeIdStateCache
34         extends PropertyInvalidatedCache<ChangeIdStateQuery, Boolean> {
35 
36     private static final String CACHE_MODULE = PropertyInvalidatedCache.MODULE_SYSTEM;
37     private static final String CACHE_API = "is_compat_change_enabled";
38 
39     private static final int MAX_ENTRIES = 2048;
40     private static boolean sDisabled = getDefaultDisabled();
41     private volatile IPlatformCompat mPlatformCompat;
42 
43 
44     @android.ravenwood.annotation.RavenwoodReplace
getDefaultDisabled()45     private static boolean getDefaultDisabled() {
46         return false;
47     }
48 
getDefaultDisabled$ravenwood()49     private static boolean getDefaultDisabled$ravenwood() {
50         return true; // TODO(b/376676753) Disable the cache for now.
51     }
52 
53     /** @hide */
ChangeIdStateCache()54     public ChangeIdStateCache() {
55         super(new PropertyInvalidatedCache.Args(CACHE_MODULE)
56                 .maxEntries(MAX_ENTRIES)
57                 .isolateUids(false)
58                 .cacheNulls(false)
59                 .api(CACHE_API),
60                 CACHE_API, null);
61     }
62 
63     /**
64      * Disable cache.
65      *
66      * <p>Should only be used in unit tests.
67      * @hide
68      */
disable()69     public static void disable() {
70         sDisabled = true;
71     }
72 
73     /**
74      * Invalidate the cache.
75      *
76      * <p>Can only be called by the system server process.
77      * @hide
78      */
invalidate()79     public static void invalidate() {
80         if (!sDisabled) {
81             PropertyInvalidatedCache.invalidateCache(CACHE_MODULE, CACHE_API);
82         }
83     }
84 
85     @NonNull
getPlatformCompatService()86     IPlatformCompat getPlatformCompatService() {
87         IPlatformCompat platformCompat = mPlatformCompat;
88         if (platformCompat == null) {
89             synchronized (this) {
90                 platformCompat = mPlatformCompat;
91                 if (platformCompat == null) {
92                     platformCompat = IPlatformCompat.Stub.asInterface(
93                         ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
94                     if (platformCompat == null) {
95                         throw new RuntimeException(
96                             "Could not get PlatformCompatService instance!");
97                     }
98                     mPlatformCompat = platformCompat;
99                 }
100             }
101         }
102         return platformCompat;
103     }
104 
105     @Override
recompute(ChangeIdStateQuery query)106     public Boolean recompute(ChangeIdStateQuery query) {
107         final long token = Binder.clearCallingIdentity();
108         try {
109             if (query.type == ChangeIdStateQuery.QUERY_BY_PACKAGE_NAME) {
110                 return getPlatformCompatService().isChangeEnabledByPackageName(query.changeId,
111                                                                    query.packageName,
112                                                                    query.userId);
113             } else if (query.type == ChangeIdStateQuery.QUERY_BY_UID) {
114                 return getPlatformCompatService().isChangeEnabledByUid(query.changeId, query.uid);
115             } else {
116                 throw new IllegalArgumentException("Invalid query type: " + query.type);
117             }
118         } catch (RemoteException e) {
119             e.rethrowFromSystemServer();
120         } finally {
121             Binder.restoreCallingIdentity(token);
122         }
123         throw new IllegalStateException("Could not recompute value!");
124     }
125 }
126