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

Commit 8e2e341b authored by Felipe Leme's avatar Felipe Leme
Browse files

Fixed Content Capture workflow when service is disabled.

Bug: 111276913
Test: manual verification

Change-Id: If53eeae88ff6ca6140c90d51ff91436950f05ead
parent c2d74304
Loading
Loading
Loading
Loading
+18 −11
Original line number Diff line number Diff line
@@ -86,6 +86,13 @@ public final class IntelligenceManager {
     */
    public static final int STATE_ACTIVE = 2;

    /**
     * Session is disabled.
     *
     * @hide
     */
    public static final int STATE_DISABLED = 3;

    private static final String BG_THREAD_NAME = "intel_svc_streamer_thread";

    /**
@@ -166,13 +173,7 @@ public final class IntelligenceManager {
                            public void send(int resultCode, Bundle resultData)
                                    throws RemoteException {
                                synchronized (mLock) {
                                    if (resultCode > 0) {
                                        mState = STATE_ACTIVE;
                                    } else {
                                        // TODO(b/111276913): handle other cases like disabled by
                                        // service
                                        resetStateLocked();
                                    }
                                    mState = resultCode;
                                    if (VERBOSE) {
                                        Log.v(TAG, "onActivityStarted() result: code=" + resultCode
                                                + ", id=" + mId
@@ -203,9 +204,13 @@ public final class IntelligenceManager {
                    // Typically happens on system apps that are started before the system service
                    // is ready (like com.android.settings/.FallbackHome)
                    //TODO(b/111276913): try to ignore session while system is not ready / boot
                    // not complete instead.
                    Log.w(TAG, "Closing session for " + getActivityDebugNameLocked()
                            + " after " + numberEvents + " delayed events");
                    // not complete instead. Similarly, the manager service should return right away
                    // when the user does not have a service set
                    if (VERBOSE) {
                        Log.v(TAG, "Closing session for " + getActivityDebugNameLocked()
                                + " after " + numberEvents + " delayed events and state "
                                + getStateAsString(mState));
                    }
                    // TODO(b/111276913): blacklist activity / use special flag to indicate that
                    // when it's launched again
                    resetStateLocked();
@@ -380,7 +385,7 @@ public final class IntelligenceManager {
        //TODO(b/111276913): properly implement by checking if it was explicitly disabled by
        // service, or if service is not set
        // (and probably renamign to isEnabledLocked()
        return mService != null;
        return mService != null && mState != STATE_DISABLED;
    }

    /**
@@ -509,6 +514,8 @@ public final class IntelligenceManager {
                return "WAITING_FOR_SERVER";
            case STATE_ACTIVE:
                return "ACTIVE";
            case STATE_DISABLED:
                return "DISABLED";
            default:
                return "INVALID:" + state;
        }
+9 −3
Original line number Diff line number Diff line
@@ -167,7 +167,7 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
    @GuardedBy("mLock")
    protected final int getServiceUidLocked() {
        if (mServiceInfo == null) {
            Slog.w(mTag, "getServiceUidLocked(): no mServiceInfo");
            if (mMaster.verbose) Slog.v(mTag, "getServiceUidLocked(): no mServiceInfo");
            return Process.INVALID_UID;
        }
        return mServiceInfo.applicationInfo.uid;
@@ -267,12 +267,18 @@ public abstract class AbstractPerUserSystemService<S extends AbstractPerUserSyst
    @GuardedBy("mLock")
    protected void dumpLocked(@NonNull String prefix, @NonNull PrintWriter pw) {
        pw.print(prefix); pw.print("User: "); pw.println(mUserId);
        pw.print(prefix); pw.print("Disabled: "); pw.println(mDisabled);
        pw.print(prefix); pw.print("Disabled by UserManager: "); pw.println(mDisabled);
        pw.print(prefix); pw.print("Setup complete: "); pw.println(mSetupComplete);
        if (mServiceInfo != null) {
            pw.print(prefix); pw.print("Service UID: ");
            pw.println(mServiceInfo.applicationInfo.uid);
        }
        pw.print(prefix); pw.print("Service name: "); pw.println(getComponentNameFromSettings());
        final String componentName = getComponentNameFromSettings();
        if (componentName != null) {
            pw.print(prefix); pw.print("Service name: ");
            pw.println(componentName);
        } else {
            pw.println("No service package set");
        }
    }
}
+20 −4
Original line number Diff line number Diff line
@@ -76,7 +76,7 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks
    }

    /**
     * Cleans up the session and remove itself from the service.
     * Cleans up the session and removes it from the service.
     *
     * @param notifyRemoteService whether it should trigger a {@link
     * IntelligenceService#onDestroyInteractionSession(InteractionSessionId)}
@@ -85,14 +85,30 @@ final class ContentCaptureSession implements RemoteIntelligenceServiceCallbacks
    @GuardedBy("mLock")
    public void removeSelfLocked(boolean notifyRemoteService) {
        try {
            if (notifyRemoteService) {
                mRemoteService.onSessionLifecycleRequest(/* context= */ null, mId);
            }
            destroyLocked(notifyRemoteService);
        } finally {
            mService.removeSessionLocked(mId);
        }
    }

    /**
     * Cleans up the session, but not removes it from the service.
     *
     * @param notifyRemoteService whether it should trigger a {@link
     * IntelligenceService#onDestroyInteractionSession(InteractionSessionId)}
     * request.
     */
    @GuardedBy("mLock")
    public void destroyLocked(boolean notifyRemoteService) {
        if (mService.isVerbose()) {
            Slog.v(TAG, "destroyLocked(notifyRemoteService=" + notifyRemoteService + ")");
        }
        // TODO(b/111276913): must call client to set session as FINISHED_BY_SERVER
        if (notifyRemoteService) {
            mRemoteService.onSessionLifecycleRequest(/* context= */ null, mId);
        }
    }

    @Override // from RemoteScreenObservationServiceCallbacks
    public void onServiceDied(AbstractRemoteService service) {
        // TODO(b/111276913): implement (remove session from PerUserSession?)
+9 −0
Original line number Diff line number Diff line
@@ -78,6 +78,15 @@ public final class IntelligenceManagerService
        publishLocalService(IntelligenceManagerInternal.class, mLocalService);
    }

    @Override // from AbstractMasterSystemService
    protected IntelligencePerUserService removeCachedServiceLocked(int userId) {
        final IntelligencePerUserService service = super.removeCachedServiceLocked(userId);
        if (service != null) {
            service.destroyLocked();
        }
        return service;
    }

    private ActivityManagerInternal getAmInternal() {
        synchronized (mLock) {
            if (mAm == null) {
+38 −3
Original line number Diff line number Diff line
@@ -88,12 +88,18 @@ final class IntelligencePerUserService
            @NonNull ComponentName componentName, int taskId, int displayId,
            @NonNull InteractionSessionId sessionId, int flags,
            @NonNull IResultReceiver resultReceiver) {
        if (!isEnabledLocked()) {
            sendToClient(resultReceiver, IntelligenceManager.STATE_DISABLED);
            return;
        }
        final ComponentName serviceComponentName = getServiceComponentName();
        if (serviceComponentName == null) {
            // TODO(b/111276913): this happens when the system service is starting, we should
            // probably handle it in a more elegant way (like waiting for boot_complete or
            // something like that
            Slog.w(TAG, "startSession(" + activityToken + "): hold your horses");
            if (mMaster.debug) {
                Slog.d(TAG, "startSession(" + activityToken + "): hold your horses");
            }
            return;
        }

@@ -128,9 +134,15 @@ final class IntelligencePerUserService
    // TODO(b/111276913): log metrics
    @GuardedBy("mLock")
    public void finishSessionLocked(@NonNull InteractionSessionId sessionId) {
        if (!isEnabledLocked()) {
            return;
        }

        final ContentCaptureSession session = mSessions.get(sessionId);
        if (session == null) {
            Slog.w(TAG, "finishSession(): no session with id" + sessionId);
            if (mMaster.debug) {
                Slog.d(TAG, "finishSession(): no session with id" + sessionId);
            }
            return;
        }
        if (mMaster.verbose) {
@@ -139,12 +151,19 @@ final class IntelligencePerUserService
        session.removeSelfLocked(true);
    }

    // TODO(b/111276913): need to figure out why some events are sent before session is started;
    // probably because IntelligenceManager is not buffering them until it gets the session back
    @GuardedBy("mLock")
    public void sendEventsLocked(@NonNull InteractionSessionId sessionId,
            @NonNull List<ContentCaptureEvent> events) {
        if (!isEnabledLocked()) {
            return;
        }
        final ContentCaptureSession session = mSessions.get(sessionId);
        if (session == null) {
            Slog.w(TAG, "sendEvents(): no session for " + sessionId);
            if (mMaster.verbose) {
                Slog.v(TAG, "sendEvents(): no session for " + sessionId);
            }
            return;
        }
        if (mMaster.verbose) {
@@ -163,6 +182,22 @@ final class IntelligencePerUserService
        return uid == getServiceUidLocked();
    }

    /**
     * Destroys the service and all state associated with it.
     *
     * <p>Called when the service was disabled (for example, if the settings change).
     */
    @GuardedBy("mLock")
    public void destroyLocked() {
        if (mMaster.debug) Slog.d(TAG, "destroyLocked()");
        final int numSessions = mSessions.size();
        for (int i = 0; i < numSessions; i++) {
            final ContentCaptureSession session = mSessions.valueAt(i);
            session.destroyLocked(true);
        }
        mSessions.clear();
    }

    @Override
    protected void dumpLocked(String prefix, PrintWriter pw) {
        super.dumpLocked(prefix, pw);