Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d669bfe8 authored by Andrey Epin's avatar Andrey Epin
Browse files

Make AppPredictor thread-safe

Make callback registration, unregistration and session deletion mutually
exclusive.

Test: manual testing

Change-Id: I2ebc8ac37f2b34e0c6a10b563e9c4f36697101b1
parent 848de045
Loading
Loading
Loading
Loading
+34 −10
Original line number Diff line number Diff line
@@ -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,7 +272,16 @@ public final class AppPredictor {
        if (!mIsClosed.getAndSet(true)) {
            mCloseGuard.close();

            // Do destroy;
            synchronized (mRegisteredCallbacks) {
                destroySessionLocked();
            }
        } else {
            throw new IllegalStateException("This client has already been destroyed.");
        }
    }

    @GuardedBy("mRegisteredCallbacks")
    private void destroySessionLocked() {
        try {
            mPredictionManager.onDestroyPredictionSession(mSessionId);
        } catch (RemoteException e) {
@@ -262,9 +289,6 @@ public final class AppPredictor {
            e.rethrowAsRuntimeException();
        }
        mRegisteredCallbacks.clear();
        } else {
            throw new IllegalStateException("This client has already been destroyed.");
        }
    }

    @Override