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

Commit e529440c authored by Nino Jagar's avatar Nino Jagar Committed by Android (Google) Code Review
Browse files

Merge "Allow service to update content protection allowlist" into main

parents 25693fe1 0f897955
Loading
Loading
Loading
Loading
+51 −11
Original line number Diff line number Diff line
@@ -138,7 +138,8 @@ public abstract class ContentCaptureService extends Service {
            new LocalDataShareAdapterResourceManager();

    private Handler mHandler;
    private IContentCaptureServiceCallback mCallback;
    @Nullable private IContentCaptureServiceCallback mContentCaptureServiceCallback;
    @Nullable private IContentProtectionAllowlistCallback mContentProtectionAllowlistCallback;

    private long mCallerMismatchTimeout = 1000;
    private long mLastCallerMismatchLog;
@@ -215,6 +216,16 @@ public abstract class ContentCaptureService extends Service {
                                    Binder.getCallingUid(),
                                    events));
                }

                @Override
                public void onUpdateAllowlistRequest(IBinder callback) {
                    mHandler.sendMessage(
                            obtainMessage(
                                    ContentCaptureService::handleOnUpdateAllowlistRequest,
                                    ContentCaptureService.this,
                                    Binder.getCallingUid(),
                                    callback));
                }
            };

    /** Binder that receives calls from the app in the content capture flow. */
@@ -278,14 +289,31 @@ public abstract class ContentCaptureService extends Service {
     */
    public final void setContentCaptureWhitelist(@Nullable Set<String> packages,
            @Nullable Set<ComponentName> activities) {
        final IContentCaptureServiceCallback callback = mCallback;
        if (callback == null) {
            Log.w(TAG, "setContentCaptureWhitelist(): no server callback");

        IContentCaptureServiceCallback contentCaptureCallback = mContentCaptureServiceCallback;
        IContentProtectionAllowlistCallback contentProtectionAllowlistCallback =
                mContentProtectionAllowlistCallback;

        if (contentCaptureCallback == null && contentProtectionAllowlistCallback == null) {
            Log.w(TAG, "setContentCaptureWhitelist(): missing both server callbacks");
            return;
        }

        if (contentCaptureCallback != null) {
            if (contentProtectionAllowlistCallback != null) {
                throw new IllegalStateException("Have both server callbacks");
            }
            try {
                contentCaptureCallback.setContentCaptureWhitelist(
                        toList(packages), toList(activities));
            } catch (RemoteException e) {
                e.rethrowFromSystemServer();
            }
            return;
        }

        try {
            callback.setContentCaptureWhitelist(toList(packages), toList(activities));
            contentProtectionAllowlistCallback.setAllowlist(toList(packages));
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
@@ -314,7 +342,7 @@ public abstract class ContentCaptureService extends Service {
     */
    public final void setContentCaptureConditions(@NonNull String packageName,
            @Nullable Set<ContentCaptureCondition> conditions) {
        final IContentCaptureServiceCallback callback = mCallback;
        final IContentCaptureServiceCallback callback = mContentCaptureServiceCallback;
        if (callback == null) {
            Log.w(TAG, "setContentCaptureConditions(): no server callback");
            return;
@@ -425,7 +453,7 @@ public abstract class ContentCaptureService extends Service {
    public final void disableSelf() {
        if (sDebug) Log.d(TAG, "disableSelf()");

        final IContentCaptureServiceCallback callback = mCallback;
        final IContentCaptureServiceCallback callback = mContentCaptureServiceCallback;
        if (callback == null) {
            Log.w(TAG, "disableSelf(): no server callback");
            return;
@@ -464,13 +492,14 @@ public abstract class ContentCaptureService extends Service {
    }

    private void handleOnConnected(@NonNull IBinder callback) {
        mCallback = IContentCaptureServiceCallback.Stub.asInterface(callback);
        mContentCaptureServiceCallback = IContentCaptureServiceCallback.Stub.asInterface(callback);
        onConnected();
    }

    private void handleOnDisconnected() {
        onDisconnected();
        mCallback = null;
        mContentCaptureServiceCallback = null;
        mContentProtectionAllowlistCallback = null;
    }

    //TODO(b/111276913): consider caching the InteractionSessionId for the lifetime of the session,
@@ -583,6 +612,16 @@ public abstract class ContentCaptureService extends Service {
        onContentCaptureEvent(sessionId, endEvent);
    }

    private void handleOnUpdateAllowlistRequest(int uid, @NonNull IBinder callback) {
        if (uid != Process.SYSTEM_UID) {
            Log.e(TAG, "handleOnUpdateAllowlistRequest() not allowed for uid: " + uid);
            return;
        }
        mContentProtectionAllowlistCallback =
                IContentProtectionAllowlistCallback.Stub.asInterface(callback);
        onConnected();
    }

    private void handleOnActivitySnapshot(int sessionId, @NonNull SnapshotData snapshotData) {
        onActivitySnapshot(new ContentCaptureSessionId(sessionId), snapshotData);
    }
@@ -701,13 +740,14 @@ public abstract class ContentCaptureService extends Service {
    private void writeFlushMetrics(int sessionId, @Nullable ComponentName app,
            @NonNull FlushMetrics flushMetrics, @Nullable ContentCaptureOptions options,
            int flushReason) {
        if (mCallback == null) {
        if (mContentCaptureServiceCallback == null) {
            Log.w(TAG, "writeSessionFlush(): no server callback");
            return;
        }

        try {
            mCallback.writeSessionFlush(sessionId, app, flushMetrics, options, flushReason);
            mContentCaptureServiceCallback.writeSessionFlush(
                    sessionId, app, flushMetrics, options, flushReason);
        } catch (RemoteException e) {
            Log.e(TAG, "failed to write flush metrics: " + e);
        }
+34 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.service.contentcapture;

import android.content.ComponentName;
import android.view.contentcapture.ContentCaptureCondition;
import android.service.contentcapture.FlushMetrics;
import android.content.ContentCaptureOptions;

import java.util.List;

/**
 * Interface for the callback used by the content protection service to call the system server and
 * update the allowlist.
 *
 * @hide
 */
oneway interface IContentProtectionAllowlistCallback {
    void setAllowlist(in List<String> packages);
}
+3 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.service.contentcapture;

import android.content.pm.ParceledListSlice;
import android.os.IBinder;
import android.view.contentcapture.ContentCaptureEvent;

/**
@@ -27,4 +28,6 @@ import android.view.contentcapture.ContentCaptureEvent;
oneway interface IContentProtectionService {

    void onLoginDetected(in ParceledListSlice events);

    void onUpdateAllowlistRequest(in IBinder callback);
}
+11 −0
Original line number Diff line number Diff line
@@ -411,6 +411,15 @@ public final class ContentCaptureManager {
    public static final String DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_ALLOWLIST_TIMEOUT_MS =
            "content_protection_allowlist_timeout_ms";

    /**
     * Sets the auto disconnect timeout for the content protection service in milliseconds.
     *
     * @hide
     */
    // Unit can't be in the name in order to pass the checkstyle hook, line would be too long.
    public static final String DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_AUTO_DISCONNECT_TIMEOUT =
            "content_protection_auto_disconnect_timeout_ms";

    /** @hide */
    @TestApi
    public static final int LOGGING_LEVEL_OFF = 0;
@@ -465,6 +474,8 @@ public final class ContentCaptureManager {
    public static final long DEFAULT_CONTENT_PROTECTION_ALLOWLIST_DELAY_MS = 30000;
    /** @hide */
    public static final long DEFAULT_CONTENT_PROTECTION_ALLOWLIST_TIMEOUT_MS = 250;
    /** @hide */
    public static final long DEFAULT_CONTENT_PROTECTION_AUTO_DISCONNECT_TIMEOUT_MS = 3000;

    private final Object mLock = new Object();

+29 −10
Original line number Diff line number Diff line
@@ -22,9 +22,12 @@ import static android.service.contentcapture.ContentCaptureService.setClientStat
import static android.view.contentcapture.ContentCaptureHelper.toList;
import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_ALLOWLIST_DELAY_MS;
import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_ALLOWLIST_TIMEOUT_MS;
import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_AUTO_DISCONNECT_TIMEOUT;
import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_BUFFER_SIZE;
import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_OPTIONAL_GROUPS_CONFIG;
import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_OPTIONAL_GROUPS_THRESHOLD;
import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_REQUIRED_GROUPS_CONFIG;
import static android.view.contentcapture.ContentCaptureManager.DEVICE_CONFIG_PROPERTY_ENABLE_CONTENT_PROTECTION_RECEIVER;
import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_FALSE;
import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_OK;
import static android.view.contentcapture.ContentCaptureManager.RESULT_CODE_SECURITY_EXCEPTION;
@@ -227,6 +230,9 @@ public class ContentCaptureManagerService extends
    @GuardedBy("mLock")
    long mDevCfgContentProtectionAllowlistTimeoutMs;

    @GuardedBy("mLock")
    long mDevCfgContentProtectionAutoDisconnectTimeoutMs;

    private final Executor mDataShareExecutor = Executors.newCachedThreadPool();
    private final Handler mHandler = new Handler(Looper.getMainLooper());

@@ -435,14 +441,15 @@ public class ContentCaptureManagerService extends
                case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT:
                case ContentCaptureManager
                        .DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING:
                case ContentCaptureManager
                        .DEVICE_CONFIG_PROPERTY_ENABLE_CONTENT_PROTECTION_RECEIVER:
                case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_BUFFER_SIZE:
                    // Content protection below
                case DEVICE_CONFIG_PROPERTY_ENABLE_CONTENT_PROTECTION_RECEIVER:
                case DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_BUFFER_SIZE:
                case DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_REQUIRED_GROUPS_CONFIG:
                case DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_OPTIONAL_GROUPS_CONFIG:
                case DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_OPTIONAL_GROUPS_THRESHOLD:
                case DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_ALLOWLIST_DELAY_MS:
                case DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_ALLOWLIST_TIMEOUT_MS:
                case DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_AUTO_DISCONNECT_TIMEOUT:
                    setFineTuneParamsFromDeviceConfig();
                    return;
                default:
@@ -502,8 +509,7 @@ public class ContentCaptureManagerService extends
            mDevCfgContentProtectionBufferSize =
                    DeviceConfig.getInt(
                            DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
                            ContentCaptureManager
                                    .DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_BUFFER_SIZE,
                            DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_BUFFER_SIZE,
                            ContentCaptureManager.DEFAULT_CONTENT_PROTECTION_BUFFER_SIZE);
            contentProtectionRequiredGroupsConfig =
                    DeviceConfig.getString(
@@ -533,7 +539,12 @@ public class ContentCaptureManagerService extends
                            DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
                            DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_ALLOWLIST_TIMEOUT_MS,
                            ContentCaptureManager.DEFAULT_CONTENT_PROTECTION_ALLOWLIST_TIMEOUT_MS);

            mDevCfgContentProtectionAutoDisconnectTimeoutMs =
                    DeviceConfig.getLong(
                            DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
                            DEVICE_CONFIG_PROPERTY_CONTENT_PROTECTION_AUTO_DISCONNECT_TIMEOUT,
                            ContentCaptureManager
                                    .DEFAULT_CONTENT_PROTECTION_AUTO_DISCONNECT_TIMEOUT_MS);
            contentProtectionAllowlistManagerOld = mContentProtectionAllowlistManager;

            if (verbose) {
@@ -565,7 +576,9 @@ public class ContentCaptureManagerService extends
                                + ", contentProtectionAllowlistDelayMs="
                                + contentProtectionAllowlistDelayMs
                                + ", contentProtectionAllowlistTimeoutMs="
                                + contentProtectionAllowlistTimeoutMs);
                                + contentProtectionAllowlistTimeoutMs
                                + ", contentProtectionAutoDisconnectTimeoutMs="
                                + mDevCfgContentProtectionAutoDisconnectTimeoutMs);
            }
        }

@@ -893,6 +906,9 @@ public class ContentCaptureManagerService extends
        pw.print(prefix2);
        pw.print("contentProtectionAllowlistTimeoutMs: ");
        pw.println(mDevCfgContentProtectionAllowlistTimeoutMs);
        pw.print(prefix2);
        pw.print("contentProtectionAutoDisconnectTimeoutMs: ");
        pw.println(mDevCfgContentProtectionAutoDisconnectTimeoutMs);
        pw.print(prefix);
        pw.println("Global Options:");
        mGlobalContentCaptureOptions.dump(prefix2, pw);
@@ -962,12 +978,14 @@ public class ContentCaptureManagerService extends
    @Nullable
    public RemoteContentProtectionService createRemoteContentProtectionService() {
        ComponentName componentName;
        long autoDisconnectTimeoutMs;
        synchronized (mLock) {
            if (!mDevCfgEnableContentProtectionReceiver
                    || mContentProtectionServiceComponentName == null) {
                return null;
            }
            componentName = mContentProtectionServiceComponentName;
            autoDisconnectTimeoutMs = mDevCfgContentProtectionAutoDisconnectTimeoutMs;
        }

        // Check permissions by trying to construct {@link ContentCaptureServiceInfo}
@@ -978,19 +996,20 @@ public class ContentCaptureManagerService extends
            return null;
        }

        return createRemoteContentProtectionService(componentName);
        return createRemoteContentProtectionService(componentName, autoDisconnectTimeoutMs);
    }

    /** @hide */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    @NonNull
    protected RemoteContentProtectionService createRemoteContentProtectionService(
            @NonNull ComponentName componentName) {
            @NonNull ComponentName componentName, long autoDisconnectTimeoutMs) {
        return new RemoteContentProtectionService(
                getContext(),
                componentName,
                UserHandle.getCallingUserId(),
                isBindInstantServiceAllowed());
                isBindInstantServiceAllowed(),
                autoDisconnectTimeoutMs);
    }

    /** @hide */
Loading