1 /* 2 * Copyright (C) 2022 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.os; 18 19 import android.annotation.FlaggedApi; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.StringDef; 23 import android.annotation.SystemApi; 24 import android.annotation.TestApi; 25 import android.app.PropertyInvalidatedCache; 26 import android.app.PropertyInvalidatedCache.Args; 27 import android.text.TextUtils; 28 import android.util.ArraySet; 29 30 import com.android.internal.annotations.GuardedBy; 31 import com.android.internal.util.FastPrintWriter; 32 33 import java.lang.annotation.Retention; 34 import java.lang.annotation.RetentionPolicy; 35 import java.io.FileOutputStream; 36 import java.io.IOException; 37 import java.io.PrintWriter; 38 import java.util.ArrayList; 39 import java.util.HashMap; 40 import java.util.LinkedHashMap; 41 import java.util.Map; 42 import java.util.Objects; 43 import java.util.Random; 44 import java.util.Set; 45 import java.util.WeakHashMap; 46 import java.util.concurrent.atomic.AtomicLong; 47 48 /** 49 * LRU cache that's invalidated when an opaque value in a property changes. Self-synchronizing, 50 * but doesn't hold a lock across data fetches on query misses. 51 * 52 * Clients should be aware of the following commonly-seen issues: 53 * <ul> 54 * 55 * <li>Client calls will not go through the cache before the first invalidation signal is 56 * received. Therefore, servers should signal an invalidation as soon as they have data to offer to 57 * clients. 58 * 59 * <li>Cache invalidation is restricted to well-known processes, which means that test code cannot 60 * invalidate a cache. {@link #disableForTestMode()} and {@link #testPropertyName} must be used in 61 * test processes that attempt cache invalidation. See 62 * {@link PropertyInvalidatedCacheTest#testBasicCache()} for an example. 63 * 64 * </ul> 65 * 66 * The intended use case is caching frequently-read, seldom-changed information normally retrieved 67 * across interprocess communication. Imagine that you've written a user birthday information 68 * daemon called "birthdayd" that exposes an {@code IUserBirthdayService} interface over 69 * binder. That binder interface looks something like this: 70 * 71 * <pre> 72 * parcelable Birthday { 73 * int month; 74 * int day; 75 * } 76 * interface IUserBirthdayService { 77 * Birthday getUserBirthday(int userId); 78 * } 79 * </pre> 80 * 81 * Suppose the service implementation itself looks like this... 82 * 83 * <pre> 84 * public class UserBirthdayServiceImpl implements IUserBirthdayService { 85 * private final HashMap<Integer, Birthday%> mUidToBirthday; 86 * {@literal @}Override 87 * public synchronized Birthday getUserBirthday(int userId) { 88 * return mUidToBirthday.get(userId); 89 * } 90 * private synchronized void updateBirthdays(Map<Integer, Birthday%> uidToBirthday) { 91 * mUidToBirthday.clear(); 92 * mUidToBirthday.putAll(uidToBirthday); 93 * } 94 * } 95 * </pre> 96 * 97 * ... and we have a client in frameworks (loaded into every app process) that looks like this: 98 * 99 * <pre> 100 * public class ActivityThread { 101 * ... 102 * public Birthday getUserBirthday(int userId) { 103 * return GetService("birthdayd").getUserBirthday(userId); 104 * } 105 * ... 106 * } 107 * </pre> 108 * 109 * With this code, every time an app calls {@code getUserBirthday(uid)}, we make a binder call to 110 * the birthdayd process and consult its database of birthdays. If we query user birthdays 111 * frequently, we do a lot of work that we don't have to do, since user birthdays change 112 * infrequently. 113 * 114 * IpcDataCache is part of a pattern for optimizing this kind of information-querying code. Using 115 * {@code IpcDataCache}, you'd write the client this way: 116 * 117 * <pre> 118 * public class ActivityThread { 119 * ... 120 * private final IpcDataCache.QueryHandler<Integer, Birthday> mBirthdayQuery = 121 * new IpcDataCache.QueryHandler<Integer, Birthday>() { 122 * {@literal @}Override 123 * public Birthday apply(Integer) { 124 * return GetService("birthdayd").getUserBirthday(userId); 125 * } 126 * }; 127 * private static final int BDAY_CACHE_MAX = 8; // Maximum birthdays to cache 128 * private static final String BDAY_API = "getUserBirthday"; 129 * private final IpcDataCache<Integer, Birthday%> mBirthdayCache = new 130 * IpcDataCache<Integer, Birthday%>( 131 * BDAY_CACHE_MAX, MODULE_SYSTEM, BDAY_API, BDAY_API, mBirthdayQuery); 132 * 133 * public void disableUserBirthdayCache() { 134 * mBirthdayCache.disableForCurrentProcess(); 135 * } 136 * public void invalidateUserBirthdayCache() { 137 * mBirthdayCache.invalidateCache(); 138 * } 139 * public Birthday getUserBirthday(int userId) { 140 * return mBirthdayCache.query(userId); 141 * } 142 * ... 143 * } 144 * </pre> 145 * 146 * With this cache, clients perform a binder call to birthdayd if asking for a user's birthday 147 * for the first time; on subsequent queries, we return the already-known Birthday object. 148 * 149 * The second parameter to the IpcDataCache constructor is a string that identifies the "module" 150 * that owns the cache. There are some well-known modules (such as {@code MODULE_SYSTEM} but any 151 * string is permitted. The third parameters is the name of the API being cached; this, too, can 152 * any value. The fourth is the name of the cache. The cache is usually named after th API. 153 * Some things you must know about the three strings: 154 * <ul> 155 * <li> The system property that controls the cache is named {@code cache_key.<module>.<api>}. 156 * Usually, the SELinux rules permit a process to write a system property (and therefore 157 * invalidate a cache) based on the wildcard {@code cache_key.<module>.*}. This means that 158 * although the cache can be constructed with any module string, whatever string is chosen must be 159 * consistent with the SELinux configuration. 160 * <li> The API name can be any string of alphanumeric characters. All caches with the same API 161 * are invalidated at the same time. If a server supports several caches and all are invalidated 162 * in common, then it is most efficient to assign the same API string to every cache. 163 * <li> The cache name can be any string. In debug output, the name is used to distiguish between 164 * caches with the same API name. The cache name is also used when disabling caches in the 165 * current process. So, invalidation is based on the module+api but disabling (which is generally 166 * a once-per-process operation) is based on the cache name. 167 * </ul> 168 * 169 * User birthdays do occasionally change, so we have to modify the server to invalidate this 170 * cache when necessary. That invalidation code looks like this: 171 * 172 * <pre> 173 * public class UserBirthdayServiceImpl { 174 * ... 175 * public UserBirthdayServiceImpl() { 176 * ... 177 * ActivityThread.currentActivityThread().disableUserBirthdayCache(); 178 * ActivityThread.currentActivityThread().invalidateUserBirthdayCache(); 179 * } 180 * 181 * private synchronized void updateBirthdays(Map<Integer, Birthday%> uidToBirthday) { 182 * mUidToBirthday.clear(); 183 * mUidToBirthday.putAll(uidToBirthday); 184 * ActivityThread.currentActivityThread().invalidateUserBirthdayCache(); 185 * } 186 * ... 187 * } 188 * </pre> 189 * 190 * The call to {@code IpcDataCache.invalidateCache()} guarantees that all clients will re-fetch 191 * birthdays from binder during consequent calls to 192 * {@code ActivityThread.getUserBirthday()}. Because the invalidate call happens with the lock 193 * held, we maintain consistency between different client views of the birthday state. The use of 194 * IpcDataCache in this idiomatic way introduces no new race conditions. 195 * 196 * IpcDataCache has a few other features for doing things like incremental enhancement of cached 197 * values and invalidation of multiple caches (that all share the same property key) at once. 198 * 199 * {@code BDAY_CACHE_KEY} is the name of a property that we set to an opaque unique value each 200 * time we update the cache. SELinux configuration must allow everyone to read this property 201 * and it must allow any process that needs to invalidate the cache (here, birthdayd) to write 202 * the property. (These properties conventionally begin with the "cache_key." prefix.) 203 * 204 * The {@code UserBirthdayServiceImpl} constructor calls {@code disableUserBirthdayCache()} so 205 * that calls to {@code getUserBirthday} from inside birthdayd don't go through the cache. In this 206 * local case, there's no IPC, so use of the cache is (depending on exact circumstance) 207 * unnecessary. 208 * 209 * There may be queries for which it is more efficient to bypass the cache than to cache the 210 * result. This would be true, for example, if some queries would require frequent cache 211 * invalidation while other queries require infrequent invalidation. To expand on the birthday 212 * example, suppose that there is a userId that signifies "the next birthday". When passed this 213 * userId, the server returns the next birthday among all users - this value changes as time 214 * advances. The userId value can be cached, but the cache must be invalidated whenever a 215 * birthday occurs, and this invalidates all birthdays. If there is a large number of users, 216 * invalidation will happen so often that the cache provides no value. 217 * 218 * The class provides a bypass mechanism to handle this situation. 219 * <pre> 220 * public class ActivityThread { 221 * ... 222 * private final IpcDataCache.QueryHandler<Integer, Birthday> mBirthdayQuery = 223 * new IpcDataCache.QueryHandler<Integer, Birthday>() { 224 * {@literal @}Override 225 * public Birthday apply(Integer) { 226 * return GetService("birthdayd").getUserBirthday(userId); 227 * } 228 * {@literal @}Override 229 * public boolean shouldBypassQuery(Integer userId) { 230 * return userId == NEXT_BIRTHDAY; 231 * } 232 * }; 233 * ... 234 * } 235 * </pre> 236 * 237 * If the {@code shouldBypassQuery()} method returns true then the cache is not used for that 238 * particular query. The {@code shouldBypassQuery()} method is not abstract and the default 239 * implementation returns false. 240 * 241 * For security, there is a allowlist of processes that are allowed to invalidate a cache. The 242 * allowlist includes normal runtime processes but does not include test processes. Test 243 * processes must call {@code IpcDataCache.disableForTestMode()} to disable all cache activity in 244 * that process. 245 * 246 * Caching can be disabled completely by initializing {@code sEnabled} to false and rebuilding. 247 * 248 * To test a binder cache, create one or more tests that exercise the binder method. This should 249 * be done twice: once with production code and once with a special image that sets {@code DEBUG} 250 * and {@code VERIFY} true. In the latter case, verify that no cache inconsistencies are 251 * reported. If a cache inconsistency is reported, however, it might be a false positive. This 252 * happens if the server side data can be read and written non-atomically with respect to cache 253 * invalidation. 254 * 255 * @param <Query> The class used to index cache entries: must be hashable and comparable 256 * @param <Result> The class holding cache entries; use a boxed primitive if possible 257 * @hide 258 */ 259 @TestApi 260 @SystemApi(client=SystemApi.Client.MODULE_LIBRARIES) 261 @android.ravenwood.annotation.RavenwoodKeepWholeClass 262 public class IpcDataCache<Query, Result> extends PropertyInvalidatedCache<Query, Result> { 263 /** 264 * {@inheritDoc} 265 * @hide 266 */ 267 @SystemApi(client=SystemApi.Client.MODULE_LIBRARIES) 268 @TestApi 269 public static abstract class QueryHandler<Q,R> 270 extends PropertyInvalidatedCache.QueryHandler<Q,R> { 271 /** 272 * Compute a result given a query. The semantics are those of Functor. 273 */ apply(@onNull Q query)274 public abstract @Nullable R apply(@NonNull Q query); 275 276 /** 277 * Return true if a query should not use the cache. The default implementation 278 * always uses the cache. 279 */ shouldBypassCache(@onNull Q query)280 public boolean shouldBypassCache(@NonNull Q query) { 281 return false; 282 } 283 }; 284 285 /** 286 * The list of cache namespaces. Each namespace corresponds to an sepolicy domain. A 287 * namespace is owned by a single process, although a single process can have more 288 * than one namespace (system_server, as an example). 289 * @hide 290 */ 291 @StringDef( 292 prefix = { "MODULE_" 293 }, 294 value = { 295 MODULE_TEST, 296 MODULE_SYSTEM, 297 MODULE_BLUETOOTH, 298 MODULE_TELEPHONY 299 } 300 ) 301 @Retention(RetentionPolicy.SOURCE) 302 public @interface IpcDataCacheModule { } 303 304 /** 305 * The module used for unit tests and cts tests. It is expected that no process in 306 * the system has permissions to write properties with this module. 307 * @hide 308 */ 309 @TestApi 310 public static final String MODULE_TEST = PropertyInvalidatedCache.MODULE_TEST; 311 312 /** 313 * The module used for system server/framework caches. This is not visible outside 314 * the system processes. 315 * @hide 316 */ 317 @TestApi 318 public static final String MODULE_SYSTEM = PropertyInvalidatedCache.MODULE_SYSTEM; 319 320 /** 321 * The module used for bluetooth caches. 322 * @hide 323 */ 324 @SystemApi(client=SystemApi.Client.MODULE_LIBRARIES) 325 @TestApi 326 public static final String MODULE_BLUETOOTH = PropertyInvalidatedCache.MODULE_BLUETOOTH; 327 328 /** 329 * Make a new property invalidated cache. The key is computed from the module and api 330 * parameters. 331 * 332 * @param maxEntries Maximum number of entries to cache; LRU discard 333 * @param module The module under which the cache key should be placed. 334 * @param api The api this cache front-ends. The api must be a Java identifier but 335 * need not be an actual api. 336 * @param cacheName Name of this cache in debug and dumpsys 337 * @param computer The code to compute values that are not in the cache. 338 * @hide 339 */ 340 @SystemApi(client=SystemApi.Client.MODULE_LIBRARIES) 341 @TestApi IpcDataCache(int maxEntries, @NonNull @IpcDataCacheModule String module, @NonNull String api, @NonNull String cacheName, @NonNull QueryHandler<Query, Result> computer)342 public IpcDataCache(int maxEntries, @NonNull @IpcDataCacheModule String module, 343 @NonNull String api, @NonNull String cacheName, 344 @NonNull QueryHandler<Query, Result> computer) { 345 super(new Args(module).maxEntries(maxEntries).api(api), cacheName, computer); 346 } 347 348 /** 349 * {@inheritDoc} 350 * @hide 351 */ 352 @SystemApi(client=SystemApi.Client.MODULE_LIBRARIES) 353 @TestApi 354 @Override disableForCurrentProcess()355 public void disableForCurrentProcess() { 356 super.disableForCurrentProcess(); 357 } 358 359 /** 360 * {@inheritDoc} 361 * @hide 362 */ 363 @SystemApi(client=SystemApi.Client.MODULE_LIBRARIES) 364 @TestApi disableForCurrentProcess(@onNull String cacheName)365 public static void disableForCurrentProcess(@NonNull String cacheName) { 366 PropertyInvalidatedCache.disableForCurrentProcess(cacheName); 367 } 368 369 /** 370 * {@inheritDoc} 371 * @hide 372 */ 373 @SystemApi(client=SystemApi.Client.MODULE_LIBRARIES) 374 @TestApi 375 @Override query(@onNull Query query)376 public @Nullable Result query(@NonNull Query query) { 377 return super.query(query); 378 } 379 380 /** 381 * {@inheritDoc} 382 * @hide 383 */ 384 @SystemApi(client=SystemApi.Client.MODULE_LIBRARIES) 385 @TestApi 386 @Override invalidateCache()387 public void invalidateCache() { 388 super.invalidateCache(); 389 } 390 391 /** 392 * Invalidate caches in all processes that are keyed for the module and api. 393 * @hide 394 */ 395 @SystemApi(client=SystemApi.Client.MODULE_LIBRARIES) 396 @TestApi invalidateCache(@onNull @pcDataCacheModule String module, @NonNull String api)397 public static void invalidateCache(@NonNull @IpcDataCacheModule String module, 398 @NonNull String api) { 399 PropertyInvalidatedCache.invalidateCache(module, api); 400 } 401 402 /** 403 * This is a convenience class that encapsulates configuration information for a cache. It 404 * may be supplied to the cache constructors in lieu of the other parameters. The class 405 * captures maximum entry count, the module, the key, and the api. The key is used to 406 * invalidate the cache and may be shared by different caches. The api is a user-visible (in 407 * debug) name for the cache. 408 * 409 * There are three specific use cases supported by this class. 410 * 411 * 1. Instance-per-cache: create a static instance of this class using the same 412 * parameters as would have been given to IpcDataCache (or 413 * PropertyInvalidatedCache). This static instance provides a hook for the 414 * invalidateCache() and disableForLocalProcess() calls, which, generally, must 415 * also be static. 416 * 417 * 2. Short-hand for shared configuration parameters: create an instance of this class 418 * to capture the maximum number of entries and the module to be used by more than 419 * one cache in the class. Refer to this instance when creating new configs. Only 420 * the api and (optionally key) for the new cache must be supplied. 421 * 422 * 3. Tied caches: create a static instance of this class to capture the maximum 423 * number of entries, the module, and the key. Refer to this instance when 424 * creating a new config that differs in only the api. The new config can be 425 * created as part of the cache constructor. All caches that trace back to the 426 * root config share the same key and are invalidated by the invalidateCache() 427 * method of the root config. All caches that trace back to the root config can be 428 * disabled in the local process by the disableAllForCurrentProcess() method of the 429 * root config. 430 * 431 * @hide 432 */ 433 public static class Config { 434 final Args mArgs; 435 final String mName; 436 437 /** 438 * The list of cache names that were created extending this Config. If 439 * disableForCurrentProcess() is invoked on this config then all children will be 440 * disabled. Furthermore, any new children based off of this config will be 441 * disabled. The construction order guarantees that new caches will be disabled 442 * before they are created (the Config must be created before the IpcDataCache is 443 * created). 444 */ 445 private ArraySet<String> mChildren; 446 447 /** 448 * True if registered children are disabled in the current process. If this is 449 * true then all new children are disabled as they are registered. 450 */ 451 private boolean mDisabled = false; 452 453 /** 454 * Fully construct a config. 455 */ Config(@onNull Args args, @NonNull String name)456 private Config(@NonNull Args args, @NonNull String name) { 457 mArgs = args; 458 mName = name; 459 } 460 461 /** 462 * 463 */ Config(int maxEntries, @NonNull @IpcDataCacheModule String module, @NonNull String api, @NonNull String name)464 public Config(int maxEntries, @NonNull @IpcDataCacheModule String module, 465 @NonNull String api, @NonNull String name) { 466 this(new Args(module).api(api).maxEntries(maxEntries), name); 467 } 468 469 /** 470 * A short-hand constructor that makes the name the same as the api. 471 */ Config(int maxEntries, @NonNull @IpcDataCacheModule String module, @NonNull String api)472 public Config(int maxEntries, @NonNull @IpcDataCacheModule String module, 473 @NonNull String api) { 474 this(maxEntries, module, api, api); 475 } 476 477 /** 478 * Copy the module and max entries from the Config and take the api and name from 479 * the parameter list. 480 */ Config(@onNull Config root, @NonNull String api, @NonNull String name)481 public Config(@NonNull Config root, @NonNull String api, @NonNull String name) { 482 this(root.mArgs.api(api), name); 483 } 484 485 /** 486 * Copy the module and max entries from the Config and take the api and name from 487 * the parameter list. 488 */ Config(@onNull Config root, @NonNull String api)489 public Config(@NonNull Config root, @NonNull String api) { 490 this(root.mArgs.api(api), api); 491 } 492 493 /** 494 * Fetch a config that is a child of <this>. The child shares the same api as the 495 * parent and is registered with the parent for the purposes of disabling in the 496 * current process. 497 */ child(@onNull String name)498 public Config child(@NonNull String name) { 499 final Config result = new Config(mArgs, name); 500 registerChild(name); 501 return result; 502 } 503 504 /** 505 * Set the cacheNull behavior. 506 */ cacheNulls(boolean enable)507 public Config cacheNulls(boolean enable) { 508 return new Config(mArgs.cacheNulls(enable), mName); 509 } 510 511 /** 512 * Set the isolateUidss behavior. 513 */ isolateUids(boolean enable)514 public Config isolateUids(boolean enable) { 515 return new Config(mArgs.isolateUids(enable), mName); 516 } 517 518 /** 519 * Register a child cache name. If disableForCurrentProcess() has been called 520 * against this cache, disable th new child. 521 */ registerChild(String name)522 private final void registerChild(String name) { 523 synchronized (this) { 524 if (mChildren == null) { 525 mChildren = new ArraySet<>(); 526 } 527 mChildren.add(name); 528 if (mDisabled) { 529 IpcDataCache.disableForCurrentProcess(name); 530 } 531 } 532 } 533 534 /** 535 * Invalidate all caches that share this Config's module and api. 536 */ invalidateCache()537 public void invalidateCache() { 538 IpcDataCache.invalidateCache(mArgs); 539 } 540 541 /** 542 * Disable all caches that share this Config's name. 543 */ disableForCurrentProcess()544 public void disableForCurrentProcess() { 545 IpcDataCache.disableForCurrentProcess(mName); 546 } 547 548 /** 549 * Disable this cache and all children. Any child that is added in the future 550 * will alwo be disabled. 551 */ disableAllForCurrentProcess()552 public void disableAllForCurrentProcess() { 553 synchronized (this) { 554 mDisabled = true; 555 disableForCurrentProcess(); 556 if (mChildren != null) { 557 for (String c : mChildren) { 558 IpcDataCache.disableForCurrentProcess(c); 559 } 560 } 561 } 562 } 563 } 564 565 /** 566 * Create a new cache using a config. 567 * @hide 568 */ IpcDataCache(@onNull Config config, @NonNull QueryHandler<Query, Result> computer)569 public IpcDataCache(@NonNull Config config, @NonNull QueryHandler<Query, Result> computer) { 570 super(config.mArgs, config.mName, computer); 571 } 572 573 /** 574 * An interface suitable for a lambda expression instead of a QueryHandler applying remote call. 575 * @hide 576 */ 577 public interface RemoteCall<Query, Result> { apply(Query query)578 Result apply(Query query) throws RemoteException; 579 } 580 581 /** 582 * An interface suitable for a lambda expression instead of a QueryHandler bypassing the cache. 583 * @hide 584 */ 585 public interface BypassCall<Query> { apply(Query query)586 Boolean apply(Query query); 587 } 588 589 /** 590 * This is a query handler that is created with a lambda expression that is invoked 591 * every time the handler is called. The handler is specifically meant for services 592 * hosted by system_server; the handler automatically rethrows RemoteException as a 593 * RuntimeException, which is the usual handling for failed binder calls. 594 */ 595 private static class SystemServerCallHandler<Query, Result> 596 extends IpcDataCache.QueryHandler<Query, Result> { 597 private final RemoteCall<Query, Result> mHandler; SystemServerCallHandler(RemoteCall handler)598 public SystemServerCallHandler(RemoteCall handler) { 599 mHandler = handler; 600 } 601 @Override apply(Query query)602 public Result apply(Query query) { 603 try { 604 return mHandler.apply(query); 605 } catch (RemoteException e) { 606 throw e.rethrowFromSystemServer(); 607 } 608 } 609 } 610 611 612 /** 613 * Create a cache using a config and a lambda expression. 614 * @param config The configuration for the cache. 615 * @param remoteCall The lambda expression that will be invoked to fetch the data. 616 * @hide 617 */ IpcDataCache(@onNull Config config, @NonNull RemoteCall<Query, Result> remoteCall)618 public IpcDataCache(@NonNull Config config, @NonNull RemoteCall<Query, Result> remoteCall) { 619 this(config, android.multiuser.Flags.cachingDevelopmentImprovements() ? 620 new QueryHandler<Query, Result>() { 621 @Override 622 public Result apply(Query query) { 623 try { 624 return remoteCall.apply(query); 625 } catch (RemoteException e) { 626 throw e.rethrowFromSystemServer(); 627 } 628 } 629 } : new SystemServerCallHandler<>(remoteCall)); 630 } 631 632 633 /** 634 * Create a cache using a config and a lambda expression. 635 * @param config The configuration for the cache. 636 * @param remoteCall The lambda expression that will be invoked to fetch the data. 637 * @param bypass The lambda expression that will be invoked to determine if the cache should be 638 * bypassed. 639 * @hide 640 */ 641 @FlaggedApi(android.multiuser.Flags.FLAG_CACHING_DEVELOPMENT_IMPROVEMENTS) IpcDataCache(@onNull Config config, @NonNull RemoteCall<Query, Result> remoteCall, @NonNull BypassCall<Query> bypass)642 public IpcDataCache(@NonNull Config config, 643 @NonNull RemoteCall<Query, Result> remoteCall, 644 @NonNull BypassCall<Query> bypass) { 645 this(config, new QueryHandler<Query, Result>() { 646 @Override 647 public Result apply(Query query) { 648 try { 649 return remoteCall.apply(query); 650 } catch (RemoteException e) { 651 throw e.rethrowFromSystemServer(); 652 } 653 } 654 655 @Override 656 public boolean shouldBypassCache(Query query) { 657 return bypass.apply(query); 658 } 659 }); 660 } 661 662 /** 663 * The following APIs are exposed to support testing. They only forward the superclass but 664 * that means the superclass does not have to expose the APIs itself. 665 */ 666 667 /** 668 * Stop disabling local caches with the same name as <this>. Any caches that are currently 669 * disabled remain disabled (the "disabled" setting is sticky). However, new caches with this 670 * name will not be disabled. It is not an error if the cache name is not found in the list 671 * of disabled caches. 672 * @hide 673 */ 674 @TestApi 675 @Override forgetDisableLocal()676 public final void forgetDisableLocal() { 677 super.forgetDisableLocal(); 678 } 679 680 /** 681 * Return whether a cache instance is disabled. 682 * @hide 683 */ 684 @TestApi 685 @Override isDisabled()686 public final boolean isDisabled() { 687 return super.isDisabled(); 688 } 689 690 /** 691 * This is an obsolete synonym for {@link #isDisabled()}. 692 * @hide 693 */ 694 @TestApi getDisabledState()695 public boolean getDisabledState() { 696 return isDisabled(); 697 } 698 699 /** 700 * Disable the use of this cache in this process. This method is used internally and during 701 * testing. To disable a cache in normal code, use disableProcessLocal(). 702 * @hide 703 */ 704 @TestApi 705 @Override disableInstance()706 public final void disableInstance() { 707 super.disableInstance(); 708 } 709 710 /** 711 * Disable all caches that use the property as the current cache. 712 * @hide 713 */ 714 @TestApi 715 @Override disableSystemWide()716 public final void disableSystemWide() { 717 super.disableSystemWide(); 718 } 719 720 /** 721 * Enable or disable test mode. The protocol requires that the mode toggle: for instance, it is 722 * illegal to clear the test mode if the test mode is already off. Enabling test mode puts 723 * all caches in the process into test mode; all nonces are initialized to UNSET and 724 * subsequent reads and writes are to process memory. This has the effect of disabling all 725 * caches that are not local to the process. Disabling test mode restores caches to normal 726 * operation. 727 * @param mode The desired test mode. 728 * @throws IllegalStateException if the supplied mode is already set. 729 * @throws IllegalStateException if the process is not running an instrumentation test. 730 * @hide 731 */ 732 @TestApi setTestMode(boolean mode)733 public static void setTestMode(boolean mode) { 734 PropertyInvalidatedCache.setTestMode(mode); 735 } 736 737 /** 738 * Enable or disable test mode. The protocol requires that the mode toggle: for instance, it is 739 * illegal to clear the test mode if the test mode is already off. Enabling test mode puts 740 * all caches in the process into test mode; all nonces are initialized to UNSET and 741 * subsequent reads and writes are to process memory. This has the effect of disabling all 742 * caches that are not local to the process. Disabling test mode restores caches to normal 743 * operation. 744 * @param mode The desired test mode. 745 * @throws IllegalStateException if the supplied mode is already set. 746 * @throws IllegalStateException if the process is not running an instrumentation test. 747 * @hide 748 */ 749 @FlaggedApi(android.os.Flags.FLAG_IPC_DATA_CACHE_TEST_APIS) 750 @SystemApi(client=SystemApi.Client.MODULE_LIBRARIES) setCacheTestMode(boolean mode)751 public static void setCacheTestMode(boolean mode) { 752 // Trunk-stable flagging requires that this API have a name different from the existing 753 // setTestMode() API. However, the functionality is identical. 754 setTestMode(mode); 755 } 756 } 757