Use noteOpNoThrow instead of checkOpNoThrow in AssistDataRequester
To audit data access and verify the uid and package are consistent,
use noteOpNoThrow instead of checkOpNoThrow.
Bug: 187439908
Test: atest AssistDataRequesterTest
Test: atest CtsVoiceInteractionTestCases
Test: atest CtsAssistTestCases
Change-Id: Ib48040b5b55be09958da4398f4d663908573568c
diff --git a/boot/hiddenapi/hiddenapi-max-target-r-loprio.txt b/boot/hiddenapi/hiddenapi-max-target-r-loprio.txt
index dbc3b51..f5184e7 100644
--- a/boot/hiddenapi/hiddenapi-max-target-r-loprio.txt
+++ b/boot/hiddenapi/hiddenapi-max-target-r-loprio.txt
@@ -39,7 +39,6 @@
Lcom/android/ims/internal/uce/presence/IPresenceService$Stub;-><init>()V
Lcom/android/ims/internal/uce/uceservice/IUceListener$Stub;-><init>()V
Lcom/android/ims/internal/uce/uceservice/IUceService$Stub;-><init>()V
-Lcom/android/internal/app/IVoiceInteractionManagerService$Stub$Proxy;->showSessionFromSession(Landroid/os/IBinder;Landroid/os/Bundle;I)Z
Lcom/android/internal/appwidget/IAppWidgetService$Stub;->TRANSACTION_bindAppWidgetId:I
Lcom/android/internal/telephony/ITelephony$Stub;->DESCRIPTOR:Ljava/lang/String;
Lcom/android/internal/telephony/ITelephony$Stub;->TRANSACTION_dial:I
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index dc6825c..c935637 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -230,7 +230,7 @@
in IBinder activityToken, int flags);
boolean isAssistDataAllowedOnCurrentActivity();
boolean requestAssistDataForTask(in IAssistDataReceiver receiver, int taskId,
- in String callingPackageName);
+ in String callingPackageName, String callingAttributionTag);
/**
* Notify the system that the keyguard is going away.
diff --git a/core/java/android/service/voice/VoiceInteractionManagerInternal.java b/core/java/android/service/voice/VoiceInteractionManagerInternal.java
index b20dccc..387708c 100644
--- a/core/java/android/service/voice/VoiceInteractionManagerInternal.java
+++ b/core/java/android/service/voice/VoiceInteractionManagerInternal.java
@@ -16,6 +16,7 @@
package android.service.voice;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
import android.os.IBinder;
@@ -32,9 +33,12 @@
* Start a new voice interaction session when requested from within an activity
* by Activity.startLocalVoiceInteraction()
* @param callingActivity The binder token representing the calling activity.
- * @param options
+ * @param attributionTag The attribution tag of the calling context or {@code null} for default
+ * attribution
+ * @param options A Bundle of private arguments to the current voice interaction service
*/
- public abstract void startLocalVoiceInteraction(IBinder callingActivity, Bundle options);
+ public abstract void startLocalVoiceInteraction(@NonNull IBinder callingActivity,
+ @Nullable String attributionTag, @NonNull Bundle options);
/**
* Returns whether the currently selected voice interaction service supports local voice
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index 1170237..1b46107 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -242,7 +242,7 @@
throw new IllegalStateException("Not available until onReady() is called");
}
try {
- mSystemService.showSession(args, flags);
+ mSystemService.showSession(args, flags, getAttributionTag());
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 42500b4..95d4b0a 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -1384,7 +1384,8 @@
throw new IllegalStateException("Can't call before onCreate()");
}
try {
- mSystemService.showSessionFromSession(mToken, args, flags);
+ mSystemService.showSessionFromSession(mToken, args, flags,
+ mContext.getAttributionTag());
} catch (RemoteException e) {
}
}
diff --git a/core/java/com/android/internal/app/AssistUtils.java b/core/java/com/android/internal/app/AssistUtils.java
index c056e26..f843318 100644
--- a/core/java/com/android/internal/app/AssistUtils.java
+++ b/core/java/com/android/internal/app/AssistUtils.java
@@ -17,6 +17,7 @@
package com.android.internal.app;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
@@ -67,12 +68,53 @@
ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
}
- public boolean showSessionForActiveService(Bundle args, int sourceFlags,
- IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken) {
+ /**
+ * Shows the session for the currently active service. Used to start a new session from system
+ * affordances.
+ *
+ * @param args the bundle to pass as arguments to the voice interaction session
+ * @param sourceFlags flags indicating the source of this show
+ * @param showCallback optional callback to be notified when the session was shown
+ * @param activityToken optional token of activity that needs to be on top
+ *
+ * @deprecated Use {@link #showSessionForActiveService(Bundle, int, String,
+ * IVoiceInteractionSessionShowCallback, IBinder)} instead
+ */
+ @Deprecated
+ public boolean showSessionForActiveService(@NonNull Bundle args, int sourceFlags,
+ @Nullable IVoiceInteractionSessionShowCallback showCallback,
+ @Nullable IBinder activityToken) {
+ return showSessionForActiveServiceInternal(args, sourceFlags, /* attributionTag */ null,
+ showCallback, activityToken);
+ }
+
+ /**
+ * Shows the session for the currently active service. Used to start a new session from system
+ * affordances.
+ *
+ * @param args the bundle to pass as arguments to the voice interaction session
+ * @param sourceFlags flags indicating the source of this show
+ * @param attributionTag the attribution tag of the calling context or {@code null} for default
+ * attribution
+ * @param showCallback optional callback to be notified when the session was shown
+ * @param activityToken optional token of activity that needs to be on top
+ */
+ public boolean showSessionForActiveService(@NonNull Bundle args, int sourceFlags,
+ @Nullable String attributionTag,
+ @Nullable IVoiceInteractionSessionShowCallback showCallback,
+ @Nullable IBinder activityToken) {
+ return showSessionForActiveServiceInternal(args, sourceFlags, attributionTag, showCallback,
+ activityToken);
+ }
+
+ private boolean showSessionForActiveServiceInternal(@NonNull Bundle args, int sourceFlags,
+ @Nullable String attributionTag,
+ @Nullable IVoiceInteractionSessionShowCallback showCallback,
+ @Nullable IBinder activityToken) {
try {
if (mVoiceInteractionManagerService != null) {
return mVoiceInteractionManagerService.showSessionForActiveService(args,
- sourceFlags, showCallback, activityToken);
+ sourceFlags, attributionTag, showCallback, activityToken);
}
} catch (RemoteException e) {
Log.w(TAG, "Failed to call showSessionForActiveService", e);
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index 4b01357..83bf801 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -39,15 +39,16 @@
import android.service.voice.IMicrophoneHotwordDetectionVoiceInteractionCallback;
interface IVoiceInteractionManagerService {
- void showSession(in Bundle sessionArgs, int flags);
+ void showSession(in Bundle sessionArgs, int flags, String attributionTag);
boolean deliverNewSession(IBinder token, IVoiceInteractionSession session,
IVoiceInteractor interactor);
- boolean showSessionFromSession(IBinder token, in Bundle sessionArgs, int flags);
+ boolean showSessionFromSession(IBinder token, in Bundle sessionArgs, int flags,
+ String attributionTag);
boolean hideSessionFromSession(IBinder token);
int startVoiceActivity(IBinder token, in Intent intent, String resolvedType,
- String callingFeatureId);
+ String attributionTag);
int startAssistantActivity(IBinder token, in Intent intent, String resolvedType,
- String callingFeatureId);
+ String attributionTag);
void setKeepAwake(IBinder token, boolean keepAwake);
void closeSystemDialogs(IBinder token);
void finish(IBinder token);
@@ -125,12 +126,14 @@
*
* @param args the bundle to pass as arguments to the voice interaction session
* @param sourceFlags flags indicating the source of this show
+ * @param attributionTag the attribution tag of the calling context or {@code null} for default
+ * attribution
* @param showCallback optional callback to be notified when the session was shown
* @param activityToken optional token of activity that needs to be on top
* @RequiresPermission Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE
*/
@EnforcePermission("ACCESS_VOICE_INTERACTION_SERVICE")
- boolean showSessionForActiveService(in Bundle args, int sourceFlags,
+ boolean showSessionForActiveService(in Bundle args, int sourceFlags, String attributionTag,
IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken);
/**
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
index 916526d..ee30972 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityManagerWrapper.java
@@ -19,7 +19,6 @@
import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
-import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
import static android.app.ActivityTaskManager.getService;
import android.annotation.NonNull;
@@ -27,7 +26,6 @@
import android.app.Activity;
import android.app.ActivityClient;
import android.app.ActivityManager;
-import android.app.ActivityManager.RecentTaskInfo;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
@@ -337,7 +335,8 @@
* Shows a voice session identified by {@code token}
* @return true if the session was shown, false otherwise
*/
- public boolean showVoiceSession(IBinder token, Bundle args, int flags) {
+ public boolean showVoiceSession(@NonNull IBinder token, @NonNull Bundle args, int flags,
+ @Nullable String attributionTag) {
IVoiceInteractionManagerService service = IVoiceInteractionManagerService.Stub.asInterface(
ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
if (service == null) {
@@ -346,7 +345,7 @@
args.putLong(INVOCATION_TIME_MS_KEY, SystemClock.elapsedRealtime());
try {
- return service.showSessionFromSession(token, args, flags);
+ return service.showSessionFromSession(token, args, flags, attributionTag);
} catch (RemoteException e) {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 7c2673c..57ffdab 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -310,7 +310,8 @@
private void startVoiceInteractor(Bundle args) {
mAssistUtils.showSessionForActiveService(args,
- VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE, null, null);
+ VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE, mContext.getAttributionTag(),
+ null, null);
}
public void launchVoiceAssistFromKeyguard() {
diff --git a/services/core/java/com/android/server/am/AssistDataRequester.java b/services/core/java/com/android/server/am/AssistDataRequester.java
index 98ad81d..98129ed 100644
--- a/services/core/java/com/android/server/am/AssistDataRequester.java
+++ b/services/core/java/com/android/server/am/AssistDataRequester.java
@@ -23,6 +23,8 @@
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityTaskManager;
import android.app.AppOpsManager;
import android.app.IActivityTaskManager;
@@ -41,6 +43,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
/**
* Helper class to asynchronously fetch the assist data and screenshot from the current running
@@ -141,50 +144,35 @@
}
/**
- * Request that autofill data be loaded asynchronously. The resulting data will be provided
- * through the {@link AssistDataRequesterCallbacks}.
- *
- * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, boolean, int,
- * String, boolean)}.
- */
- public void requestAutofillData(List<IBinder> activityTokens, int callingUid,
- String callingPackage) {
- requestData(activityTokens, true /* requestAutofillData */,
- true /* fetchData */, false /* fetchScreenshot */,
- true /* fetchStructure */, true /* allowFetchData */,
- false /* allowFetchScreenshot */, false /* ignoreTopActivityCheck */, callingUid,
- callingPackage);
- }
-
- /**
* Request that assist data be loaded asynchronously. The resulting data will be provided
* through the {@link AssistDataRequesterCallbacks}.
*
- * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, boolean, int,
- * String, boolean)}.
+ * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, boolean, boolean,
+ * int, String, String)}.
*/
- public void requestAssistData(List<IBinder> activityTokens, final boolean fetchData,
+ public void requestAssistData(@NonNull List<IBinder> activityTokens, final boolean fetchData,
final boolean fetchScreenshot, boolean allowFetchData, boolean allowFetchScreenshot,
- int callingUid, String callingPackage) {
+ int callingUid, @NonNull String callingPackage,
+ @Nullable String callingAttributionTag) {
requestAssistData(activityTokens, fetchData, fetchScreenshot, true /* fetchStructure */,
allowFetchData, allowFetchScreenshot, false /* ignoreTopActivityCheck */,
- callingUid, callingPackage);
+ callingUid, callingPackage, callingAttributionTag);
}
/**
* Request that assist data be loaded asynchronously. The resulting data will be provided
* through the {@link AssistDataRequesterCallbacks}.
*
- * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, boolean, int,
- * String, boolean)}.
+ * See {@link #requestData(List, boolean, boolean, boolean, boolean, boolean, boolean, boolean,
+ * int, String, String)}.
*/
- public void requestAssistData(List<IBinder> activityTokens, final boolean fetchData,
+ public void requestAssistData(@NonNull List<IBinder> activityTokens, final boolean fetchData,
final boolean fetchScreenshot, final boolean fetchStructure, boolean allowFetchData,
boolean allowFetchScreenshot, boolean ignoreTopActivityCheck, int callingUid,
- String callingPackage) {
+ @NonNull String callingPackage, @Nullable String callingAttributionTag) {
requestData(activityTokens, false /* requestAutofillData */, fetchData, fetchScreenshot,
fetchStructure, allowFetchData, allowFetchScreenshot, ignoreTopActivityCheck,
- callingUid, callingPackage);
+ callingUid, callingPackage, callingAttributionTag);
}
/**
@@ -208,14 +196,22 @@
* requester is allowed to fetch the assist screenshot
* @param ignoreTopActivityCheck overrides the check for whether the activity is in focus when
* making the request. Used when passing an activity from Recents.
+ * @param callingUid the uid of the real caller
+ * @param callingPackage the package name of the real caller
+ * @param callingAttributionTag The {@link Context#createAttributionContext attribution tag}
+ * of the calling context or {@code null} for default attribution
*/
- private void requestData(List<IBinder> activityTokens, final boolean requestAutofillData,
- final boolean fetchData, final boolean fetchScreenshot, final boolean fetchStructure,
- boolean allowFetchData, boolean allowFetchScreenshot, boolean ignoreTopActivityCheck,
- int callingUid, String callingPackage) {
+ private void requestData(@NonNull List<IBinder> activityTokens,
+ final boolean requestAutofillData, final boolean fetchData,
+ final boolean fetchScreenshot, final boolean fetchStructure, boolean allowFetchData,
+ boolean allowFetchScreenshot, boolean ignoreTopActivityCheck, int callingUid,
+ @NonNull String callingPackage, @Nullable String callingAttributionTag) {
// TODO(b/34090158): Known issue, if the assist data is not allowed on the current activity,
// then no assist data is requested for any of the other activities
+ Objects.requireNonNull(activityTokens);
+ Objects.requireNonNull(callingPackage);
+
// Early exit if there are no activity to fetch for
if (activityTokens.isEmpty()) {
// No activities, just dispatch request-complete
@@ -241,8 +237,9 @@
mAssistScreenshot.clear();
if (fetchData) {
- if (mAppOpsManager.checkOpNoThrow(mRequestStructureAppOps, callingUid, callingPackage)
- == MODE_ALLOWED && allowFetchData) {
+ if (mAppOpsManager.noteOpNoThrow(mRequestStructureAppOps, callingUid,
+ callingPackage, callingAttributionTag, /* message */ null) == MODE_ALLOWED
+ && allowFetchData) {
final int numActivities = activityTokens.size();
for (int i = 0; i < numActivities; i++) {
IBinder topActivity = activityTokens.get(i);
@@ -291,8 +288,9 @@
}
if (fetchScreenshot) {
- if (mAppOpsManager.checkOpNoThrow(mRequestScreenshotAppOps, callingUid, callingPackage)
- == MODE_ALLOWED && allowFetchScreenshot) {
+ if (mAppOpsManager.noteOpNoThrow(mRequestScreenshotAppOps, callingUid,
+ callingPackage, callingAttributionTag, /* message */ null) == MODE_ALLOWED
+ && allowFetchScreenshot) {
try {
MetricsLogger.count(mContext, "assist_with_screen", 1);
mPendingScreenshotCount++;
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 1ccdaf7..8f0cf2f 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -1005,6 +1005,7 @@
public boolean showAssistFromActivity(IBinder token, Bundle args) {
final long ident = Binder.clearCallingIdentity();
try {
+ final String callingAttributionTag;
synchronized (mGlobalLock) {
final ActivityRecord caller = ActivityRecord.forTokenLocked(token);
final Task topRootTask = mService.getTopDisplayFocusedRootTask();
@@ -1020,9 +1021,10 @@
+ " is not visible");
return false;
}
+ callingAttributionTag = top.launchedFromFeatureId;
}
return mAssistUtils.showSessionForActiveService(args, SHOW_SOURCE_APPLICATION,
- null /* showCallback */, token);
+ callingAttributionTag, null /* showCallback */, token);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -1039,6 +1041,7 @@
@Override
public void startLocalVoiceInteraction(IBinder callingActivity, Bundle options) {
Slog.i(TAG, "Activity tried to startLocalVoiceInteraction");
+ final String callingAttributionTag;
synchronized (mGlobalLock) {
final Task topRootTask = mService.getTopDisplayFocusedRootTask();
final ActivityRecord activity = topRootTask != null
@@ -1056,9 +1059,10 @@
return;
}
activity.pendingVoiceInteractionStart = true;
+ callingAttributionTag = activity.launchedFromFeatureId;
}
LocalServices.getService(VoiceInteractionManagerInternal.class)
- .startLocalVoiceInteraction(callingActivity, options);
+ .startLocalVoiceInteraction(callingActivity, callingAttributionTag, options);
}
@Override
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 6de1b95..8014f82 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2962,7 +2962,7 @@
@Override
public boolean requestAssistDataForTask(IAssistDataReceiver receiver, int taskId,
- String callingPackageName) {
+ String callingPackageName, @Nullable String callingAttributionTag) {
mAmInternal.enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO,
"requestAssistDataForTask()");
final long callingId = Binder.clearCallingIdentity();
@@ -2989,7 +2989,7 @@
requester.requestAssistData(topActivityToken, true /* fetchData */,
false /* fetchScreenshot */, false /* fetchStructure */, true /* allowFetchData */,
false /* allowFetchScreenshot*/, true /* ignoreFocusCheck */,
- Binder.getCallingUid(), callingPackageName);
+ Binder.getCallingUid(), callingPackageName, callingAttributionTag);
return true;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java b/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
index 2e85897..06b4ad9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
@@ -87,6 +87,7 @@
private static final int TEST_UID = 0;
private static final String TEST_PACKAGE = "";
+ private static final String TEST_ATTRIBUTION_TAG = "";
private AssistDataRequester mDataRequester;
private Callbacks mCallbacks;
@@ -148,9 +149,9 @@
boolean assistScreenshotAllowed) throws Exception {
doReturn(currentActivityAssistAllowed).when(mAtm).isAssistDataAllowedOnCurrentActivity();
doReturn(assistStructureAllowed ? MODE_ALLOWED : MODE_ERRORED).when(mAppOpsManager)
- .checkOpNoThrow(eq(OP_ASSIST_STRUCTURE), anyInt(), anyString());
+ .noteOpNoThrow(eq(OP_ASSIST_STRUCTURE), anyInt(), anyString(), any(), any());
doReturn(assistScreenshotAllowed ? MODE_ALLOWED : MODE_ERRORED).when(mAppOpsManager)
- .checkOpNoThrow(eq(OP_ASSIST_SCREENSHOT), anyInt(), anyString());
+ .noteOpNoThrow(eq(OP_ASSIST_SCREENSHOT), anyInt(), anyString(), any(), any());
}
@Test
@@ -160,7 +161,8 @@
CALLER_ASSIST_SCREENSHOT_ALLOWED);
mDataRequester.requestAssistData(createActivityList(5), FETCH_DATA, FETCH_SCREENSHOTS,
- ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE);
+ ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE,
+ TEST_ATTRIBUTION_TAG);
assertReceivedDataCount(5, 5, 1, 1);
}
@@ -170,7 +172,8 @@
CALLER_ASSIST_SCREENSHOT_ALLOWED);
mDataRequester.requestAssistData(createActivityList(0), FETCH_DATA, FETCH_SCREENSHOTS,
- ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE);
+ ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE,
+ TEST_ATTRIBUTION_TAG);
assertReceivedDataCount(0, 0, 0, 0);
}
@@ -180,7 +183,8 @@
CALLER_ASSIST_SCREENSHOT_ALLOWED);
mDataRequester.requestAssistData(createActivityList(5), FETCH_DATA, FETCH_SCREENSHOTS,
- ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE);
+ ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE,
+ TEST_ATTRIBUTION_TAG);
assertReceivedDataCount(0, 1, 0, 1);
}
@@ -191,7 +195,8 @@
mCallbacks.mCanHandleReceivedData = false;
mDataRequester.requestAssistData(createActivityList(5), FETCH_DATA, FETCH_SCREENSHOTS,
- ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE);
+ ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE,
+ TEST_ATTRIBUTION_TAG);
assertEquals(5, mDataRequester.getPendingDataCount());
assertEquals(1, mDataRequester.getPendingScreenshotCount());
mGate.countDown();
@@ -226,7 +231,8 @@
CALLER_ASSIST_SCREENSHOT_ALLOWED);
mDataRequester.requestAssistData(createActivityList(5), !FETCH_DATA, FETCH_SCREENSHOTS,
- ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE);
+ ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE,
+ TEST_ATTRIBUTION_TAG);
assertReceivedDataCount(0, 0, 0, 1);
}
@@ -236,7 +242,8 @@
CALLER_ASSIST_SCREENSHOT_ALLOWED);
mDataRequester.requestAssistData(createActivityList(5), FETCH_DATA, FETCH_SCREENSHOTS,
- ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE);
+ ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE,
+ TEST_ATTRIBUTION_TAG);
// Expect a single null data when the appops is denied
assertReceivedDataCount(0, 1, 0, 1);
}
@@ -249,7 +256,8 @@
anyBoolean(), anyBoolean());
mDataRequester.requestAssistData(createActivityList(5), FETCH_DATA, FETCH_SCREENSHOTS,
- ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE);
+ ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE,
+ TEST_ATTRIBUTION_TAG);
// Expect a single null data when requestAssistContextExtras() fails
assertReceivedDataCount(0, 1, 0, 1);
}
@@ -261,7 +269,8 @@
CALLER_ASSIST_SCREENSHOT_ALLOWED);
mDataRequester.requestAssistData(createActivityList(5), FETCH_DATA, !FETCH_SCREENSHOTS,
- ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE);
+ ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE,
+ TEST_ATTRIBUTION_TAG);
assertReceivedDataCount(5, 5, 0, 0);
}
@@ -272,7 +281,8 @@
!CALLER_ASSIST_SCREENSHOT_ALLOWED);
mDataRequester.requestAssistData(createActivityList(5), FETCH_DATA, FETCH_SCREENSHOTS,
- ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE);
+ ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE,
+ TEST_ATTRIBUTION_TAG);
// Expect a single null screenshot when the appops is denied
assertReceivedDataCount(5, 5, 0, 1);
}
@@ -284,7 +294,8 @@
mCallbacks.mCanHandleReceivedData = false;
mDataRequester.requestAssistData(createActivityList(5), FETCH_DATA, FETCH_SCREENSHOTS,
- ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE);
+ ALLOW_FETCH_DATA, ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE,
+ TEST_ATTRIBUTION_TAG);
mGate.countDown();
waitForIdle(mHandler);
assertThat(mCallbacks.mReceivedData).isEmpty();
@@ -297,7 +308,8 @@
CALLER_ASSIST_SCREENSHOT_ALLOWED);
mDataRequester.requestAssistData(createActivityList(5), FETCH_DATA, FETCH_SCREENSHOTS,
- !ALLOW_FETCH_DATA, !ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE);
+ !ALLOW_FETCH_DATA, !ALLOW_FETCH_SCREENSHOTS, TEST_UID, TEST_PACKAGE,
+ TEST_ATTRIBUTION_TAG);
assertReceivedDataCount(0, 1, 0, 1);
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 7699262..e18c7ec 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -223,12 +223,13 @@
class LocalService extends VoiceInteractionManagerInternal {
@Override
- public void startLocalVoiceInteraction(IBinder callingActivity, Bundle options) {
+ public void startLocalVoiceInteraction(@NonNull IBinder callingActivity,
+ @Nullable String attributionTag, @NonNull Bundle options) {
if (DEBUG) {
Slog.i(TAG, "startLocalVoiceInteraction " + callingActivity);
}
VoiceInteractionManagerService.this.mServiceStub.startLocalVoiceInteraction(
- callingActivity, options);
+ callingActivity, attributionTag, options);
}
@Override
@@ -383,14 +384,15 @@
}
// TODO: VI Make sure the caller is the current user or profile
- void startLocalVoiceInteraction(final IBinder token, Bundle options) {
+ void startLocalVoiceInteraction(@NonNull final IBinder token,
+ @Nullable String attributionTag, @NonNull Bundle options) {
if (mImpl == null) return;
final int callingUid = Binder.getCallingUid();
final long caller = Binder.clearCallingIdentity();
try {
mImpl.showSessionLocked(options,
- VoiceInteractionSession.SHOW_SOURCE_ACTIVITY,
+ VoiceInteractionSession.SHOW_SOURCE_ACTIVITY, attributionTag,
new IVoiceInteractionSessionShowCallback.Stub() {
@Override
public void onFailed() {
@@ -898,13 +900,13 @@
}
@Override
- public void showSession(Bundle args, int flags) {
+ public void showSession(@NonNull Bundle args, int flags, @Nullable String attributionTag) {
synchronized (this) {
enforceIsCurrentVoiceInteractionService();
final long caller = Binder.clearCallingIdentity();
try {
- mImpl.showSessionLocked(args, flags, null, null);
+ mImpl.showSessionLocked(args, flags, attributionTag, null, null);
} finally {
Binder.restoreCallingIdentity(caller);
}
@@ -929,7 +931,8 @@
}
@Override
- public boolean showSessionFromSession(IBinder token, Bundle sessionArgs, int flags) {
+ public boolean showSessionFromSession(@NonNull IBinder token, @NonNull Bundle sessionArgs,
+ int flags, @Nullable String attributionTag) {
synchronized (this) {
if (mImpl == null) {
Slog.w(TAG, "showSessionFromSession without running voice interaction service");
@@ -937,7 +940,7 @@
}
final long caller = Binder.clearCallingIdentity();
try {
- return mImpl.showSessionLocked(sessionArgs, flags, null, null);
+ return mImpl.showSessionLocked(sessionArgs, flags, attributionTag, null, null);
} finally {
Binder.restoreCallingIdentity(caller);
}
@@ -961,8 +964,8 @@
}
@Override
- public int startVoiceActivity(IBinder token, Intent intent, String resolvedType,
- String callingFeatureId) {
+ public int startVoiceActivity(@NonNull IBinder token, @NonNull Intent intent,
+ @Nullable String resolvedType, @Nullable String attributionTag) {
synchronized (this) {
if (mImpl == null) {
Slog.w(TAG, "startVoiceActivity without running voice interaction service");
@@ -980,8 +983,8 @@
} else {
Slog.w(TAG, "Cannot find ActivityInfo in startVoiceActivity.");
}
- return mImpl.startVoiceActivityLocked(
- callingFeatureId, callingPid, callingUid, token, intent, resolvedType);
+ return mImpl.startVoiceActivityLocked(attributionTag, callingPid, callingUid,
+ token, intent, resolvedType);
} finally {
Binder.restoreCallingIdentity(caller);
}
@@ -989,8 +992,8 @@
}
@Override
- public int startAssistantActivity(IBinder token, Intent intent, String resolvedType,
- String callingFeatureId) {
+ public int startAssistantActivity(@NonNull IBinder token, @NonNull Intent intent,
+ @Nullable String resolvedType, @Nullable String attributionTag) {
synchronized (this) {
if (mImpl == null) {
Slog.w(TAG, "startAssistantActivity without running voice interaction service");
@@ -1000,7 +1003,7 @@
final int callingUid = Binder.getCallingUid();
final long caller = Binder.clearCallingIdentity();
try {
- return mImpl.startAssistantActivityLocked(callingFeatureId, callingPid,
+ return mImpl.startAssistantActivityLocked(attributionTag, callingPid,
callingUid, token, intent, resolvedType);
} finally {
Binder.restoreCallingIdentity(caller);
@@ -1669,8 +1672,10 @@
@android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE)
@Override
- public boolean showSessionForActiveService(Bundle args, int sourceFlags,
- IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken) {
+ public boolean showSessionForActiveService(@NonNull Bundle args, int sourceFlags,
+ @Nullable String attributionTag,
+ @Nullable IVoiceInteractionSessionShowCallback showCallback,
+ @Nullable IBinder activityToken) {
if (DEBUG_USER) Slog.d(TAG, "showSessionForActiveService()");
synchronized (this) {
@@ -1691,7 +1696,7 @@
sourceFlags
| VoiceInteractionSession.SHOW_WITH_ASSIST
| VoiceInteractionSession.SHOW_WITH_SCREENSHOT,
- showCallback, activityToken);
+ attributionTag, showCallback, activityToken);
} finally {
Binder.restoreCallingIdentity(caller);
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index b9793ca..9f66059 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -244,8 +244,10 @@
/* direct= */ true);
}
- public boolean showSessionLocked(Bundle args, int flags,
- IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken) {
+ public boolean showSessionLocked(@NonNull Bundle args, int flags,
+ @Nullable String attributionTag,
+ @Nullable IVoiceInteractionSessionShowCallback showCallback,
+ @Nullable IBinder activityToken) {
if (mActiveSession == null) {
mActiveSession = new VoiceInteractionSessionConnection(mServiceStub,
mSessionComponentName, mUser, mContext, this,
@@ -269,8 +271,8 @@
} else {
visibleActivities = allVisibleActivities;
}
- return mActiveSession.showLocked(args, flags, mDisabledShowContext, showCallback,
- visibleActivities);
+ return mActiveSession.showLocked(args, flags, attributionTag, mDisabledShowContext,
+ showCallback, visibleActivities);
}
public void getActiveServiceSupportedActions(List<String> commands,
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java
index 9bdf4e4..80f5dc5 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceShellCommand.java
@@ -114,8 +114,8 @@
try {
Bundle args = new Bundle();
- boolean ok = mService.showSessionForActiveService(args, /* sourceFlags= */ 0, callback,
- /* activityToken= */ null);
+ boolean ok = mService.showSessionForActiveService(args, /* sourceFlags= */ 0,
+ /* attributionTag= */ null, callback, /* activityToken= */ null);
if (!ok) {
pw.println("showSessionForActiveService() returned false");
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index 093e976..63781cc 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -29,6 +29,8 @@
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_TASK_ID;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.AppOpsManager;
@@ -263,9 +265,9 @@
return flags;
}
- public boolean showLocked(Bundle args, int flags, int disabledContext,
- IVoiceInteractionSessionShowCallback showCallback,
- List<ActivityAssistInfo> topActivities) {
+ public boolean showLocked(@NonNull Bundle args, int flags, @Nullable String attributionTag,
+ int disabledContext, @Nullable IVoiceInteractionSessionShowCallback showCallback,
+ @NonNull List<ActivityAssistInfo> topActivities) {
if (mBound) {
if (!mFullyBound) {
mFullyBound = mContext.bindServiceAsUser(mBindIntent, mFullConnection,
@@ -291,12 +293,15 @@
for (int i = 0; i < topActivitiesCount; i++) {
topActivitiesToken.add(topActivities.get(i).getActivityToken());
}
+
mAssistDataRequester.requestAssistData(topActivitiesToken,
fetchData,
fetchScreenshot,
(disabledContext & VoiceInteractionSession.SHOW_WITH_ASSIST) == 0,
(disabledContext & VoiceInteractionSession.SHOW_WITH_SCREENSHOT) == 0,
- mCallingUid, mSessionComponentName.getPackageName());
+ mCallingUid,
+ mSessionComponentName.getPackageName(),
+ attributionTag);
boolean needDisclosure = mAssistDataRequester.getPendingDataCount() > 0
|| mAssistDataRequester.getPendingScreenshotCount() > 0;