Merge "Make AppPredictor thread-safe" into tm-qpr-dev am: 2a4339d073

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20269815

Change-Id: I7e0440785e6ea2858fc3d5b276c7aec58e2246a6
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Andrey Epin
2022-11-17 16:55:40 +00:00
committed by Automerger Merge Worker

View File

@@ -30,6 +30,8 @@ import android.os.ServiceManager;
import android.util.ArrayMap;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import dalvik.system.CloseGuard;
import java.util.List;
@@ -74,12 +76,12 @@ public final class AppPredictor {
private static final String TAG = AppPredictor.class.getSimpleName();
private final IPredictionManager mPredictionManager;
private final CloseGuard mCloseGuard = CloseGuard.get();
private final AtomicBoolean mIsClosed = new AtomicBoolean(false);
private final AppPredictionSessionId mSessionId;
@GuardedBy("itself")
private final ArrayMap<Callback, CallbackWrapper> mRegisteredCallbacks = new ArrayMap<>();
private final IBinder mToken = new Binder();
@@ -97,7 +99,7 @@ public final class AppPredictor {
IBinder b = ServiceManager.getService(Context.APP_PREDICTION_SERVICE);
mPredictionManager = IPredictionManager.Stub.asInterface(b);
mSessionId = new AppPredictionSessionId(
context.getPackageName() + ":" + UUID.randomUUID().toString(), context.getUserId());
context.getPackageName() + ":" + UUID.randomUUID(), context.getUserId());
try {
mPredictionManager.createPredictionSession(predictionContext, mSessionId, mToken);
} catch (RemoteException e) {
@@ -158,6 +160,15 @@ public final class AppPredictor {
*/
public void registerPredictionUpdates(@NonNull @CallbackExecutor Executor callbackExecutor,
@NonNull AppPredictor.Callback callback) {
synchronized (mRegisteredCallbacks) {
registerPredictionUpdatesLocked(callbackExecutor, callback);
}
}
@GuardedBy("mRegisteredCallbacks")
private void registerPredictionUpdatesLocked(
@NonNull @CallbackExecutor Executor callbackExecutor,
@NonNull AppPredictor.Callback callback) {
if (mIsClosed.get()) {
throw new IllegalStateException("This client has already been destroyed.");
}
@@ -186,6 +197,13 @@ public final class AppPredictor {
* @param callback The callback to be unregistered.
*/
public void unregisterPredictionUpdates(@NonNull AppPredictor.Callback callback) {
synchronized (mRegisteredCallbacks) {
unregisterPredictionUpdatesLocked(callback);
}
}
@GuardedBy("mRegisteredCallbacks")
private void unregisterPredictionUpdatesLocked(@NonNull AppPredictor.Callback callback) {
if (mIsClosed.get()) {
throw new IllegalStateException("This client has already been destroyed.");
}
@@ -238,7 +256,7 @@ public final class AppPredictor {
}
try {
mPredictionManager.sortAppTargets(mSessionId, new ParceledListSlice(targets),
mPredictionManager.sortAppTargets(mSessionId, new ParceledListSlice<>(targets),
new CallbackWrapper(callbackExecutor, callback));
} catch (RemoteException e) {
Log.e(TAG, "Failed to sort targets", e);
@@ -254,19 +272,25 @@ public final class AppPredictor {
if (!mIsClosed.getAndSet(true)) {
mCloseGuard.close();
// Do destroy;
try {
mPredictionManager.onDestroyPredictionSession(mSessionId);
} catch (RemoteException e) {
Log.e(TAG, "Failed to notify app target event", e);
e.rethrowAsRuntimeException();
synchronized (mRegisteredCallbacks) {
destroySessionLocked();
}
mRegisteredCallbacks.clear();
} else {
throw new IllegalStateException("This client has already been destroyed.");
}
}
@GuardedBy("mRegisteredCallbacks")
private void destroySessionLocked() {
try {
mPredictionManager.onDestroyPredictionSession(mSessionId);
} catch (RemoteException e) {
Log.e(TAG, "Failed to notify app target event", e);
e.rethrowAsRuntimeException();
}
mRegisteredCallbacks.clear();
}
@Override
protected void finalize() throws Throwable {
try {