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

Commit be6bfb67 authored by Kai Li's avatar Kai Li
Browse files

Init underlay from content capture services.

As the first step in system UI(ag/32801123), we are having a broadcast listener to control the lifecycle of underlay. The content capture service is responsible for detecting the lifecycle of the target apps and create/destroy the underlay accordingly. Will migrate to a binder aidl later.

Bug: 403422950
Flag: android.view.contentcapture.flags.enable_system_ui_underlay
Change-Id: I7c0020952a50ea89121c301f4942d68ac2244ea5
Test: atest CtsContentCaptureServiceTestCase
parent 52a686e3
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -16,6 +16,13 @@ flag {
    is_exported: true
}

flag {
    name: "enable_system_ui_underlay"
    namespace: "ailabs"
    description: "Feature flag to enable the connection between content capture and system UI underlay"
    bug: "403422950"
}

flag {
    name: "flush_after_each_frame"
    namespace: "pixel_state_server"
+54 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.content.ComponentName;
import android.content.ContentCaptureOptions;
import android.content.Intent;
import android.content.pm.ActivityPresentationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -61,12 +62,14 @@ import android.service.voice.VoiceInteractionManagerInternal;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.view.contentcapture.ContentCaptureCondition;
import android.view.contentcapture.DataRemovalRequest;
import android.view.contentcapture.DataShareRequest;
import android.view.contentcapture.flags.Flags;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.IResultReceiver;
@@ -94,6 +97,9 @@ final class ContentCapturePerUserService
    static final int EVENT_LOG_CONNECT_STATE_CONNECTED = 1;
    static final int EVENT_LOG_CONNECT_STATE_DISCONNECTED = 2;

    private final String ACTION_CREATE_UNDERLAY = "com.systemui.underlay.action.CREATE_UNDERLAY";
    private final String ACTION_DESTROY_UNDERLAY = "com.systemui.underlay.action.DESTROY_UNDERLAY";

    @GuardedBy("mLock")
    private final SparseArray<ContentCaptureServerSession> mSessions = new SparseArray<>();

@@ -363,6 +369,11 @@ final class ContentCapturePerUserService
        }
        mSessions.put(sessionId, newSession);
        newSession.notifySessionStartedLocked(clientReceiver);

        if (Flags.enableSystemUiUnderlay()) {
            if (mMaster.debug) Slog.d(mTag, "startSessionLocked " + componentName);
            createSystemUIUnderlay(newSession.getSessionId());
        }
    }

    @GuardedBy("mLock")
@@ -498,6 +509,17 @@ final class ContentCapturePerUserService
        return null;
    }

    @GuardedBy("mLock")
    private ContentCaptureServerSession getSession(@NonNull ActivityId activityId) {
        for (int i = 0; i < mSessions.size(); i++) {
            final ContentCaptureServerSession session = mSessions.valueAt(i);
            if (session.isActivitySession(activityId)) {
                return session;
            }
        }
        return null;
    }

    /**
     * Destroys the service and all state associated with it.
     *
@@ -562,9 +584,41 @@ final class ContentCapturePerUserService

        if (mMaster.verbose) Slog.v(mTag, "onActivityEvent(): " + event);

        if (Flags.enableSystemUiUnderlay()) {
            if (type == ActivityEvent.TYPE_ACTIVITY_STARTED) {
                ContentCaptureServerSession session = getSession(activityId);
                if (session != null) {
                    createSystemUIUnderlay(session.getSessionId());
                }
            } else if (type == ActivityEvent.TYPE_ACTIVITY_STOPPED) {
                ContentCaptureServerSession session = getSession(activityId);
                if (session != null) {
                    destroySystemUIUnderlay(session.getSessionId());
                }
            }
        }

        mRemoteService.onActivityLifecycleEvent(event);
    }

    private void createSystemUIUnderlay(int sessionId) {
        if (mMaster.debug) Slog.d(mTag, "createSystemUIUnderlay: " + sessionId);
        // TODO: b/403422950 migrate to aidl when available
        Intent intent = new Intent(ACTION_CREATE_UNDERLAY);
        intent.putExtra("dataSessionId", sessionId);
        intent.putExtra("timestamp", System.currentTimeMillis());
        getContext().sendBroadcast(intent);
    }

    private void destroySystemUIUnderlay(int sessionId) {
        if (mMaster.debug) Slog.d(mTag, "destroySystemUIUnderlay: " + sessionId);
        // TODO: b/403422950 migrate to aidl when available
        Intent intent = new Intent(ACTION_DESTROY_UNDERLAY);
        intent.putExtra("dataSessionId", sessionId);
        intent.putExtra("timestamp", System.currentTimeMillis());
        getContext().sendBroadcast(intent);
    }

    @Override
    protected void dumpLocked(String prefix, PrintWriter pw) {
        super.dumpLocked(prefix, pw);
+20 −0
Original line number Diff line number Diff line
@@ -48,6 +48,10 @@ final class ContentCaptureServerSession {

    private static final String TAG = ContentCaptureServerSession.class.getSimpleName();

    /**
     * The {@link Activity#getActivityToken()}.
     * Note, not the {@link Activity#getShareableActivityToken()}.
     */
    final IBinder mActivityToken;
    private final ContentCapturePerUserService mService;

@@ -73,6 +77,8 @@ final class ContentCaptureServerSession {

    private final Object mLock;

    private final ActivityId mActivityId;

    public final ComponentName appComponentName;

    ContentCaptureServerSession(@NonNull Object lock, @NonNull IBinder activityToken,
@@ -86,6 +92,7 @@ final class ContentCaptureServerSession {
        mService = service;
        mId = sessionId;
        mUid = uid;
        mActivityId = activityId;
        mContentCaptureContext = new ContentCaptureContext(/* clientContext= */ null,
                activityId, appComponentName, displayId, activityToken, flags);
        mSessionStateReceiver = sessionStateReceiver;
@@ -98,11 +105,20 @@ final class ContentCaptureServerSession {

    /**
     * Returns whether this session is for the given activity.
     *
     * @param activityToken the {@link Activity#getActivityToken()} from the activity.
     */
    boolean isActivitySession(@NonNull IBinder activityToken) {
        return mActivityToken.equals(activityToken);
    }

    /**
     * Returns whether this session is for the given activity.
     */
    boolean isActivitySession(@NonNull ActivityId activityId) {
        return mActivityId.equals(activityId);
    }

    /**
     * Notifies the {@link ContentCaptureService} that the service started.
     */
@@ -213,6 +229,10 @@ final class ContentCaptureServerSession {
                /* binder= */ null);
    }

    int getSessionId() {
        return mId;
    }

    /**
     * Called when the session client binder object died - typically when its process was killed
     * and the activity was not properly destroyed.