Integrate content capture with FLAG_SECURE
Change-Id: I4e2c7d8063ca224d2037c01b7ddb24f8a7d85cbf
Fixes: 119254124
Test: atest CtsContentCaptureServiceTestCases
Test: atest android.contentcaptureservice.cts.LoginActivityTest#testStateDisabledByFlagSecure
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index fdb71bb..c89848e 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -121,6 +121,7 @@
import android.view.autofill.AutofillManager.AutofillClient;
import android.view.autofill.AutofillPopupWindow;
import android.view.autofill.IAutofillWindowPresenter;
+import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.ContentCaptureManager;
import android.widget.AdapterView;
import android.widget.Toast;
@@ -1045,14 +1046,19 @@
private void notifyContentCaptureManagerIfNeeded(@ContentCaptureNotificationType int type) {
final ContentCaptureManager cm = getContentCaptureManager();
- if (cm == null || !cm.isContentCaptureEnabled()) {
+ if (cm == null) {
return;
}
switch (type) {
case CONTENT_CAPTURE_START:
//TODO(b/111276913): decide whether the InteractionSessionId should be
// saved / restored in the activity bundle - probably not
- cm.onActivityStarted(mToken, getComponentName());
+ int flags = 0;
+ if ((getWindow().getAttributes().flags
+ & WindowManager.LayoutParams.FLAG_SECURE) != 0) {
+ flags |= ContentCaptureContext.FLAG_DISABLED_BY_FLAG_SECURE;
+ }
+ cm.onActivityStarted(mToken, getComponentName(), flags);
break;
case CONTENT_CAPTURE_FLUSH:
cm.flush();
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index 26bf361..adcb7a5 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -311,6 +311,14 @@
@NonNull String sessionId, int uid, IResultReceiver clientReceiver) {
mSessionUids.put(sessionId, uid);
onCreateContentCaptureSession(context, new ContentCaptureSessionId(sessionId));
+
+ final int flags = context.getFlags();
+ if ((flags & ContentCaptureContext.FLAG_DISABLED_BY_FLAG_SECURE) != 0) {
+ setClientState(clientReceiver, ContentCaptureSession.STATE_DISABLED_BY_FLAG_SECURE,
+ mClientInterface.asBinder());
+ return;
+ }
+
setClientState(clientReceiver, ContentCaptureSession.STATE_ACTIVE,
mClientInterface.asBinder());
}
@@ -392,15 +400,16 @@
}
/**
- * Sends the state of the {@link ContentCaptureManager} in the cleint app.
+ * Sends the state of the {@link ContentCaptureManager} in the client app.
*
* @param clientReceiver receiver in the client app.
+ * @param sessionState state of the session
* @param binder handle to the {@code IContentCaptureDirectManager} object that resides in the
* service.
* @hide
*/
public static void setClientState(@NonNull IResultReceiver clientReceiver,
- int sessionStatus, @Nullable IBinder binder) {
+ int sessionState, @Nullable IBinder binder) {
try {
final Bundle extras;
if (binder != null) {
@@ -409,7 +418,7 @@
} else {
extras = null;
}
- clientReceiver.send(sessionStatus, extras);
+ clientReceiver.send(sessionState, extras);
} catch (RemoteException e) {
Slog.w(TAG, "Error async reporting result to client: " + e);
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index e962e7c..fe050ac 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -116,8 +116,8 @@
/** @hide */
public void onActivityStarted(@NonNull IBinder applicationToken,
- @NonNull ComponentName activityComponent) {
- getMainContentCaptureSession().start(applicationToken, activityComponent);
+ @NonNull ComponentName activityComponent, int flags) {
+ getMainContentCaptureSession().start(applicationToken, activityComponent, flags);
}
/** @hide */
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 344b9973..2119073 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -86,6 +86,13 @@
*/
public static final int STATE_DISABLED_DUPLICATED_ID = 4;
+ /**
+ * Session is disabled by FLAG_SECURE
+ *
+ * @hide
+ */
+ public static final int STATE_DISABLED_BY_FLAG_SECURE = 5;
+
private static final int INITIAL_CHILDREN_CAPACITY = 5;
private final CloseGuard mCloseGuard = CloseGuard.get();
@@ -356,6 +363,8 @@
return "DISABLED_NO_SERVICE";
case STATE_DISABLED_DUPLICATED_ID:
return "DISABLED_DUPLICATED_ID";
+ case STATE_DISABLED_BY_FLAG_SECURE:
+ return "DISABLED_FLAG_SECURE";
default:
return "INVALID:" + state;
}
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index 8be887b..a29aaf0 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -157,7 +157,8 @@
*
* @hide
*/
- void start(@NonNull IBinder applicationToken, @NonNull ComponentName activityComponent) {
+ void start(@NonNull IBinder applicationToken, @NonNull ComponentName activityComponent,
+ int flags) {
if (!isContentCaptureEnabled()) return;
if (VERBOSE) {
@@ -166,7 +167,7 @@
}
mHandler.sendMessage(obtainMessage(MainContentCaptureSession::handleStartSession, this,
- applicationToken, activityComponent));
+ applicationToken, activityComponent, flags));
}
@Override
@@ -181,7 +182,8 @@
obtainMessage(MainContentCaptureSession::handleDestroySession, this));
}
- private void handleStartSession(@NonNull IBinder token, @NonNull ComponentName componentName) {
+ private void handleStartSession(@NonNull IBinder token, @NonNull ComponentName componentName,
+ int flags) {
if (mState != STATE_UNKNOWN) {
// TODO(b/111276913): revisit this scenario
Log.w(TAG, "ignoring handleStartSession(" + token + ") while on state "
@@ -196,7 +198,6 @@
Log.v(TAG, "handleStartSession(): token=" + token + ", act="
+ getActivityDebugName() + ", id=" + mId);
}
- final int flags = 0; // TODO(b/111276913): get proper flags
try {
if (mSystemServerInterface == null) return;
@@ -245,7 +246,11 @@
Log.w(TAG, "Failed to link to death on " + binder + ": " + e);
}
}
- if (resultCode == STATE_DISABLED_NO_SERVICE || resultCode == STATE_DISABLED_DUPLICATED_ID) {
+
+ // TODO(b/111276913): change the resultCode to use flags so there's just one flag for
+ // disabled stuff
+ if (resultCode == STATE_DISABLED_NO_SERVICE || resultCode == STATE_DISABLED_DUPLICATED_ID
+ || resultCode == STATE_DISABLED_BY_FLAG_SECURE) {
mDisabled.set(true);
handleResetSession(/* resetState= */ false);
} else {