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

Commit cfd980ac authored by Pinyao Ting's avatar Pinyao Ting
Browse files

route prediction service session based on device config

Bug: 148173565
Change-Id: I83c100d315609095b427b096d8a1215949849c42
Test: manual override the flag to force routing through
people service, and verify it works.
parent 29aa0e81
Loading
Loading
Loading
Loading
+76 −50
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.appprediction;

import static android.provider.DeviceConfig.NAMESPACE_SYSTEMUI;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppGlobals;
@@ -30,12 +32,17 @@ import android.content.pm.ParceledListSlice;
import android.content.pm.ServiceInfo;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.provider.DeviceConfig;
import android.service.appprediction.AppPredictionService;
import android.service.appprediction.IPredictionService;
import android.util.ArrayMap;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.infra.AbstractRemoteService;
import com.android.server.LocalServices;
import com.android.server.infra.AbstractPerUserSystemService;
import com.android.server.people.PeopleServiceInternal;

import java.util.function.Consumer;

@@ -47,6 +54,8 @@ public class AppPredictionPerUserService extends
             implements RemoteAppPredictionService.RemoteAppPredictionServiceCallbacks {

    private static final String TAG = AppPredictionPerUserService.class.getSimpleName();
    private static final String PREDICT_USING_PEOPLE_SERVICE_PREFIX =
            "predict_using_people_service_";

    @Nullable
    @GuardedBy("mLock")
@@ -104,14 +113,16 @@ public class AppPredictionPerUserService extends
    @GuardedBy("mLock")
    public void onCreatePredictionSessionLocked(@NonNull AppPredictionContext context,
            @NonNull AppPredictionSessionId sessionId) {
        final RemoteAppPredictionService service = getRemoteServiceLocked();
        if (service != null) {
            service.onCreatePredictionSession(context, sessionId);

        if (!mSessionInfos.containsKey(sessionId)) {
            mSessionInfos.put(sessionId, new AppPredictionSessionInfo(sessionId, context,
                    DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI,
                            PREDICT_USING_PEOPLE_SERVICE_PREFIX + context.getUiSurface(), false),
                    this::removeAppPredictionSessionInfo));
        }
        final boolean serviceExists = resolveService(sessionId, s ->
                s.onCreatePredictionSession(context, sessionId));
        if (!serviceExists) {
            mSessionInfos.remove(sessionId);
        }
    }

@@ -121,10 +132,7 @@ public class AppPredictionPerUserService extends
    @GuardedBy("mLock")
    public void notifyAppTargetEventLocked(@NonNull AppPredictionSessionId sessionId,
            @NonNull AppTargetEvent event) {
        final RemoteAppPredictionService service = getRemoteServiceLocked();
        if (service != null) {
            service.notifyAppTargetEvent(sessionId, event);
        }
        resolveService(sessionId, s -> s.notifyAppTargetEvent(sessionId, event));
    }

    /**
@@ -133,10 +141,8 @@ public class AppPredictionPerUserService extends
    @GuardedBy("mLock")
    public void notifyLaunchLocationShownLocked(@NonNull AppPredictionSessionId sessionId,
            @NonNull String launchLocation, @NonNull ParceledListSlice targetIds) {
        final RemoteAppPredictionService service = getRemoteServiceLocked();
        if (service != null) {
            service.notifyLaunchLocationShown(sessionId, launchLocation, targetIds);
        }
        resolveService(sessionId, s ->
                s.notifyLaunchLocationShown(sessionId, launchLocation, targetIds));
    }

    /**
@@ -145,10 +151,7 @@ public class AppPredictionPerUserService extends
    @GuardedBy("mLock")
    public void sortAppTargetsLocked(@NonNull AppPredictionSessionId sessionId,
            @NonNull ParceledListSlice targets, @NonNull IPredictionCallback callback) {
        final RemoteAppPredictionService service = getRemoteServiceLocked();
        if (service != null) {
            service.sortAppTargets(sessionId, targets, callback);
        }
        resolveService(sessionId, s -> s.sortAppTargets(sessionId, targets, callback));
    }

    /**
@@ -157,16 +160,13 @@ public class AppPredictionPerUserService extends
    @GuardedBy("mLock")
    public void registerPredictionUpdatesLocked(@NonNull AppPredictionSessionId sessionId,
            @NonNull IPredictionCallback callback) {
        final RemoteAppPredictionService service = getRemoteServiceLocked();
        if (service != null) {
            service.registerPredictionUpdates(sessionId, callback);

            AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
            if (sessionInfo != null) {
        final boolean serviceExists = resolveService(sessionId, s ->
                s.registerPredictionUpdates(sessionId, callback));
        final AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
        if (serviceExists && sessionInfo != null) {
            sessionInfo.addCallbackLocked(callback);
        }
    }
    }

    /**
     * Unregisters a callback for continuous updates of predicted apps or shortcuts.
@@ -174,26 +174,20 @@ public class AppPredictionPerUserService extends
    @GuardedBy("mLock")
    public void unregisterPredictionUpdatesLocked(@NonNull AppPredictionSessionId sessionId,
            @NonNull IPredictionCallback callback) {
        final RemoteAppPredictionService service = getRemoteServiceLocked();
        if (service != null) {
            service.unregisterPredictionUpdates(sessionId, callback);

            AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
            if (sessionInfo != null) {
        final boolean serviceExists = resolveService(sessionId, s ->
                s.unregisterPredictionUpdates(sessionId, callback));
        final AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
        if (serviceExists && sessionInfo != null) {
            sessionInfo.removeCallbackLocked(callback);
        }
    }
    }

    /**
     * Requests a new set of predicted apps or shortcuts.
     */
    @GuardedBy("mLock")
    public void requestPredictionUpdateLocked(@NonNull AppPredictionSessionId sessionId) {
        final RemoteAppPredictionService service = getRemoteServiceLocked();
        if (service != null) {
            service.requestPredictionUpdate(sessionId);
        }
        resolveService(sessionId, s -> s.requestPredictionUpdate(sessionId));
    }

    /**
@@ -201,16 +195,13 @@ public class AppPredictionPerUserService extends
     */
    @GuardedBy("mLock")
    public void onDestroyPredictionSessionLocked(@NonNull AppPredictionSessionId sessionId) {
        final RemoteAppPredictionService service = getRemoteServiceLocked();
        if (service != null) {
            service.onDestroyPredictionSession(sessionId);

            AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
            if (sessionInfo != null) {
        final boolean serviceExists = resolveService(sessionId, s ->
                s.onDestroyPredictionSession(sessionId));
        final AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
        if (serviceExists && sessionInfo != null) {
            sessionInfo.destroy();
        }
    }
    }

    @Override
    public void onFailureOrTimeout(boolean timedOut) {
@@ -310,6 +301,33 @@ public class AppPredictionPerUserService extends
        }
    }

    @GuardedBy("mLock")
    @Nullable
    protected boolean resolveService(@NonNull final AppPredictionSessionId sessionId,
            @NonNull final AbstractRemoteService.AsyncRequest<IPredictionService> cb) {
        final AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
        if (sessionInfo == null) return false;
        if (sessionInfo.mUsesPeopleService) {
            final IPredictionService service =
                    LocalServices.getService(PeopleServiceInternal.class);
            if (service != null) {
                try {
                    cb.run(service);
                } catch (RemoteException e) {
                    // Shouldn't happen.
                    Slog.w(TAG, "Failed to invoke service:" + service, e);
                }
            }
            return service != null;
        } else {
            final RemoteAppPredictionService service = getRemoteServiceLocked();
            if (service != null) {
                service.scheduleOnResolvedService(cb);
            }
            return service != null;
        }
    }

    @GuardedBy("mLock")
    @Nullable
    private RemoteAppPredictionService getRemoteServiceLocked() {
@@ -334,8 +352,12 @@ public class AppPredictionPerUserService extends
    private static final class AppPredictionSessionInfo {
        private static final boolean DEBUG = false;  // Do not submit with true

        @NonNull
        private final AppPredictionSessionId mSessionId;
        @NonNull
        private final AppPredictionContext mPredictionContext;
        private final boolean mUsesPeopleService;
        @NonNull
        private final Consumer<AppPredictionSessionId> mRemoveSessionInfoAction;

        private final RemoteCallbackList<IPredictionCallback> mCallbacks =
@@ -352,13 +374,17 @@ public class AppPredictionPerUserService extends
                    }
                };

        AppPredictionSessionInfo(AppPredictionSessionId id, AppPredictionContext predictionContext,
                Consumer<AppPredictionSessionId> removeSessionInfoAction) {
        AppPredictionSessionInfo(
                @NonNull final AppPredictionSessionId id,
                @NonNull final AppPredictionContext predictionContext,
                final boolean usesPeopleService,
                @NonNull final Consumer<AppPredictionSessionId> removeSessionInfoAction) {
            if (DEBUG) {
                Slog.d(TAG, "Creating AppPredictionSessionInfo for session Id=" + id);
            }
            mSessionId = id;
            mPredictionContext = predictionContext;
            mUsesPeopleService = usesPeopleService;
            mRemoveSessionInfoAction = removeSessionInfoAction;
        }

+6 −68
Original line number Diff line number Diff line
@@ -16,13 +16,8 @@
package com.android.server.appprediction;

import android.annotation.NonNull;
import android.app.prediction.AppPredictionContext;
import android.app.prediction.AppPredictionSessionId;
import android.app.prediction.AppTargetEvent;
import android.app.prediction.IPredictionCallback;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.os.IBinder;
import android.service.appprediction.IPredictionService;
import android.text.format.DateUtils;
@@ -71,74 +66,17 @@ public class RemoteAppPredictionService extends
    }

    /**
     * Notifies the service of a new prediction session.
     */
    public void onCreatePredictionSession(@NonNull AppPredictionContext context,
            @NonNull AppPredictionSessionId sessionId) {
        scheduleAsyncRequest((s) -> s.onCreatePredictionSession(context, sessionId));
    }

    /**
     * Records an app target event to the service.
     */
    public void notifyAppTargetEvent(@NonNull AppPredictionSessionId sessionId,
            @NonNull AppTargetEvent event) {
        scheduleAsyncRequest((s) -> s.notifyAppTargetEvent(sessionId, event));
    }

    /**
     * Records when a launch location is shown.
     */
    public void notifyLaunchLocationShown(@NonNull AppPredictionSessionId sessionId,
            @NonNull String launchLocation, @NonNull ParceledListSlice targetIds) {
        scheduleAsyncRequest((s)
                -> s.notifyLaunchLocationShown(sessionId, launchLocation, targetIds));
    }

    /**
     * Requests the service to sort a list of apps or shortcuts.
     */
    public void sortAppTargets(@NonNull AppPredictionSessionId sessionId,
            @NonNull ParceledListSlice targets, @NonNull IPredictionCallback callback) {
        scheduleAsyncRequest((s) -> s.sortAppTargets(sessionId, targets, callback));
    }


    /**
     * Registers a callback for continuous updates of predicted apps or shortcuts.
     */
    public void registerPredictionUpdates(@NonNull AppPredictionSessionId sessionId,
            @NonNull IPredictionCallback callback) {
        scheduleAsyncRequest((s) -> s.registerPredictionUpdates(sessionId, callback));
    }

    /**
     * Unregisters a callback for continuous updates of predicted apps or shortcuts.
     */
    public void unregisterPredictionUpdates(@NonNull AppPredictionSessionId sessionId,
            @NonNull IPredictionCallback callback) {
        scheduleAsyncRequest((s) -> s.unregisterPredictionUpdates(sessionId, callback));
    }

    /**
     * Requests a new set of predicted apps or shortcuts.
     */
    public void requestPredictionUpdate(@NonNull AppPredictionSessionId sessionId) {
        scheduleAsyncRequest((s) -> s.requestPredictionUpdate(sessionId));
    }

    /**
     * Notifies the service of the end of an existing prediction session.
     * Schedules a request to bind to the remote service.
     */
    public void onDestroyPredictionSession(@NonNull AppPredictionSessionId sessionId) {
        scheduleAsyncRequest((s) -> s.onDestroyPredictionSession(sessionId));
    public void reconnect() {
        super.scheduleBind();
    }

    /**
     * Schedules a request to bind to the remote service.
     * Schedule async request on remote service.
     */
    public void reconnect() {
        super.scheduleBind();
    public void scheduleOnResolvedService(@NonNull AsyncRequest<IPredictionService> request) {
        scheduleAsyncRequest(request);
    }

    /**