diff options
6 files changed, 97 insertions, 42 deletions
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java index f0140e1a4df2..7fa0ac846d60 100644 --- a/core/java/android/service/contentcapture/ContentCaptureService.java +++ b/core/java/android/service/contentcapture/ContentCaptureService.java @@ -37,6 +37,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.ParcelFileDescriptor; +import android.os.Process; import android.os.RemoteException; import android.util.Log; import android.util.Slog; @@ -140,10 +141,9 @@ public abstract class ContentCaptureService extends Service { private long mCallerMismatchTimeout = 1000; private long mLastCallerMismatchLog; - /** - * Binder that receives calls from the system server. - */ - private final IContentCaptureService mServerInterface = new IContentCaptureService.Stub() { + /** Binder that receives calls from the system server in the content capture flow. */ + private final IContentCaptureService mContentCaptureServerInterface = + new IContentCaptureService.Stub() { @Override public void onConnected(IBinder callback, boolean verbose, boolean debug) { @@ -199,10 +199,24 @@ public abstract class ContentCaptureService extends Service { } }; - /** - * Binder that receives calls from the app. - */ - private final IContentCaptureDirectManager mClientInterface = + /** Binder that receives calls from the system server in the content protection flow. */ + private final IContentProtectionService mContentProtectionServerInterface = + new IContentProtectionService.Stub() { + + @Override + public void onLoginDetected( + @SuppressWarnings("rawtypes") ParceledListSlice events) { + mHandler.sendMessage( + obtainMessage( + ContentCaptureService::handleOnLoginDetected, + ContentCaptureService.this, + Binder.getCallingUid(), + events)); + } + }; + + /** Binder that receives calls from the app in the content capture flow. */ + private final IContentCaptureDirectManager mContentCaptureClientInterface = new IContentCaptureDirectManager.Stub() { @Override @@ -232,9 +246,19 @@ public abstract class ContentCaptureService extends Service { @Override public final IBinder onBind(Intent intent) { if (SERVICE_INTERFACE.equals(intent.getAction())) { - return mServerInterface.asBinder(); - } - Log.w(TAG, "Tried to bind to wrong intent (should be " + SERVICE_INTERFACE + ": " + intent); + return mContentCaptureServerInterface.asBinder(); + } + if (PROTECTION_SERVICE_INTERFACE.equals(intent.getAction())) { + return mContentProtectionServerInterface.asBinder(); + } + Log.w( + TAG, + "Tried to bind to wrong intent (should be " + + SERVICE_INTERFACE + + " or " + + PROTECTION_SERVICE_INTERFACE + + "): " + + intent); return null; } @@ -468,7 +492,7 @@ public abstract class ContentCaptureService extends Service { } else { stateFlags |= ContentCaptureSession.STATE_DISABLED; } - setClientState(clientReceiver, stateFlags, mClientInterface.asBinder()); + setClientState(clientReceiver, stateFlags, mContentCaptureClientInterface.asBinder()); } private void handleSendEvents(int uid, @@ -536,6 +560,18 @@ public abstract class ContentCaptureService extends Service { writeFlushMetrics(lastSessionId, activityComponent, metrics, options, reason); } + private void handleOnLoginDetected( + int uid, @NonNull ParceledListSlice<ContentCaptureEvent> parceledEvents) { + if (uid != Process.SYSTEM_UID) { + Log.e(TAG, "handleOnLoginDetected() not allowed for uid: " + uid); + return; + } + List<ContentCaptureEvent> events = parceledEvents.getList(); + int sessionIdInt = events.isEmpty() ? NO_SESSION_ID : events.get(0).getSessionId(); + ContentCaptureSessionId sessionId = new ContentCaptureSessionId(sessionIdInt); + events.forEach(event -> onContentCaptureEvent(sessionId, event)); + } + private void handleOnActivitySnapshot(int sessionId, @NonNull SnapshotData snapshotData) { onActivitySnapshot(new ContentCaptureSessionId(sessionId), snapshotData); } diff --git a/core/java/android/service/contentcapture/IContentProtectionService.aidl b/core/java/android/service/contentcapture/IContentProtectionService.aidl new file mode 100644 index 000000000000..4a13c3f63a33 --- /dev/null +++ b/core/java/android/service/contentcapture/IContentProtectionService.aidl @@ -0,0 +1,30 @@ +/* + * 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.pm.ParceledListSlice; +import android.view.contentcapture.ContentCaptureEvent; + +/** + * Interface from the system server to the content protection service. + * + * @hide + */ +oneway interface IContentProtectionService { + + void onLoginDetected(in ParceledListSlice events); +} diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java index b22910648e71..dc3d32317ded 100644 --- a/core/java/android/view/contentcapture/ContentCaptureSession.java +++ b/core/java/android/view/contentcapture/ContentCaptureSession.java @@ -181,8 +181,6 @@ public abstract class ContentCaptureSession implements AutoCloseable { public static final int FLUSH_REASON_VIEW_TREE_APPEARING = 9; /** @hide */ public static final int FLUSH_REASON_VIEW_TREE_APPEARED = 10; - /** @hide */ - public static final int FLUSH_REASON_LOGIN_DETECTED = 11; /** * After {@link UPSIDE_DOWN_CAKE}, {@link #notifyViewsDisappeared(AutofillId, long[])} wraps @@ -205,8 +203,7 @@ public abstract class ContentCaptureSession implements AutoCloseable { FLUSH_REASON_SESSION_CONNECTED, FLUSH_REASON_FORCE_FLUSH, FLUSH_REASON_VIEW_TREE_APPEARING, - FLUSH_REASON_VIEW_TREE_APPEARED, - FLUSH_REASON_LOGIN_DETECTED + FLUSH_REASON_VIEW_TREE_APPEARED }) @Retention(RetentionPolicy.SOURCE) public @interface FlushReason {} @@ -690,8 +687,6 @@ public abstract class ContentCaptureSession implements AutoCloseable { return "VIEW_TREE_APPEARING"; case FLUSH_REASON_VIEW_TREE_APPEARED: return "VIEW_TREE_APPEARED"; - case FLUSH_REASON_LOGIN_DETECTED: - return "LOGIN_DETECTED"; default: return "UNKNOWN-" + reason; } diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java index f8ebd09899a8..23b9b9bdb451 100644 --- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java +++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureSessionTest.java @@ -32,6 +32,7 @@ import com.google.common.collect.ImmutableMap; import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges; import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; @@ -130,6 +131,7 @@ public class ContentCaptureSessionTest { () -> mSession1.notifyViewsDisappeared(new AutofillId(42, 108), new long[] {666})); } + @Ignore("b/286134492") @Test public void testNotifyViewsDisappeared_noSendTreeEventBeforeU() { MyContentCaptureSession session = new MyContentCaptureSession(121); @@ -139,6 +141,7 @@ public class ContentCaptureSessionTest { assertThat(session.mInternalNotifyViewTreeEventFinishedCount).isEqualTo(0); } + @Ignore("b/286134492") @EnableCompatChanges({ContentCaptureSession.NOTIFY_NODES_DISAPPEAR_NOW_SENDS_TREE_EVENTS}) @Test public void testNotifyViewsDisappeared_sendTreeEventSinceU() { @@ -151,7 +154,7 @@ public class ContentCaptureSessionTest { @Test public void testGetFlushReasonAsString() { - int invalidFlushReason = ContentCaptureSession.FLUSH_REASON_LOGIN_DETECTED + 1; + int invalidFlushReason = ContentCaptureSession.FLUSH_REASON_VIEW_TREE_APPEARED + 1; Map<Integer, String> expectedMap = new ImmutableMap.Builder<Integer, String>() .put(ContentCaptureSession.FLUSH_REASON_FULL, "FULL") @@ -168,8 +171,7 @@ public class ContentCaptureSessionTest { .put( ContentCaptureSession.FLUSH_REASON_VIEW_TREE_APPEARED, "VIEW_TREE_APPEARED") - .put(ContentCaptureSession.FLUSH_REASON_LOGIN_DETECTED, "LOGIN_DETECTED") - .put(invalidFlushReason, "UNKOWN-" + invalidFlushReason) + .put(invalidFlushReason, "UNKNOWN-" + invalidFlushReason) .build(); expectedMap.forEach( diff --git a/services/contentcapture/java/com/android/server/contentprotection/RemoteContentProtectionService.java b/services/contentcapture/java/com/android/server/contentprotection/RemoteContentProtectionService.java index f5e5a431e3dd..dd5545dcccc7 100644 --- a/services/contentcapture/java/com/android/server/contentprotection/RemoteContentProtectionService.java +++ b/services/contentcapture/java/com/android/server/contentprotection/RemoteContentProtectionService.java @@ -16,17 +16,15 @@ package com.android.server.contentprotection; -import static android.view.contentcapture.ContentCaptureSession.FLUSH_REASON_LOGIN_DETECTED; - import android.annotation.NonNull; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ParceledListSlice; import android.service.contentcapture.ContentCaptureService; +import android.service.contentcapture.IContentProtectionService; import android.util.Slog; import android.view.contentcapture.ContentCaptureEvent; -import android.view.contentcapture.IContentCaptureDirectManager; import com.android.internal.infra.ServiceConnector; @@ -38,7 +36,7 @@ import java.time.Duration; * @hide */ public class RemoteContentProtectionService - extends ServiceConnector.Impl<IContentCaptureDirectManager> { + extends ServiceConnector.Impl<IContentProtectionService> { private static final String TAG = RemoteContentProtectionService.class.getSimpleName(); @@ -57,7 +55,7 @@ public class RemoteContentProtectionService .setComponent(componentName), bindAllowInstant ? Context.BIND_ALLOW_INSTANT : 0, userId, - IContentCaptureDirectManager.Stub::asInterface); + IContentProtectionService.Stub::asInterface); mComponentName = componentName; } @@ -68,7 +66,7 @@ public class RemoteContentProtectionService @Override // from ServiceConnector.Impl protected void onServiceConnectionStatusChanged( - @NonNull IContentCaptureDirectManager service, boolean isConnected) { + @NonNull IContentProtectionService service, boolean isConnected) { Slog.i( TAG, "Connection status for: " @@ -78,9 +76,6 @@ public class RemoteContentProtectionService } public void onLoginDetected(@NonNull ParceledListSlice<ContentCaptureEvent> events) { - run( - service -> - service.sendEvents( - events, FLUSH_REASON_LOGIN_DETECTED, /* options= */ null)); + run(service -> service.onLoginDetected(events)); } } diff --git a/services/tests/servicestests/src/com/android/server/contentprotection/RemoteContentProtectionServiceTest.java b/services/tests/servicestests/src/com/android/server/contentprotection/RemoteContentProtectionServiceTest.java index 2f57fd37194e..9135ef3a1286 100644 --- a/services/tests/servicestests/src/com/android/server/contentprotection/RemoteContentProtectionServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/contentprotection/RemoteContentProtectionServiceTest.java @@ -16,8 +16,6 @@ package com.android.server.contentprotection; -import static android.view.contentcapture.ContentCaptureSession.FLUSH_REASON_LOGIN_DETECTED; - import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.fail; @@ -29,8 +27,8 @@ import android.content.ComponentName; import android.content.Context; import android.content.pm.ParceledListSlice; import android.os.UserHandle; +import android.service.contentcapture.IContentProtectionService; import android.view.contentcapture.ContentCaptureEvent; -import android.view.contentcapture.IContentCaptureDirectManager; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -63,7 +61,7 @@ public class RemoteContentProtectionServiceTest { @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); - @Mock private IContentCaptureDirectManager mMockContentCaptureDirectManager; + @Mock private IContentProtectionService mMockContentProtectionService; private RemoteContentProtectionService mRemoteContentProtectionService; @@ -79,7 +77,7 @@ public class RemoteContentProtectionServiceTest { @Test public void doesNotAutoConnect() { assertThat(mConnectCallCount).isEqualTo(0); - verifyZeroInteractions(mMockContentCaptureDirectManager); + verifyZeroInteractions(mMockContentProtectionService); } @Test @@ -98,8 +96,7 @@ public class RemoteContentProtectionServiceTest { mRemoteContentProtectionService.onLoginDetected(events); - verify(mMockContentCaptureDirectManager) - .sendEvents(events, FLUSH_REASON_LOGIN_DETECTED, /* options= */ null); + verify(mMockContentProtectionService).onLoginDetected(events); } private final class TestRemoteContentProtectionService extends RemoteContentProtectionService { @@ -109,15 +106,15 @@ public class RemoteContentProtectionServiceTest { } @Override // from ServiceConnector - public synchronized AndroidFuture<IContentCaptureDirectManager> connect() { + public synchronized AndroidFuture<IContentProtectionService> connect() { mConnectCallCount++; - return AndroidFuture.completedFuture(mMockContentCaptureDirectManager); + return AndroidFuture.completedFuture(mMockContentProtectionService); } @Override // from ServiceConnector - public boolean run(@NonNull ServiceConnector.VoidJob<IContentCaptureDirectManager> job) { + public boolean run(@NonNull ServiceConnector.VoidJob<IContentProtectionService> job) { try { - job.run(mMockContentCaptureDirectManager); + job.run(mMockContentProtectionService); } catch (Exception ex) { fail("Unexpected exception: " + ex); } |