diff options
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/app/ActivityThread.java | 102 | ||||
| -rw-r--r-- | core/java/android/security/keymaster/KeymasterDefs.java | 7 |
2 files changed, 73 insertions, 36 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index bdd9e41..beb244b 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -257,18 +257,21 @@ public final class ActivityThread { } } + static final class AcquiringProviderRecord { + IActivityManager.ContentProviderHolder holder; + boolean acquiring = true; + int requests = 1; + } + // The lock of mProviderMap protects the following variables. - final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap - = new ArrayMap<ProviderKey, ProviderClientRecord>(); - final ArrayMap<IBinder, ProviderRefCount> mProviderRefCountMap - = new ArrayMap<IBinder, ProviderRefCount>(); - final ArrayMap<IBinder, ProviderClientRecord> mLocalProviders - = new ArrayMap<IBinder, ProviderClientRecord>(); - final ArrayMap<ComponentName, ProviderClientRecord> mLocalProvidersByName - = new ArrayMap<ComponentName, ProviderClientRecord>(); + final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap = new ArrayMap<>(); + final ArrayMap<ProviderKey, AcquiringProviderRecord> mAcquiringProviderMap = new ArrayMap<>(); + final ArrayMap<IBinder, ProviderRefCount> mProviderRefCountMap = new ArrayMap<>(); + final ArrayMap<IBinder, ProviderClientRecord> mLocalProviders = new ArrayMap<>(); + final ArrayMap<ComponentName, ProviderClientRecord> mLocalProvidersByName = new ArrayMap<>(); final ArrayMap<Activity, ArrayList<OnActivityPausedListener>> mOnPauseListeners - = new ArrayMap<Activity, ArrayList<OnActivityPausedListener>>(); + = new ArrayMap<>(); final GcIdler mGcIdler = new GcIdler(); boolean mGcIdlerScheduled = false; @@ -345,7 +348,7 @@ public final class ActivityThread { } } - final class ProviderClientRecord { + static final class ProviderClientRecord { final String[] mNames; final IContentProvider mProvider; final ContentProvider mLocalProvider; @@ -4648,22 +4651,57 @@ public final class ActivityThread { public final IContentProvider acquireProvider( Context c, String auth, int userId, boolean stable) { - final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable); + final ProviderKey key = new ProviderKey(auth, userId); + final IContentProvider provider = acquireExistingProvider(c, key, stable); if (provider != null) { return provider; } + AcquiringProviderRecord r; + boolean first = false; + synchronized (mAcquiringProviderMap) { + r = mAcquiringProviderMap.get(key); + if (r == null) { + r = new AcquiringProviderRecord(); + mAcquiringProviderMap.put(key, r); + first = true; + } else { + r.requests++; + } + } - // There is a possible race here. Another thread may try to acquire - // the same provider at the same time. When this happens, we want to ensure - // that the first one wins. - // Note that we cannot hold the lock while acquiring and installing the - // provider since it might take a long time to run and it could also potentially - // be re-entrant in the case where the provider is in the same process. IActivityManager.ContentProviderHolder holder = null; - try { - holder = ActivityManagerNative.getDefault().getContentProvider( - getApplicationThread(), auth, userId, stable); - } catch (RemoteException ex) { + if (first) { + // Multiple threads may try to acquire the same provider at the same time. + // When this happens, we only let the first one really gets provider. + // Other threads just wait for its result. + // Note that we cannot hold the lock while acquiring and installing the + // provider since it might take a long time to run and it could also potentially + // be re-entrant in the case where the provider is in the same process. + try { + holder = ActivityManagerNative.getDefault().getContentProvider( + getApplicationThread(), auth, userId, stable); + } catch (RemoteException ex) { + } + synchronized (r) { + r.holder = holder; + r.acquiring = false; + r.notifyAll(); + } + } else { + synchronized (r) { + while (r.acquiring) { + try { + r.wait(); + } catch (InterruptedException e) { + } + } + holder = r.holder; + } + } + synchronized (mAcquiringProviderMap) { + if (--r.requests == 0) { + mAcquiringProviderMap.remove(key); + } } if (holder == null) { Slog.e(TAG, "Failed to find provider info for " + auth); @@ -4747,8 +4785,12 @@ public final class ActivityThread { public final IContentProvider acquireExistingProvider( Context c, String auth, int userId, boolean stable) { + return acquireExistingProvider(c, new ProviderKey(auth, userId), stable); + } + + final IContentProvider acquireExistingProvider( + Context c, ProviderKey key, boolean stable) { synchronized (mProviderMap) { - final ProviderKey key = new ProviderKey(auth, userId); final ProviderClientRecord pr = mProviderMap.get(key); if (pr == null) { return null; @@ -4759,7 +4801,7 @@ public final class ActivityThread { if (!jBinder.isBinderAlive()) { // The hosting process of the provider has died; we can't // use this one. - Log.i(TAG, "Acquiring provider " + auth + " for user " + userId + Log.i(TAG, "Acquiring provider " + key.authority + " for user " + key.userId + ": existing object's process dead"); handleUnstableProviderDiedLocked(jBinder, true); return null; @@ -5081,18 +5123,12 @@ public final class ActivityThread { if (DEBUG_PROVIDER) { Slog.v(TAG, "installProvider: lost the race, updating ref count"); } - // We need to transfer our new reference to the existing - // ref count, releasing the old one... but only if - // release is needed (that is, it is not running in the - // system process). + // The provider has already been installed, so we need + // to increase reference count to the existing one, but + // only if release is needed (that is, it is not running + // in the system process or local to the process). if (!noReleaseNeeded) { incProviderRefLocked(prc, stable); - try { - ActivityManagerNative.getDefault().removeContentProvider( - holder.connection, stable); - } catch (RemoteException e) { - //do nothing content provider object is dead any way - } } } else { ProviderClientRecord client = installProviderAuthoritiesLocked( diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java index c2ebbc6..e94a312 100644 --- a/core/java/android/security/keymaster/KeymasterDefs.java +++ b/core/java/android/security/keymaster/KeymasterDefs.java @@ -181,7 +181,7 @@ public final class KeymasterDefs { public static final int KM_ERROR_UNSUPPORTED_KEY_SIZE = -6; public static final int KM_ERROR_UNSUPPORTED_BLOCK_MODE = -7; public static final int KM_ERROR_INCOMPATIBLE_BLOCK_MODE = -8; - public static final int KM_ERROR_UNSUPPORTED_TAG_LENGTH = -9; + public static final int KM_ERROR_UNSUPPORTED_MAC_LENGTH = -9; public static final int KM_ERROR_UNSUPPORTED_PADDING_MODE = -10; public static final int KM_ERROR_INCOMPATIBLE_PADDING_MODE = -11; public static final int KM_ERROR_UNSUPPORTED_DIGEST = -12; @@ -237,8 +237,8 @@ public final class KeymasterDefs { sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_KEY_SIZE, "Unsupported key size"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_BLOCK_MODE, "Unsupported block mode"); sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_BLOCK_MODE, "Incompatible block mode"); - sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_TAG_LENGTH, - "Unsupported authentication tag length"); + sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_MAC_LENGTH, + "Unsupported MAC or authentication tag length"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_PADDING_MODE, "Unsupported padding mode"); sErrorCodeToString.put(KM_ERROR_INCOMPATIBLE_PADDING_MODE, "Incompatible padding mode"); sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_DIGEST, "Unsupported digest"); @@ -261,6 +261,7 @@ public final class KeymasterDefs { sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_TAG, "Unsupported tag"); sErrorCodeToString.put(KM_ERROR_INVALID_TAG, "Invalid tag"); sErrorCodeToString.put(KM_ERROR_MEMORY_ALLOCATION_FAILED, "Memory allocation failed"); + sErrorCodeToString.put(KM_ERROR_UNSUPPORTED_EC_FIELD, "Unsupported EC field"); sErrorCodeToString.put(KM_ERROR_UNIMPLEMENTED, "Not implemented"); sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error"); } |
