diff options
| author | 2024-11-05 13:23:57 -0800 | |
|---|---|---|
| committer | 2024-11-05 16:00:07 -0800 | |
| commit | 554e5a011cc482a4cd503146e213c7e40bfe9402 (patch) | |
| tree | b5b1b8718a9365e68b57946301405ce7fb2b0771 | |
| parent | 9b9a570882d24f361538f2f637dbc6ea0047e455 (diff) | |
Add synchronization to PIC shared memory
Add more robust synchronization to the PIC shared memory nonce
storage. The updated code follows the standard "double-checked"
pattern.
Flag: android.app.pic_uses_shared_memory
Bug: 360897450
Test: atest
* FrameworksCoreTests:PropertyInvalidatedCacheTests
* FrameworksCoreTests:IpcDataCacheTest
* CtsOsTestCases:IpcDataCacheTest
Change-Id: I22ee87f9ea86f1bf17dd5e550dfae237236e3f98
| -rw-r--r-- | core/java/android/app/PropertyInvalidatedCache.java | 77 |
1 files changed, 45 insertions, 32 deletions
diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java index 038dcdb7efc9..f432a22b14ac 100644 --- a/core/java/android/app/PropertyInvalidatedCache.java +++ b/core/java/android/app/PropertyInvalidatedCache.java @@ -717,12 +717,10 @@ public class PropertyInvalidatedCache<Query, Result> { // The shared memory. private volatile NonceStore mStore; - // The index of the nonce in shared memory. + // The index of the nonce in shared memory. This changes from INVALID only when the local + // object is completely initialized. private volatile int mHandle = NonceStore.INVALID_NONCE_INDEX; - // True if the string has been stored, ever. - private volatile boolean mRecorded = false; - // A short name that is saved in shared memory. This is the portion of the property name // that follows the prefix. private final String mShortName; @@ -736,48 +734,63 @@ public class PropertyInvalidatedCache<Query, Result> { } } + // Initialize the mStore and mHandle variables. This function does nothing if the + // variables are already initialized. Synchronization ensures that initialization happens + // no more than once. The function returns the new value of mHandle. + // + // If the "update" boolean is true, then the property is registered with the nonce store + // before the associated handle is fetched. + private int initialize(boolean update) { + synchronized (mLock) { + int handle = mHandle; + if (handle == NonceStore.INVALID_NONCE_INDEX) { + if (mStore == null) { + mStore = NonceStore.getInstance(); + if (mStore == null) { + return NonceStore.INVALID_NONCE_INDEX; + } + } + if (update) { + mStore.storeName(mShortName); + } + handle = mStore.getHandleForName(mShortName); + if (handle == NonceStore.INVALID_NONCE_INDEX) { + return NonceStore.INVALID_NONCE_INDEX; + } + // The handle must be valid. + mHandle = handle; + } + return handle; + } + } + // Fetch the nonce from shared memory. If the shared memory is not available, return // UNSET. If the shared memory is available but the nonce name is not known (it may not // have been invalidated by the server yet), return UNSET. @Override long getNonceInternal() { - if (mHandle == NonceStore.INVALID_NONCE_INDEX) { - if (mStore == null) { - mStore = NonceStore.getInstance(); - if (mStore == null) { - return NONCE_UNSET; - } - } - mHandle = mStore.getHandleForName(mShortName); - if (mHandle == NonceStore.INVALID_NONCE_INDEX) { + int handle = mHandle; + if (handle == NonceStore.INVALID_NONCE_INDEX) { + handle = initialize(false); + if (handle == NonceStore.INVALID_NONCE_INDEX) { return NONCE_UNSET; } } - return mStore.getNonce(mHandle); + return mStore.getNonce(handle); } - // Set the nonce in shared mmory. If the shared memory is not available, throw an - // exception. Otherwise, if the nonce name has never been recorded, record it now and - // fetch the handle for the name. If the handle cannot be created, throw an exception. + // Set the nonce in shared memory. If the shared memory is not available or if the nonce + // cannot be registered in shared memory, throw an exception. @Override void setNonceInternal(long value) { - if (mHandle == NonceStore.INVALID_NONCE_INDEX || !mRecorded) { - if (mStore == null) { - mStore = NonceStore.getInstance(); - if (mStore == null) { - throw new IllegalStateException("setNonce: shared memory not ready"); - } - } - // Always store the name before fetching the handle. storeName() is idempotent - // but does take a little time, so this code calls it just once. - mStore.storeName(mShortName); - mRecorded = true; - mHandle = mStore.getHandleForName(mShortName); - if (mHandle == NonceStore.INVALID_NONCE_INDEX) { - throw new IllegalStateException("setNonce: shared memory store failed"); + int handle = mHandle; + if (handle == NonceStore.INVALID_NONCE_INDEX) { + handle = initialize(true); + if (handle == NonceStore.INVALID_NONCE_INDEX) { + throw new IllegalStateException("unable to assign nonce handle: " + mName); } } - mStore.setNonce(mHandle, value); + mStore.setNonce(handle, value); } } |