summaryrefslogtreecommitdiffstats
path: root/services/voiceinteraction
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2015-03-11 15:16:13 -0700
committerDianne Hackborn <hackbod@google.com>2015-03-12 17:07:51 -0700
commita83ce1dd2ad3a6b71e90ff4845afc1299fe17b9d (patch)
tree2b0f1d1e65920fdbf7e3b7867070ee32776f246e /services/voiceinteraction
parentd6ee06a0c86d9d1556bb4b15c9aaea538e415e38 (diff)
downloadframeworks_base-a83ce1dd2ad3a6b71e90ff4845afc1299fe17b9d.zip
frameworks_base-a83ce1dd2ad3a6b71e90ff4845afc1299fe17b9d.tar.gz
frameworks_base-a83ce1dd2ad3a6b71e90ff4845afc1299fe17b9d.tar.bz2
More work on collecting assist data.
Optimize parceling of AssistData (which is now renamed to AssistStructure) by pooling duplicated class name strings. Change text associated with a view node to a CharSequence, so styling information comes along. Include global text attributes -- size, colors, etc. Introduce a new AssistContent structure, which allows us to propagate information about the intent and data the activity is looking at. This further allows us to propagate permission grants, so the assistant can dig in to that data. The default implementation propagates the base intent of an activity, so if for example you bring up the assistant while doing a share the assistant itself has the same information and access that was given to the share activity (so it could for example share it in another way if it wanted to). Did some optimization of loading PersistableBundle from xml, to avoid duplicating hash maps and such. Changed how we dispatch ACTION_ASSIST to no longer include the more detailed AssistStructure (and new AssistContent) data when launching; now the example code that intercepts that needs to be sure to ask for assist data when it starts its session. This is more like it will finally be, and allows us to get to the UI more quickly. Change-Id: I88420a55761bf48d34ce3013e81bd96a0e087637
Diffstat (limited to 'services/voiceinteraction')
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java123
1 files changed, 105 insertions, 18 deletions
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
index e2b47c3..30d97b9 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
@@ -16,12 +16,17 @@
package com.android.server.voiceinteraction;
+import android.app.ActivityManager;
import android.app.ActivityManagerNative;
+import android.app.AssistContent;
import android.app.IActivityManager;
+import android.content.ClipData;
import android.content.ComponentName;
+import android.content.ContentProvider;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -53,6 +58,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
final int mCallingUid;
final IActivityManager mAm;
final IWindowManager mIWindowManager;
+ final IBinder mPermissionOwner;
boolean mShown;
Bundle mShowArgs;
int mShowFlags;
@@ -83,15 +89,9 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
public void send(int resultCode, Bundle resultData) throws RemoteException {
synchronized (mLock) {
if (mShown) {
- if (mSession != null) {
- try {
- mSession.handleAssist(resultData);
- } catch (RemoteException e) {
- }
- } else {
- mHaveAssistData = true;
- mAssistData = resultData;
- }
+ mHaveAssistData = true;
+ mAssistData = resultData;
+ deliverAssistData();
}
}
}
@@ -109,6 +109,14 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
mAm = ActivityManagerNative.getDefault();
mIWindowManager = IWindowManager.Stub.asInterface(
ServiceManager.getService(Context.WINDOW_SERVICE));
+ IBinder permOwner = null;
+ try {
+ permOwner = mAm.newUriPermissionOwner("voicesession:"
+ + component.flattenToShortString());
+ } catch (RemoteException e) {
+ Slog.w("voicesession", "AM dead", e);
+ }
+ mPermissionOwner = permOwner;
mBindIntent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
mBindIntent.setComponent(mSessionComponentName);
mBound = mContext.bindServiceAsUser(mBindIntent, this,
@@ -138,7 +146,8 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
mShowFlags = flags;
if ((flags&VoiceInteractionService.START_WITH_ASSIST) != 0) {
try {
- mAm.requestAssistContextExtras(0, mAssistReceiver);
+ mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL,
+ mAssistReceiver);
} catch (RemoteException e) {
}
} else {
@@ -152,20 +161,91 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
mShowFlags = 0;
} catch (RemoteException e) {
}
- if (mHaveAssistData) {
- try {
- mSession.handleAssist(mAssistData);
- mAssistData = null;
- mHaveAssistData = false;
- } catch (RemoteException e) {
- }
- }
+ deliverAssistData();
}
return true;
}
return false;
}
+ void grantUriPermission(Uri uri, int mode, int srcUid, int destUid, String destPkg) {
+ if (!"content".equals(uri.getScheme())) {
+ return;
+ }
+ long ident = Binder.clearCallingIdentity();
+ try {
+ // This will throw SecurityException for us.
+ mAm.checkGrantUriPermission(srcUid, null, ContentProvider.getUriWithoutUserId(uri),
+ mode, ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(srcUid)));
+ // No security exception, do the grant.
+ int sourceUserId = ContentProvider.getUserIdFromUri(uri, mUser);
+ uri = ContentProvider.getUriWithoutUserId(uri);
+ mAm.grantUriPermissionFromOwner(mPermissionOwner, srcUid, destPkg,
+ uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, sourceUserId, mUser);
+ } catch (RemoteException e) {
+ } catch (SecurityException e) {
+ Slog.w(TAG, "Can't propagate permission", e);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+
+ }
+
+ void grantClipDataItemPermission(ClipData.Item item, int mode, int srcUid, int destUid,
+ String destPkg) {
+ if (item.getUri() != null) {
+ grantUriPermission(item.getUri(), mode, srcUid, destUid, destPkg);
+ }
+ Intent intent = item.getIntent();
+ if (intent != null && intent.getData() != null) {
+ grantUriPermission(intent.getData(), mode, srcUid, destUid, destPkg);
+ }
+ }
+
+ void grantClipDataPermissions(ClipData data, int mode, int srcUid, int destUid,
+ String destPkg) {
+ final int N = data.getItemCount();
+ for (int i=0; i<N; i++) {
+ grantClipDataItemPermission(data.getItemAt(i), mode, srcUid, destUid, destPkg);
+ }
+ }
+
+ void deliverAssistData() {
+ if (mSession == null || !mHaveAssistData) {
+ return;
+ }
+ if (mAssistData != null) {
+ int uid = mAssistData.getInt(Intent.EXTRA_ASSIST_UID, -1);
+ if (uid >= 0) {
+ Bundle assistContext = mAssistData.getBundle(Intent.EXTRA_ASSIST_CONTEXT);
+ if (assistContext != null) {
+ AssistContent content = AssistContent.getAssistContent(assistContext);
+ if (content != null) {
+ Intent intent = content.getIntent();
+ if (intent != null) {
+ ClipData data = intent.getClipData();
+ if (data != null && Intent.isAccessUriMode(intent.getFlags())) {
+ grantClipDataPermissions(data, intent.getFlags(), uid,
+ mCallingUid, mSessionComponentName.getPackageName());
+ }
+ }
+ ClipData data = content.getClipData();
+ if (data != null) {
+ grantClipDataPermissions(data, Intent.FLAG_GRANT_READ_URI_PERMISSION,
+ uid, mCallingUid, mSessionComponentName.getPackageName());
+ }
+ }
+ }
+ }
+ }
+ try {
+ mSession.handleAssist(mAssistData);
+ mAssistData = null;
+ mHaveAssistData = false;
+ } catch (RemoteException e) {
+ }
+ }
+
public boolean hideLocked() {
if (mBound) {
if (mShown) {
@@ -180,6 +260,13 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
} catch (RemoteException e) {
}
}
+ try {
+ mAm.revokeUriPermissionFromOwner(mPermissionOwner, null,
+ Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
+ mUser);
+ } catch (RemoteException e) {
+ }
}
if (mFullyBound) {
mContext.unbindService(mFullConnection);