summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoanne Chung <joannechung@google.com>2021-02-01 19:01:30 +0800
committerJoanne Chung <joannechung@google.com>2021-03-02 06:47:48 +0000
commitaf76755ff76e5e323ee31af593870dcde154b1d2 (patch)
tree57d3ccacc51c3a4912673b4594b12f3040badaec
parentea5f042755856ab9b249f83adcb8e47e64a0cab9 (diff)
Update ContentCaptureContext to have a token information
In order to support auto translation, we need to give information to content capture service to let the app can use this information to find the Activity which needed to be translated. It's not safe to provide an activity token to the client app directly even if it is a privilege app. They can use this activity token to access many activity/windows related functions. We create a new token for use for content capture and translation. This token will be used get the target Activity for translation new APIs. This change focuses on the Content capture API change, the API change about translation will be done in the next change, Bug: 177789967 Test: manual. Make sure cc service can get the information. Test: atest android.view.contentcapture.ContentCaptureContextTest Test: atest CtsContentCaptureServiceTestCases Change-Id: Ife8096a8bd1e71ce4e686d95043e347222ad7ee6
-rw-r--r--core/api/system-current.txt4
-rw-r--r--core/api/test-current.txt9
-rw-r--r--core/java/android/app/Activity.java12
-rw-r--r--core/java/android/app/ActivityThread.java15
-rw-r--r--core/java/android/app/Instrumentation.java3
-rw-r--r--core/java/android/app/LocalActivityManager.java2
-rw-r--r--core/java/android/app/assist/ActivityId.java125
-rw-r--r--core/java/android/app/servertransaction/LaunchActivityItem.java22
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureContext.java46
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureManager.java5
-rw-r--r--core/java/android/view/contentcapture/IContentCaptureManager.aidl5
-rw-r--r--core/java/android/view/contentcapture/MainContentCaptureSession.java16
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java4
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/TestUtils.java9
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java1
-rw-r--r--core/tests/coretests/src/android/view/contentcapture/ContentCaptureContextTest.java15
-rw-r--r--core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java2
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java23
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java6
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java9
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java12
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskSupervisor.java2
24 files changed, 288 insertions, 65 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 0f11f53fb5af..c7744a415db5 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -954,6 +954,9 @@ package android.app.admin {
package android.app.assist {
+ public class ActivityId {
+ }
+
public static class AssistStructure.ViewNode {
ctor public AssistStructure.ViewNode();
}
@@ -13996,6 +13999,7 @@ package android.view.contentcapture {
public final class ContentCaptureContext implements android.os.Parcelable {
method @Nullable public android.content.ComponentName getActivityComponent();
+ method @Nullable public android.app.assist.ActivityId getActivityId();
method public int getDisplayId();
method public int getFlags();
method @Nullable public android.view.contentcapture.ContentCaptureSessionId getParentSessionId();
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 6ee57d6b0392..76295545ad17 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -544,6 +544,15 @@ package android.app.admin {
}
+package android.app.assist {
+
+ public class ActivityId {
+ method public int getTaskId();
+ method @Nullable public android.os.IBinder getToken();
+ }
+
+}
+
package android.app.blob {
public class BlobStoreManager {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a73fe71cfe1a..cc2d36379c88 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -803,6 +803,7 @@ public class Activity extends ContextThemeWrapper
@UnsupportedAppUsage
private IBinder mToken;
private IBinder mAssistToken;
+ private IBinder mShareableActivityToken;
@UnsupportedAppUsage
private int mIdent;
@UnsupportedAppUsage
@@ -1210,7 +1211,7 @@ public class Activity extends ContextThemeWrapper
if (window != null) {
cm.updateWindowAttributes(window.getAttributes());
}
- cm.onActivityCreated(mToken, getComponentName());
+ cm.onActivityCreated(mToken, mShareableActivityToken, getComponentName());
break;
case CONTENT_CAPTURE_RESUME:
cm.onActivityResumed();
@@ -7838,7 +7839,8 @@ public class Activity extends ContextThemeWrapper
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor,
- Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
+ Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,
+ IBinder shareableActivityToken) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
@@ -7860,6 +7862,7 @@ public class Activity extends ContextThemeWrapper
mInstrumentation = instr;
mToken = token;
mAssistToken = assistToken;
+ mShareableActivityToken = shareableActivityToken;
mIdent = ident;
mApplication = application;
mIntent = intent;
@@ -7918,6 +7921,11 @@ public class Activity extends ContextThemeWrapper
}
/** @hide */
+ public final IBinder getShareableActivityToken() {
+ return mParent != null ? mParent.getShareableActivityToken() : mShareableActivityToken;
+ }
+
+ /** @hide */
@VisibleForTesting
public final ActivityThread getActivityThread() {
return mMainThread;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 47d2e7cee65a..730fce9449d0 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -517,6 +517,9 @@ public final class ActivityThread extends ClientTransactionHandler {
@UnsupportedAppUsage
public IBinder token;
public IBinder assistToken;
+ // A reusable token for other purposes, e.g. content capture, translation. It shouldn't be
+ // used without security checks
+ public IBinder shareableActivityToken;
int ident;
@UnsupportedAppUsage
Intent intent;
@@ -604,9 +607,11 @@ public final class ActivityThread extends ClientTransactionHandler {
PersistableBundle persistentState, List<ResultInfo> pendingResults,
List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
boolean isForward, ProfilerInfo profilerInfo, ClientTransactionHandler client,
- IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments) {
+ IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments,
+ IBinder shareableActivityToken) {
this.token = token;
this.assistToken = assistToken;
+ this.shareableActivityToken = shareableActivityToken;
this.ident = ident;
this.intent = intent;
this.referrer = referrer;
@@ -3157,11 +3162,13 @@ public final class ActivityThread extends ClientTransactionHandler {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public final Activity startActivityNow(Activity parent, String id,
- Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
- Activity.NonConfigurationInstances lastNonConfigurationInstances, IBinder assistToken) {
+ Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
+ Activity.NonConfigurationInstances lastNonConfigurationInstances, IBinder assistToken,
+ IBinder shareableActivityToken) {
ActivityClientRecord r = new ActivityClientRecord();
r.token = token;
r.assistToken = assistToken;
+ r.shareableActivityToken = shareableActivityToken;
r.ident = 0;
r.intent = intent;
r.state = state;
@@ -3504,7 +3511,7 @@ public final class ActivityThread extends ClientTransactionHandler {
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback,
- r.assistToken);
+ r.assistToken, r.shareableActivityToken);
if (customIntent != null) {
activity.mIntent = customIntent;
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 8d1076ea1277..b2184fe65887 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1247,7 +1247,8 @@ public class Instrumentation {
info, title, parent, id,
(Activity.NonConfigurationInstances)lastNonConfigurationInstance,
new Configuration(), null /* referrer */, null /* voiceInteractor */,
- null /* window */, null /* activityConfigCallback */, null /*assistToken*/);
+ null /* window */, null /* activityConfigCallback */, null /*assistToken*/,
+ null /*shareableActivityToken*/);
return activity;
}
diff --git a/core/java/android/app/LocalActivityManager.java b/core/java/android/app/LocalActivityManager.java
index 74e61250f109..6b5f19a52e33 100644
--- a/core/java/android/app/LocalActivityManager.java
+++ b/core/java/android/app/LocalActivityManager.java
@@ -158,7 +158,7 @@ public class LocalActivityManager {
r.activityInfo = mActivityThread.resolveActivityInfo(r.intent);
}
r.activity = mActivityThread.startActivityNow(
- mParent, r.id, r.intent, r.activityInfo, r, r.instanceState, instance, r);
+ mParent, r.id, r.intent, r.activityInfo, r, r.instanceState, instance, r, r);
if (r.activity == null) {
return;
}
diff --git a/core/java/android/app/assist/ActivityId.java b/core/java/android/app/assist/ActivityId.java
new file mode 100644
index 000000000000..fb0d056c2a34
--- /dev/null
+++ b/core/java/android/app/assist/ActivityId.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2021 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.app.assist;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.service.contentcapture.ContentCaptureService;
+import android.view.contentcapture.ContentCaptureContext;
+import android.view.translation.UiTranslationManager;
+
+import com.android.internal.annotations.Immutable;
+
+/**
+ * The class is used to identify an instance of an Activity. The system provides this to services
+ * that need to request operations on a specific Activity. For example, the system provides this in
+ * {@link ContentCaptureContext} to {@link ContentCaptureService} which can use it to issue requests
+ * like {@link UiTranslationManager#startTranslation}.
+ *
+ * @hide
+ */
+@Immutable
+@SystemApi
+public class ActivityId {
+
+ /**
+ * The identifier of the task this activity is in.
+ */
+ private final int mTaskId;
+ /**
+ * The identifier of the activity.
+ */
+ @Nullable
+ private final IBinder mActivityId;
+
+ /**
+ * @hide
+ */
+ public ActivityId(int taskId, @Nullable IBinder activityId) {
+ mTaskId = taskId;
+ mActivityId = activityId;
+ }
+
+ /**
+ * @hide
+ */
+ public ActivityId(@NonNull Parcel source) {
+ mTaskId = source.readInt();
+ mActivityId = source.readStrongBinder();
+ }
+
+ /**
+ * The identifier of the task this activity is in.
+ * @hide
+ */
+ @TestApi
+ public int getTaskId() {
+ return mTaskId;
+ }
+
+ /**
+ * The identifier of the activity. In some case, this value may be null, e.g. the child session
+ * of content capture.
+ * @hide
+ */
+ @Nullable
+ @TestApi
+ public IBinder getToken() {
+ return mActivityId;
+ }
+
+ /**
+ * @hide
+ */
+ public void writeToParcel(@NonNull Parcel dest, int parcelableFlags) {
+ dest.writeInt(mTaskId);
+ dest.writeStrongBinder(mActivityId);
+ }
+
+ @Override
+ public String toString() {
+ return "ActivityId { taskId = " + mTaskId + ", activityId = " + mActivityId + " }";
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ ActivityId that = (ActivityId) o;
+ if (mTaskId != that.mTaskId) {
+ return false;
+ }
+ return mActivityId != null
+ ? mActivityId.equals(that.mActivityId)
+ : that.mActivityId == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = mTaskId;
+ result = 31 * result + (mActivityId != null ? mActivityId.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java
index 73a9ceccecee..94ab0dd00113 100644
--- a/core/java/android/app/servertransaction/LaunchActivityItem.java
+++ b/core/java/android/app/servertransaction/LaunchActivityItem.java
@@ -71,6 +71,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
private boolean mIsForward;
private ProfilerInfo mProfilerInfo;
private IBinder mAssistToken;
+ private IBinder mShareableActivityToken;
/**
* It is only non-null if the process is the first time to launch activity. It is only an
* optimization for quick look up of the interface so the field is ignored for comparison.
@@ -95,7 +96,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mActivityOptions, mIsForward, mProfilerInfo,
- client, mAssistToken, mFixedRotationAdjustments);
+ client, mAssistToken, mFixedRotationAdjustments, mShareableActivityToken);
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
@@ -119,7 +120,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
List<ReferrerIntent> pendingNewIntents, ActivityOptions activityOptions,
boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken,
IActivityClientController activityClientController,
- FixedRotationAdjustments fixedRotationAdjustments) {
+ FixedRotationAdjustments fixedRotationAdjustments, IBinder shareableActivityToken) {
LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class);
if (instance == null) {
instance = new LaunchActivityItem();
@@ -127,7 +128,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
setValues(instance, intent, ident, info, curConfig, overrideConfig, compatInfo, referrer,
voiceInteractor, procState, state, persistentState, pendingResults,
pendingNewIntents, activityOptions, isForward, profilerInfo, assistToken,
- activityClientController, fixedRotationAdjustments);
+ activityClientController, fixedRotationAdjustments, shareableActivityToken);
return instance;
}
@@ -135,7 +136,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
@Override
public void recycle() {
setValues(this, null, 0, null, null, null, null, null, null, 0, null, null, null, null,
- null, false, null, null, null, null);
+ null, false, null, null, null, null, null);
ObjectPool.recycle(this);
}
@@ -164,6 +165,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
dest.writeStrongBinder(mAssistToken);
dest.writeStrongInterface(mActivityClientController);
dest.writeTypedObject(mFixedRotationAdjustments, flags);
+ dest.writeStrongBinder(mShareableActivityToken);
}
/** Read from Parcel. */
@@ -181,7 +183,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
in.readTypedObject(ProfilerInfo.CREATOR),
in.readStrongBinder(),
IActivityClientController.Stub.asInterface(in.readStrongBinder()),
- in.readTypedObject(FixedRotationAdjustments.CREATOR));
+ in.readTypedObject(FixedRotationAdjustments.CREATOR), in.readStrongBinder());
}
public static final @NonNull Creator<LaunchActivityItem> CREATOR =
@@ -219,7 +221,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
&& mIsForward == other.mIsForward
&& Objects.equals(mProfilerInfo, other.mProfilerInfo)
&& Objects.equals(mAssistToken, other.mAssistToken)
- && Objects.equals(mFixedRotationAdjustments, other.mFixedRotationAdjustments);
+ && Objects.equals(mFixedRotationAdjustments, other.mFixedRotationAdjustments)
+ && Objects.equals(mShareableActivityToken, other.mShareableActivityToken);
}
@Override
@@ -241,6 +244,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
result = 31 * result + Objects.hashCode(mProfilerInfo);
result = 31 * result + Objects.hashCode(mAssistToken);
result = 31 * result + Objects.hashCode(mFixedRotationAdjustments);
+ result = 31 * result + Objects.hashCode(mShareableActivityToken);
return result;
}
@@ -277,7 +281,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
+ ",persistentState=" + mPersistentState + ",pendingResults=" + mPendingResults
+ ",pendingNewIntents=" + mPendingNewIntents + ",options=" + mActivityOptions
+ ",profilerInfo=" + mProfilerInfo + ",assistToken=" + mAssistToken
- + ",rotationAdj=" + mFixedRotationAdjustments + "}";
+ + ",rotationAdj=" + mFixedRotationAdjustments
+ + ",shareableActivityToken=" + mShareableActivityToken + "}";
}
// Using the same method to set and clear values to make sure we don't forget anything
@@ -288,7 +293,7 @@ public class LaunchActivityItem extends ClientTransactionItem {
List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
ActivityOptions activityOptions, boolean isForward, ProfilerInfo profilerInfo,
IBinder assistToken, IActivityClientController activityClientController,
- FixedRotationAdjustments fixedRotationAdjustments) {
+ FixedRotationAdjustments fixedRotationAdjustments, IBinder shareableActivityToken) {
instance.mIntent = intent;
instance.mIdent = ident;
instance.mInfo = info;
@@ -308,5 +313,6 @@ public class LaunchActivityItem extends ClientTransactionItem {
instance.mAssistToken = assistToken;
instance.mActivityClientController = activityClientController;
instance.mFixedRotationAdjustments = fixedRotationAdjustments;
+ instance.mShareableActivityToken = shareableActivityToken;
}
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java
index 9bf3626fe868..9998fbc02d12 100644
--- a/core/java/android/view/contentcapture/ContentCaptureContext.java
+++ b/core/java/android/view/contentcapture/ContentCaptureContext.java
@@ -22,6 +22,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.TaskInfo;
+import android.app.assist.ActivityId;
import android.content.ComponentName;
import android.content.Context;
import android.content.LocusId;
@@ -36,6 +37,8 @@ import com.android.internal.util.Preconditions;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
/**
* Context associated with a {@link ContentCaptureSession} - see {@link ContentCaptureManager} for
* more info.
@@ -99,16 +102,17 @@ public final class ContentCaptureContext implements Parcelable {
// Fields below are set by server when the session starts
private final @Nullable ComponentName mComponentName;
- private final int mTaskId;
private final int mFlags;
private final int mDisplayId;
+ private final ActivityId mActivityId;
// Fields below are set by the service upon "delivery" and are not marshalled in the parcel
private int mParentSessionId = NO_SESSION_ID;
/** @hide */
public ContentCaptureContext(@Nullable ContentCaptureContext clientContext,
- @NonNull ComponentName componentName, int taskId, int displayId, int flags) {
+ @NonNull ActivityId activityId, @NonNull ComponentName componentName, int displayId,
+ int flags) {
if (clientContext != null) {
mHasClientContext = true;
mExtras = clientContext.mExtras;
@@ -118,10 +122,10 @@ public final class ContentCaptureContext implements Parcelable {
mExtras = null;
mId = null;
}
- mComponentName = Preconditions.checkNotNull(componentName);
- mTaskId = taskId;
- mDisplayId = displayId;
+ mComponentName = Objects.requireNonNull(componentName);
mFlags = flags;
+ mDisplayId = displayId;
+ mActivityId = activityId;
}
private ContentCaptureContext(@NonNull Builder builder) {
@@ -130,8 +134,9 @@ public final class ContentCaptureContext implements Parcelable {
mId = builder.mId;
mComponentName = null;
- mTaskId = mFlags = 0;
+ mFlags = 0;
mDisplayId = Display.INVALID_DISPLAY;
+ mActivityId = null;
}
/** @hide */
@@ -140,9 +145,9 @@ public final class ContentCaptureContext implements Parcelable {
mExtras = original.mExtras;
mId = original.mId;
mComponentName = original.mComponentName;
- mTaskId = original.mTaskId;
mFlags = original.mFlags | extraFlags;
mDisplayId = original.mDisplayId;
+ mActivityId = original.mActivityId;
}
/**
@@ -170,7 +175,7 @@ public final class ContentCaptureContext implements Parcelable {
*/
@SystemApi
public int getTaskId() {
- return mTaskId;
+ return mHasClientContext ? 0 : mActivityId.getTaskId();
}
/**
@@ -184,6 +189,18 @@ public final class ContentCaptureContext implements Parcelable {
}
/**
+ * Gets the Activity id information associated with this context, or {@code null} when it is a
+ * child session.
+ *
+ * @hide
+ */
+ @SystemApi
+ @Nullable
+ public ActivityId getActivityId() {
+ return mHasClientContext ? null : mActivityId;
+ }
+
+ /**
* Gets the id of the session that originated this session (through
* {@link ContentCaptureSession#createContentCaptureSession(ContentCaptureContext)}),
* or {@code null} if this is the main session associated with the Activity's {@link Context}.
@@ -309,7 +326,7 @@ public final class ContentCaptureContext implements Parcelable {
if (mId != null) {
pw.print(", id="); mId.dump(pw);
}
- pw.print(", taskId="); pw.print(mTaskId);
+ pw.print(", activityId="); pw.print(mActivityId);
pw.print(", displayId="); pw.print(mDisplayId);
if (mParentSessionId != NO_SESSION_ID) {
pw.print(", parentId="); pw.print(mParentSessionId);
@@ -333,7 +350,7 @@ public final class ContentCaptureContext implements Parcelable {
if (fromServer()) {
builder.append("act=").append(ComponentName.flattenToShortString(mComponentName))
- .append(", taskId=").append(mTaskId)
+ .append(", activityId=").append(mActivityId)
.append(", displayId=").append(mDisplayId)
.append(", flags=").append(mFlags);
} else {
@@ -363,9 +380,9 @@ public final class ContentCaptureContext implements Parcelable {
}
parcel.writeParcelable(mComponentName, flags);
if (fromServer()) {
- parcel.writeInt(mTaskId);
parcel.writeInt(mDisplayId);
parcel.writeInt(mFlags);
+ mActivityId.writeToParcel(parcel, flags);
}
}
@@ -393,11 +410,12 @@ public final class ContentCaptureContext implements Parcelable {
// Client-state only
return clientContext;
} else {
- final int taskId = parcel.readInt();
final int displayId = parcel.readInt();
final int flags = parcel.readInt();
- return new ContentCaptureContext(clientContext, componentName, taskId, displayId,
- flags);
+ final ActivityId activityId = new ActivityId(parcel);
+
+ return new ContentCaptureContext(clientContext, activityId, componentName,
+ displayId, flags);
}
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 46e0306cefc8..9523bcdb8e39 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -435,10 +435,11 @@ public final class ContentCaptureManager {
/** @hide */
@UiThread
public void onActivityCreated(@NonNull IBinder applicationToken,
- @NonNull ComponentName activityComponent) {
+ @NonNull IBinder shareableActivityToken, @NonNull ComponentName activityComponent) {
if (mOptions.lite) return;
synchronized (mLock) {
- getMainContentCaptureSession().start(applicationToken, activityComponent, mFlags);
+ getMainContentCaptureSession().start(applicationToken, shareableActivityToken,
+ activityComponent, mFlags);
}
}
diff --git a/core/java/android/view/contentcapture/IContentCaptureManager.aidl b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
index ef8295c30fdf..b1b443f919d9 100644
--- a/core/java/android/view/contentcapture/IContentCaptureManager.aidl
+++ b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
@@ -44,8 +44,9 @@ oneway interface IContentCaptureManager {
* @param flags Meta flags that enable or disable content capture (see
* {@link IContentCaptureContext#flags}).
*/
- void startSession(IBinder activityToken, in ComponentName componentName,
- int sessionId, int flags, in IResultReceiver result);
+ void startSession(IBinder activityToken, IBinder shareableActivityToken,
+ in ComponentName componentName, int sessionId, int flags,
+ in IResultReceiver result);
/**
* Marks the end of a session for the calling user identified by
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index 3c18b6b89af8..5ca793e3c394 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -123,6 +123,8 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
@Nullable
private IBinder mApplicationToken;
+ @Nullable
+ private IBinder mShareableActivityToken;
@Nullable
private ComponentName mComponentName;
@@ -217,8 +219,8 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
* Starts this session.
*/
@UiThread
- void start(@NonNull IBinder token, @NonNull ComponentName component,
- int flags) {
+ void start(@NonNull IBinder token, @NonNull IBinder shareableActivityToken,
+ @NonNull ComponentName component, int flags) {
if (!isContentCaptureEnabled()) return;
if (sVerbose) {
@@ -237,6 +239,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
}
mState = STATE_WAITING_FOR_SERVER;
mApplicationToken = token;
+ mShareableActivityToken = shareableActivityToken;
mComponentName = component;
if (sVerbose) {
@@ -245,8 +248,8 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
}
try {
- mSystemServerInterface.startSession(mApplicationToken, component, mId, flags,
- mSessionStateReceiver);
+ mSystemServerInterface.startSession(mApplicationToken, mShareableActivityToken,
+ component, mId, flags, mSessionStateReceiver);
} catch (RemoteException e) {
Log.w(TAG, "Error starting session for " + component.flattenToShortString() + ": " + e);
}
@@ -583,6 +586,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
mDisabled.set((newState & STATE_DISABLED) != 0);
// TODO(b/122454205): must reset children (which currently is owned by superclass)
mApplicationToken = null;
+ mShareableActivityToken = null;
mComponentName = null;
mEvents = null;
if (mDirectServiceInterface != null) {
@@ -721,6 +725,10 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
if (mApplicationToken != null) {
pw.print(prefix); pw.print("app token: "); pw.println(mApplicationToken);
}
+ if (mShareableActivityToken != null) {
+ pw.print(prefix); pw.print("sharable activity token: ");
+ pw.println(mShareableActivityToken);
+ }
if (mComponentName != null) {
pw.print(prefix); pw.print("component name: ");
pw.println(mComponentName.flattenToShortString());
diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
index 50b52eb2a0ea..6c8b94129c82 100644
--- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java
@@ -148,13 +148,15 @@ public class ObjectPoolTests {
PersistableBundle persistableBundle = new PersistableBundle();
persistableBundle.putInt("k", 4);
IBinder assistToken = new Binder();
+ IBinder shareableActivityToken = new Binder();
Supplier<LaunchActivityItem> itemSupplier = () -> new LaunchActivityItemBuilder()
.setIntent(intent).setIdent(ident).setInfo(activityInfo).setCurConfig(config())
.setOverrideConfig(overrideConfig).setCompatInfo(compat).setReferrer(referrer)
.setProcState(procState).setState(bundle).setPersistentState(persistableBundle)
.setPendingResults(resultInfoList()).setPendingNewIntents(referrerIntentList())
- .setIsForward(true).setAssistToken(assistToken).build();
+ .setIsForward(true).setAssistToken(assistToken)
+ .setShareableActivityToken(shareableActivityToken).build();
LaunchActivityItem emptyItem = new LaunchActivityItemBuilder().build();
LaunchActivityItem item = itemSupplier.get();
diff --git a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
index 02e75dd76a07..1a06789e729f 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java
@@ -109,6 +109,7 @@ class TestUtils {
private boolean mIsForward;
private ProfilerInfo mProfilerInfo;
private IBinder mAssistToken;
+ private IBinder mShareableActivityToken;
private FixedRotationAdjustments mFixedRotationAdjustments;
LaunchActivityItemBuilder setIntent(Intent intent) {
@@ -196,6 +197,11 @@ class TestUtils {
return this;
}
+ LaunchActivityItemBuilder setShareableActivityToken(IBinder shareableActivityToken) {
+ mShareableActivityToken = shareableActivityToken;
+ return this;
+ }
+
LaunchActivityItemBuilder setFixedRotationAdjustments(FixedRotationAdjustments fra) {
mFixedRotationAdjustments = fra;
return this;
@@ -206,7 +212,8 @@ class TestUtils {
mCurConfig, mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor,
mProcState, mState, mPersistentState, mPendingResults, mPendingNewIntents,
mActivityOptions, mIsForward, mProfilerInfo, mAssistToken,
- null /* activityClientController */, mFixedRotationAdjustments);
+ null /* activityClientController */, mFixedRotationAdjustments,
+ mShareableActivityToken);
}
}
}
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index f6d985b1788f..6f3d7ae5eb3c 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -207,6 +207,7 @@ public class TransactionParcelTests {
.setPendingResults(resultInfoList()).setActivityOptions(ActivityOptions.makeBasic())
.setPendingNewIntents(referrerIntentList()).setIsForward(true)
.setAssistToken(new Binder()).setFixedRotationAdjustments(fixedRotationAdjustments)
+ .setShareableActivityToken(new Binder())
.build();
writeAndPrepareForReading(item);
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureContextTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureContextTest.java
index 4680a640a7ff..ddb6729b55e1 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureContextTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureContextTest.java
@@ -17,14 +17,17 @@ package android.view.contentcapture;
import static com.google.common.truth.Truth.assertThat;
+import android.app.assist.ActivityId;
import android.content.ComponentName;
+import android.os.Binder;
+import android.os.IBinder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/**
- * Unit test for {@link ContentCaptureEvent}.
+ * Unit test for {@link ContentCaptureContext}.
*
* <p>To run it:
* {@code atest FrameworksCoreTests:android.view.contentcapture.ContentCaptureContextTest}
@@ -35,13 +38,17 @@ public class ContentCaptureContextTest {
@Test
public void testConstructorAdditionalFlags() {
final ComponentName componentName = new ComponentName("component", "name");
+ final IBinder token = new Binder();
final ContentCaptureContext ctx = new ContentCaptureContext(/* clientContext= */ null,
- componentName, /* taskId= */ 666, /* displayId= */ 42, /* flags= */ 1);
+ new ActivityId(/* taskId= */ 666, token), componentName, /* displayId= */
+ 42, /* flags= */ 1);
final ContentCaptureContext newCtx = new ContentCaptureContext(ctx, /* extraFlags= */ 2);
assertThat(newCtx.getFlags()).isEqualTo(3);
-
assertThat(newCtx.getActivityComponent()).isEqualTo(componentName);
- assertThat(newCtx.getTaskId()).isEqualTo(666);
+ ActivityId activityId = newCtx.getActivityId();
+ assertThat(activityId).isNotNull();
+ assertThat(activityId.getTaskId()).isEqualTo(666);
+ assertThat(activityId.getToken()).isEqualTo(token);
assertThat(newCtx.getDisplayId()).isEqualTo(42);
assertThat(newCtx.getExtras()).isNull();
assertThat(newCtx.getLocusId()).isNull();
diff --git a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
index d2b20b4298d9..0808186b21c5 100644
--- a/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
+++ b/core/tests/mockingcoretests/src/android/app/activity/ActivityThreadClientTest.java
@@ -298,7 +298,7 @@ public class ActivityThreadClientTest {
null /* pendingResults */, null /* pendingNewIntents */,
null /* activityOptions */, true /* isForward */, null /* profilerInfo */,
mThread /* client */, null /* asssitToken */,
- null /* fixedRotationAdjustments */);
+ null /* fixedRotationAdjustments */, null /* shareableActivityToken */);
}
@Override
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 220f87db8bd4..02930dc238ba 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -88,7 +88,6 @@ import com.android.internal.infra.AbstractRemoteService;
import com.android.internal.infra.GlobalWhitelistState;
import com.android.internal.os.IResultReceiver;
import com.android.internal.util.DumpUtils;
-import com.android.internal.util.Preconditions;
import com.android.server.LocalServices;
import com.android.server.infra.AbstractMasterSystemService;
import com.android.server.infra.FrameworkResourcesServiceNameResolver;
@@ -101,6 +100,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -602,10 +602,11 @@ public final class ContentCaptureManagerService extends
@Override
public void startSession(@NonNull IBinder activityToken,
- @NonNull ComponentName componentName, int sessionId, int flags,
- @NonNull IResultReceiver result) {
- Preconditions.checkNotNull(activityToken);
- Preconditions.checkNotNull(sessionId);
+ @NonNull IBinder shareableActivityToken, @NonNull ComponentName componentName,
+ int sessionId, int flags, @NonNull IResultReceiver result) {
+ Objects.requireNonNull(activityToken);
+ Objects.requireNonNull(shareableActivityToken);
+ Objects.requireNonNull(sessionId);
final int userId = UserHandle.getCallingUserId();
final ActivityPresentationInfo activityPresentationInfo = getAmInternal()
@@ -617,14 +618,14 @@ public final class ContentCaptureManagerService extends
setClientState(result, STATE_DISABLED, /* binder= */ null);
return;
}
- service.startSessionLocked(activityToken, activityPresentationInfo, sessionId,
- Binder.getCallingUid(), flags, result);
+ service.startSessionLocked(activityToken, shareableActivityToken,
+ activityPresentationInfo, sessionId, Binder.getCallingUid(), flags, result);
}
}
@Override
public void finishSession(int sessionId) {
- Preconditions.checkNotNull(sessionId);
+ Objects.requireNonNull(sessionId);
final int userId = UserHandle.getCallingUserId();
synchronized (mLock) {
@@ -650,7 +651,7 @@ public final class ContentCaptureManagerService extends
@Override
public void removeData(@NonNull DataRemovalRequest request) {
- Preconditions.checkNotNull(request);
+ Objects.requireNonNull(request);
assertCalledByPackageOwner(request.getPackageName());
final int userId = UserHandle.getCallingUserId();
@@ -663,8 +664,8 @@ public final class ContentCaptureManagerService extends
@Override
public void shareData(@NonNull DataShareRequest request,
@NonNull IDataShareWriteAdapter clientAdapter) {
- Preconditions.checkNotNull(request);
- Preconditions.checkNotNull(clientAdapter);
+ Objects.requireNonNull(request);
+ Objects.requireNonNull(clientAdapter);
assertCalledByPackageOwner(request.getPackageName());
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index ea68e190ff1f..53cdc330cf9e 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -35,6 +35,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
+import android.app.assist.ActivityId;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.content.ComponentName;
@@ -241,6 +242,7 @@ final class ContentCapturePerUserService
@GuardedBy("mLock")
public void startSessionLocked(@NonNull IBinder activityToken,
+ @NonNull IBinder shareableActivityToken,
@NonNull ActivityPresentationInfo activityPresentationInfo, int sessionId, int uid,
int flags, @NonNull IResultReceiver clientReceiver) {
if (activityPresentationInfo == null) {
@@ -340,8 +342,8 @@ final class ContentCapturePerUserService
mRemoteService.ensureBoundLocked();
final ContentCaptureServerSession newSession = new ContentCaptureServerSession(mLock,
- activityToken, this, componentName, clientReceiver, taskId, displayId, sessionId,
- uid, flags);
+ activityToken, new ActivityId(taskId, shareableActivityToken), this, componentName,
+ clientReceiver, taskId, displayId, sessionId, uid, flags);
if (mMaster.verbose) {
Slog.v(TAG, "startSession(): new session for "
+ ComponentName.flattenToShortString(componentName) + " and id " + sessionId);
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
index 06ab426c6698..9f3045e68550 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
@@ -25,6 +25,7 @@ import static android.view.contentcapture.ContentCaptureSession.STATE_SERVICE_RE
import static android.view.contentcapture.ContentCaptureSession.STATE_SERVICE_UPDATING;
import android.annotation.NonNull;
+import android.app.assist.ActivityId;
import android.content.ComponentName;
import android.os.Bundle;
import android.os.IBinder;
@@ -75,9 +76,9 @@ final class ContentCaptureServerSession {
public final ComponentName appComponentName;
ContentCaptureServerSession(@NonNull Object lock, @NonNull IBinder activityToken,
- @NonNull ContentCapturePerUserService service, @NonNull ComponentName appComponentName,
- @NonNull IResultReceiver sessionStateReceiver, int taskId, int displayId, int sessionId,
- int uid, int flags) {
+ @NonNull ActivityId activityId, @NonNull ContentCapturePerUserService service,
+ @NonNull ComponentName appComponentName, @NonNull IResultReceiver sessionStateReceiver,
+ int taskId, int displayId, int sessionId, int uid, int flags) {
Preconditions.checkArgument(sessionId != NO_SESSION_ID);
mLock = lock;
mActivityToken = activityToken;
@@ -86,7 +87,7 @@ final class ContentCaptureServerSession {
mId = sessionId;
mUid = uid;
mContentCaptureContext = new ContentCaptureContext(/* clientContext= */ null,
- appComponentName, taskId, displayId, flags);
+ activityId, appComponentName, displayId, flags);
mSessionStateReceiver = sessionStateReceiver;
try {
sessionStateReceiver.asBinder().linkToDeath(() -> onClientDeath(), 0);
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index c1fe4887da57..33abcb478c77 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -763,6 +763,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Token for targeting this activity for assist purposes.
final Binder assistToken = new Binder();
+ // A reusable token for other purposes, e.g. content capture, translation. It shouldn't be used
+ // without security checks
+ final Binder shareableActivityToken = new Binder();
+
// Tracking cookie for the launch of this activity and it's task.
IBinder mLaunchCookie;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 94379b1f230e..e858fe1034b1 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -348,13 +348,16 @@ public abstract class ActivityTaskManagerInternal {
public final class ActivityTokens {
private final @NonNull IBinder mActivityToken;
private final @NonNull IBinder mAssistToken;
+ private final @NonNull IBinder mShareableActivityToken;
private final @NonNull IApplicationThread mAppThread;
public ActivityTokens(@NonNull IBinder activityToken,
- @NonNull IBinder assistToken, @NonNull IApplicationThread appThread) {
+ @NonNull IBinder assistToken, @NonNull IApplicationThread appThread,
+ @NonNull IBinder shareableActivityToken) {
mActivityToken = activityToken;
mAssistToken = assistToken;
mAppThread = appThread;
+ mShareableActivityToken = shareableActivityToken;
}
/**
@@ -372,6 +375,13 @@ public abstract class ActivityTaskManagerInternal {
}
/**
+ * @return The sharable activity token..
+ */
+ public @NonNull IBinder getShareableActivityToken() {
+ return mShareableActivityToken;
+ }
+
+ /**
* @return The assist token.
*/
public @NonNull IApplicationThread getApplicationThread() {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index db499158a5d9..a874dee2c768 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -5550,7 +5550,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return null;
}
return new ActivityTokens(activity.appToken, activity.assistToken,
- activity.app.getThread());
+ activity.app.getThread(), activity.shareableActivityToken);
}
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index bf2aae8867ba..bb0f1f0b6f5f 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -825,7 +825,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
r.getSavedState(), r.getPersistentSavedState(), results, newIntents,
r.takeOptions(), dc.isNextTransitionForward(),
proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
- r.createFixedRotationAdjustmentsIfNeeded()));
+ r.createFixedRotationAdjustmentsIfNeeded(), r.shareableActivityToken));
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;