am 3aefa438: am 78ead58d: Merge "Fix issue #22531747: Assist info should declare if user has disabled..." into mnc-dev

* commit '3aefa438300b116d2c080de434e0a890bf1dded5':
  Fix issue #22531747: Assist info should declare if user has disabled...
This commit is contained in:
Dianne Hackborn
2015-07-20 20:12:48 +00:00
committed by Android Git Automerger
19 changed files with 262 additions and 100 deletions

View File

@ -3466,6 +3466,7 @@ package android.app {
method public final void setVolumeControlStream(int); method public final void setVolumeControlStream(int);
method public boolean shouldShowRequestPermissionRationale(java.lang.String); method public boolean shouldShowRequestPermissionRationale(java.lang.String);
method public boolean shouldUpRecreateTask(android.content.Intent); method public boolean shouldUpRecreateTask(android.content.Intent);
method public boolean showAssist(android.os.Bundle);
method public final deprecated void showDialog(int); method public final deprecated void showDialog(int);
method public final deprecated boolean showDialog(int, android.os.Bundle); method public final deprecated boolean showDialog(int, android.os.Bundle);
method public void showLockTaskEscapeMessage(); method public void showLockTaskEscapeMessage();
@ -28808,6 +28809,7 @@ package android.service.voice {
method public android.content.Context getContext(); method public android.content.Context getContext();
method public int getDisabledShowContext(); method public int getDisabledShowContext();
method public android.view.LayoutInflater getLayoutInflater(); method public android.view.LayoutInflater getLayoutInflater();
method public int getUserDisabledShowContext();
method public android.app.Dialog getWindow(); method public android.app.Dialog getWindow();
method public void hide(); method public void hide();
method public void onAssistStructureFailure(java.lang.Throwable); method public void onAssistStructureFailure(java.lang.Throwable);
@ -28843,6 +28845,7 @@ package android.service.voice {
method public void setTheme(int); method public void setTheme(int);
method public void show(android.os.Bundle, int); method public void show(android.os.Bundle, int);
method public void startVoiceActivity(android.content.Intent); method public void startVoiceActivity(android.content.Intent);
field public static final int SHOW_SOURCE_APPLICATION = 8; // 0x8
field public static final int SHOW_SOURCE_ASSIST_GESTURE = 4; // 0x4 field public static final int SHOW_SOURCE_ASSIST_GESTURE = 4; // 0x4
field public static final int SHOW_WITH_ASSIST = 1; // 0x1 field public static final int SHOW_WITH_ASSIST = 1; // 0x1
field public static final int SHOW_WITH_SCREENSHOT = 2; // 0x2 field public static final int SHOW_WITH_SCREENSHOT = 2; // 0x2

View File

@ -3569,6 +3569,7 @@ package android.app {
method public final void setVolumeControlStream(int); method public final void setVolumeControlStream(int);
method public boolean shouldShowRequestPermissionRationale(java.lang.String); method public boolean shouldShowRequestPermissionRationale(java.lang.String);
method public boolean shouldUpRecreateTask(android.content.Intent); method public boolean shouldUpRecreateTask(android.content.Intent);
method public boolean showAssist(android.os.Bundle);
method public final deprecated void showDialog(int); method public final deprecated void showDialog(int);
method public final deprecated boolean showDialog(int, android.os.Bundle); method public final deprecated boolean showDialog(int, android.os.Bundle);
method public void showLockTaskEscapeMessage(); method public void showLockTaskEscapeMessage();
@ -30960,6 +30961,7 @@ package android.service.voice {
method public android.content.Context getContext(); method public android.content.Context getContext();
method public int getDisabledShowContext(); method public int getDisabledShowContext();
method public android.view.LayoutInflater getLayoutInflater(); method public android.view.LayoutInflater getLayoutInflater();
method public int getUserDisabledShowContext();
method public android.app.Dialog getWindow(); method public android.app.Dialog getWindow();
method public void hide(); method public void hide();
method public void onAssistStructureFailure(java.lang.Throwable); method public void onAssistStructureFailure(java.lang.Throwable);
@ -30995,6 +30997,7 @@ package android.service.voice {
method public void setTheme(int); method public void setTheme(int);
method public void show(android.os.Bundle, int); method public void show(android.os.Bundle, int);
method public void startVoiceActivity(android.content.Intent); method public void startVoiceActivity(android.content.Intent);
field public static final int SHOW_SOURCE_APPLICATION = 8; // 0x8
field public static final int SHOW_SOURCE_ASSIST_GESTURE = 4; // 0x4 field public static final int SHOW_SOURCE_ASSIST_GESTURE = 4; // 0x4
field public static final int SHOW_WITH_ASSIST = 1; // 0x1 field public static final int SHOW_WITH_ASSIST = 1; // 0x1
field public static final int SHOW_WITH_SCREENSHOT = 2; // 0x2 field public static final int SHOW_WITH_SCREENSHOT = 2; // 0x2

View File

@ -1544,6 +1544,24 @@ public class Activity extends ContextThemeWrapper
public void onProvideAssistContent(AssistContent outContent) { public void onProvideAssistContent(AssistContent outContent) {
} }
/**
* Ask to have the current assistant shown to the user. This only works if the calling
* activity is the current foreground activity. It is the same as calling
* {@link android.service.voice.VoiceInteractionService#showSession
* VoiceInteractionService.showSession} and requesting all of the possible context.
* The receiver will always see
* {@link android.service.voice.VoiceInteractionSession#SHOW_SOURCE_APPLICATION} set.
* @return Returns true if the assistant was successfully invoked, else false. For example
* false will be returned if the caller is not the current top activity.
*/
public boolean showAssist(Bundle args) {
try {
return ActivityManagerNative.getDefault().showAssistFromActivity(mToken, args);
} catch (RemoteException e) {
}
return false;
}
/** /**
* Called when you are no longer visible to the user. You will next * Called when you are no longer visible to the user. You will next
* receive either {@link #onRestart}, {@link #onDestroy}, or nothing, * receive either {@link #onRestart}, {@link #onDestroy}, or nothing,

View File

@ -2807,7 +2807,7 @@ public class ActivityManager {
/** /**
* Request that the system start watching for the calling process to exceed a pss * Request that the system start watching for the calling process to exceed a pss
* size as given here. Once called, the system will look for any occassions where it * size as given here. Once called, the system will look for any occasions where it
* sees the associated process with a larger pss size and, when this happens, automatically * sees the associated process with a larger pss size and, when this happens, automatically
* pull a heap dump from it and allow the user to share the data. Note that this request * pull a heap dump from it and allow the user to share the data. Note that this request
* continues running even if the process is killed and restarted. To remove the watch, * continues running even if the process is killed and restarted. To remove the watch,

View File

@ -2193,8 +2193,10 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
data.enforceInterface(IActivityManager.descriptor); data.enforceInterface(IActivityManager.descriptor);
int requestType = data.readInt(); int requestType = data.readInt();
IResultReceiver receiver = IResultReceiver.Stub.asInterface(data.readStrongBinder()); IResultReceiver receiver = IResultReceiver.Stub.asInterface(data.readStrongBinder());
requestAssistContextExtras(requestType, receiver); IBinder activityToken = data.readStrongBinder();
boolean res = requestAssistContextExtras(requestType, receiver, activityToken);
reply.writeNoException(); reply.writeNoException();
reply.writeInt(res ? 1 : 0);
return true; return true;
} }
@ -2225,7 +2227,17 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
case IS_SCREEN_CAPTURE_ALLOWED_ON_CURRENT_ACTIVITY_TRANSACTION: { case IS_SCREEN_CAPTURE_ALLOWED_ON_CURRENT_ACTIVITY_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor); data.enforceInterface(IActivityManager.descriptor);
boolean res = isScreenCaptureAllowedOnCurrentActivity(); boolean res = isAssistDataAllowedOnCurrentActivity();
reply.writeNoException();
reply.writeInt(res ? 1 : 0);
return true;
}
case SHOW_ASSIST_FROM_ACTIVITY_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
Bundle args = data.readBundle();
boolean res = showAssistFromActivity(token, args);
reply.writeNoException(); reply.writeNoException();
reply.writeInt(res ? 1 : 0); reply.writeInt(res ? 1 : 0);
return true; return true;
@ -5377,17 +5389,20 @@ class ActivityManagerProxy implements IActivityManager
return res; return res;
} }
public void requestAssistContextExtras(int requestType, IResultReceiver receiver) public boolean requestAssistContextExtras(int requestType, IResultReceiver receiver,
throws RemoteException { IBinder activityToken) throws RemoteException {
Parcel data = Parcel.obtain(); Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain(); Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor); data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(requestType); data.writeInt(requestType);
data.writeStrongBinder(receiver.asBinder()); data.writeStrongBinder(receiver.asBinder());
data.writeStrongBinder(activityToken);
mRemote.transact(REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION, data, reply, 0); mRemote.transact(REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION, data, reply, 0);
reply.readException(); reply.readException();
boolean res = reply.readInt() != 0;
data.recycle(); data.recycle();
reply.recycle(); reply.recycle();
return res;
} }
public void reportAssistContextExtras(IBinder token, Bundle extras, AssistStructure structure, public void reportAssistContextExtras(IBinder token, Bundle extras, AssistStructure structure,
@ -5429,7 +5444,7 @@ class ActivityManagerProxy implements IActivityManager
return res; return res;
} }
public boolean isScreenCaptureAllowedOnCurrentActivity() throws RemoteException { public boolean isAssistDataAllowedOnCurrentActivity() throws RemoteException {
Parcel data = Parcel.obtain(); Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain(); Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor); data.writeInterfaceToken(IActivityManager.descriptor);
@ -5441,6 +5456,20 @@ class ActivityManagerProxy implements IActivityManager
return res; return res;
} }
public boolean showAssistFromActivity(IBinder token, Bundle args) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(token);
data.writeBundle(args);
mRemote.transact(SHOW_ASSIST_FROM_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
boolean res = reply.readInt() != 0;
data.recycle();
reply.recycle();
return res;
}
public void killUid(int uid, String reason) throws RemoteException { public void killUid(int uid, String reason) throws RemoteException {
Parcel data = Parcel.obtain(); Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain(); Parcel reply = Parcel.obtain();

View File

@ -434,8 +434,8 @@ public interface IActivityManager extends IInterface {
public Bundle getAssistContextExtras(int requestType) throws RemoteException; public Bundle getAssistContextExtras(int requestType) throws RemoteException;
public void requestAssistContextExtras(int requestType, IResultReceiver receiver) public boolean requestAssistContextExtras(int requestType, IResultReceiver receiver,
throws RemoteException; IBinder activityToken) throws RemoteException;
public void reportAssistContextExtras(IBinder token, Bundle extras, public void reportAssistContextExtras(IBinder token, Bundle extras,
AssistStructure structure, AssistContent content, Uri referrer) throws RemoteException; AssistStructure structure, AssistContent content, Uri referrer) throws RemoteException;
@ -443,7 +443,9 @@ public interface IActivityManager extends IInterface {
public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle, public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle,
Bundle args) throws RemoteException; Bundle args) throws RemoteException;
public boolean isScreenCaptureAllowedOnCurrentActivity() throws RemoteException; public boolean isAssistDataAllowedOnCurrentActivity() throws RemoteException;
public boolean showAssistFromActivity(IBinder token, Bundle args) throws RemoteException;
public void killUid(int uid, String reason) throws RemoteException; public void killUid(int uid, String reason) throws RemoteException;
@ -858,4 +860,5 @@ public interface IActivityManager extends IInterface {
int UNREGISTER_UID_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+298; int UNREGISTER_UID_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+298;
int IS_SCREEN_CAPTURE_ALLOWED_ON_CURRENT_ACTIVITY_TRANSACTION int IS_SCREEN_CAPTURE_ALLOWED_ON_CURRENT_ACTIVITY_TRANSACTION
= IBinder.FIRST_CALL_TRANSACTION+299; = IBinder.FIRST_CALL_TRANSACTION+299;
int SHOW_ASSIST_FROM_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+300;
} }

View File

@ -91,6 +91,12 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
*/ */
public static final int SHOW_SOURCE_ASSIST_GESTURE = 1<<2; public static final int SHOW_SOURCE_ASSIST_GESTURE = 1<<2;
/**
* Flag for use with {@link #onShow}: indicates that the application itself has invoked
* the assistant.
*/
public static final int SHOW_SOURCE_APPLICATION = 1<<3;
final Context mContext; final Context mContext;
final HandlerCaller mHandlerCaller; final HandlerCaller mHandlerCaller;
@ -935,6 +941,23 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
} }
} }
/**
* Return which show context flags have been disabled by the user through the system
* settings UI, so the session will never get this data. Returned flags are any combination of
* {@link VoiceInteractionSession#SHOW_WITH_ASSIST VoiceInteractionSession.SHOW_WITH_ASSIST} and
* {@link VoiceInteractionSession#SHOW_WITH_SCREENSHOT
* VoiceInteractionSession.SHOW_WITH_SCREENSHOT}. Note that this only tells you about
* global user settings, not about restrictions that may be applied contextual based on
* the current application the user is in or other transient states.
*/
public int getUserDisabledShowContext() {
try {
return mSystemService.getUserDisabledShowContext();
} catch (RemoteException e) {
return 0;
}
}
/** /**
* Show the UI for this session. This asks the system to go through the process of showing * Show the UI for this session. This asks the system to go through the process of showing
* your UI, which will eventually culminate in {@link #onShow}. This is similar to calling * your UI, which will eventually culminate in {@link #onShow}. This is similar to calling
@ -1179,23 +1202,33 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
/** /**
* Called to receive data from the application that the user was currently viewing when * Called to receive data from the application that the user was currently viewing when
* an assist session is started. * an assist session is started. If the original show request did not specify
* {@link #SHOW_WITH_ASSIST}, this method will not be called.
* *
* @param data Arbitrary data supplied by the app through * @param data Arbitrary data supplied by the app through
* {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}. * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
* May be null if assist data has been disabled by the user or device policy.
* @param structure If available, the structure definition of all windows currently * @param structure If available, the structure definition of all windows currently
* displayed by the app; if structure has been turned off by the user, will be null. * displayed by the app. May be null if assist data has been disabled by the user
* or device policy; will be an empty stub if the application has disabled assist
* by marking its window as secure.
* @param content Additional content data supplied by the app through * @param content Additional content data supplied by the app through
* {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}. * {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}.
* May be null if assist data has been disabled by the user or device policy; will
* not be automatically filled in with data from the app if the app has marked its
* window as secure.
*/ */
public void onHandleAssist(Bundle data, AssistStructure structure, AssistContent content) { public void onHandleAssist(@Nullable Bundle data, @Nullable AssistStructure structure,
@Nullable AssistContent content) {
} }
/** /**
* Called to receive a screenshot of what the user was currently viewing when an assist * Called to receive a screenshot of what the user was currently viewing when an assist
* session is started. Will be null if screenshots are disabled by the user. * session is started. May be null if screenshots are disabled by the user, policy,
* or application. If the original show request did not specify
* {@link #SHOW_WITH_SCREENSHOT}, this method will not be called.
*/ */
public void onHandleScreenshot(Bitmap screenshot) { public void onHandleScreenshot(@Nullable Bitmap screenshot) {
} }
public boolean onKeyDown(int keyCode, KeyEvent event) { public boolean onKeyDown(int keyCode, KeyEvent event) {

View File

@ -23,6 +23,7 @@ import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ServiceManager; import android.os.ServiceManager;
import android.provider.Settings; import android.provider.Settings;
@ -45,13 +46,15 @@ public class AssistUtils {
ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE)); ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
} }
public void showSessionForActiveService(Bundle args, public boolean showSessionForActiveService(Bundle args, int sourceFlags,
IVoiceInteractionSessionShowCallback showCallback) { IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken) {
try { try {
mVoiceInteractionManagerService.showSessionForActiveService(args, showCallback); return mVoiceInteractionManagerService.showSessionForActiveService(args, sourceFlags,
showCallback, activityToken);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.w(TAG, "Failed to call showSessionForActiveService", e); Log.w(TAG, "Failed to call showSessionForActiveService", e);
} }
return false;
} }
public void launchVoiceAssistFromKeyguard() { public void launchVoiceAssistFromKeyguard() {

View File

@ -39,6 +39,7 @@ interface IVoiceInteractionManagerService {
void finish(IBinder token); void finish(IBinder token);
void setDisabledShowContext(int flags); void setDisabledShowContext(int flags);
int getDisabledShowContext(); int getDisabledShowContext();
int getUserDisabledShowContext();
/** /**
* Gets the registered Sound model for keyphrase detection for the current user. * Gets the registered Sound model for keyphrase detection for the current user.
@ -96,10 +97,12 @@ interface IVoiceInteractionManagerService {
* affordances. * affordances.
* *
* @param args the bundle to pass as arguments to the voice interaction session * @param args the bundle to pass as arguments to the voice interaction session
* @param showCallback callback to be notified when the session was shown * @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
*/ */
void showSessionForActiveService(in Bundle args, boolean showSessionForActiveService(in Bundle args, int sourceFlags,
IVoiceInteractionSessionShowCallback showCallback); IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken);
/** /**
* Hides the session from the active service, if it is showing. * Hides the session from the active service, if it is showing.

View File

@ -18,6 +18,7 @@ import android.os.Handler;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.UserHandle; import android.os.UserHandle;
import android.provider.Settings; import android.provider.Settings;
import android.service.voice.VoiceInteractionSession;
import android.util.Log; import android.util.Log;
import android.view.Gravity; import android.view.Gravity;
import android.view.HapticFeedbackConstants; import android.view.HapticFeedbackConstants;
@ -218,7 +219,8 @@ public class AssistManager {
} }
private void startVoiceInteractor(Bundle args) { private void startVoiceInteractor(Bundle args) {
mAssistUtils.showSessionForActiveService(args, mShowCallback); mAssistUtils.showSessionForActiveService(args,
VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE, mShowCallback, null);
} }
public void launchVoiceAssistFromKeyguard() { public void launchVoiceAssistFromKeyguard() {

View File

@ -65,6 +65,7 @@ import android.os.storage.IMountService;
import android.os.storage.MountServiceInternal; import android.os.storage.MountServiceInternal;
import android.os.storage.StorageManager; import android.os.storage.StorageManager;
import android.service.voice.IVoiceInteractionSession; import android.service.voice.IVoiceInteractionSession;
import android.service.voice.VoiceInteractionSession;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.DebugUtils; import android.util.DebugUtils;
@ -73,6 +74,7 @@ import android.view.Display;
import com.android.internal.R; import com.android.internal.R;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.AssistUtils;
import com.android.internal.app.DumpHeapActivity; import com.android.internal.app.DumpHeapActivity;
import com.android.internal.app.IAppOpsService; import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IVoiceInteractor; import com.android.internal.app.IVoiceInteractor;
@ -10686,7 +10688,7 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override @Override
public Bundle getAssistContextExtras(int requestType) { public Bundle getAssistContextExtras(int requestType) {
PendingAssistExtras pae = enqueueAssistContext(requestType, null, null, null, PendingAssistExtras pae = enqueueAssistContext(requestType, null, null, null,
UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_TIMEOUT); null, UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_TIMEOUT);
if (pae == null) { if (pae == null) {
return null; return null;
} }
@ -10707,7 +10709,7 @@ public final class ActivityManagerService extends ActivityManagerNative
} }
@Override @Override
public boolean isScreenCaptureAllowedOnCurrentActivity() { public boolean isAssistDataAllowedOnCurrentActivity() {
int userId = mCurrentUserId; int userId = mCurrentUserId;
synchronized (this) { synchronized (this) {
ActivityRecord activity = getFocusedStack().topActivity(); ActivityRecord activity = getFocusedStack().topActivity();
@ -10722,13 +10724,41 @@ public final class ActivityManagerService extends ActivityManagerNative
} }
@Override @Override
public void requestAssistContextExtras(int requestType, IResultReceiver receiver) { public boolean showAssistFromActivity(IBinder token, Bundle args) {
enqueueAssistContext(requestType, null, null, receiver, UserHandle.getCallingUserId(), long ident = Binder.clearCallingIdentity();
null, PENDING_ASSIST_EXTRAS_LONG_TIMEOUT); try {
synchronized (this) {
ActivityRecord caller = ActivityRecord.forTokenLocked(token);
ActivityRecord top = getFocusedStack().topActivity();
if (top != caller) {
Slog.w(TAG, "showAssistFromActivity failed: caller " + caller
+ " is not current top " + top);
return false;
}
if (!top.nowVisible) {
Slog.w(TAG, "showAssistFromActivity failed: caller " + caller
+ " is not visible");
return false;
}
}
AssistUtils utils = new AssistUtils(mContext);
return utils.showSessionForActiveService(args,
VoiceInteractionSession.SHOW_SOURCE_APPLICATION, null, token);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override
public boolean requestAssistContextExtras(int requestType, IResultReceiver receiver,
IBinder activityToken) {
return enqueueAssistContext(requestType, null, null, receiver, activityToken,
UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_LONG_TIMEOUT) != null;
} }
private PendingAssistExtras enqueueAssistContext(int requestType, Intent intent, String hint, private PendingAssistExtras enqueueAssistContext(int requestType, Intent intent, String hint,
IResultReceiver receiver, int userHandle, Bundle args, long timeout) { IResultReceiver receiver, IBinder activityToken, int userHandle, Bundle args,
long timeout) {
enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO, enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO,
"enqueueAssistContext()"); "enqueueAssistContext()");
synchronized (this) { synchronized (this) {
@ -10741,9 +10771,13 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.w(TAG, "getAssistContextExtras failed: no process for " + activity); Slog.w(TAG, "getAssistContextExtras failed: no process for " + activity);
return null; return null;
} }
if (activity.app.pid == Binder.getCallingPid()) { if (activityToken != null) {
Slog.w(TAG, "getAssistContextExtras failed: request process same as " + activity); ActivityRecord caller = ActivityRecord.forTokenLocked(activityToken);
return null; if (activity != caller) {
Slog.w(TAG, "enqueueAssistContext failed: caller " + caller
+ " is not current top " + activity);
return null;
}
} }
PendingAssistExtras pae; PendingAssistExtras pae;
Bundle extras = new Bundle(); Bundle extras = new Bundle();
@ -10854,7 +10888,7 @@ public final class ActivityManagerService extends ActivityManagerNative
public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle, public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle,
Bundle args) { Bundle args) {
return enqueueAssistContext(requestType, intent, hint, null, userHandle, args, return enqueueAssistContext(requestType, intent, hint, null, null, userHandle, args,
PENDING_ASSIST_EXTRAS_TIMEOUT) != null; PENDING_ASSIST_EXTRAS_TIMEOUT) != null;
} }

View File

@ -448,7 +448,7 @@ public class VoiceInteractionManagerService extends SystemService {
} }
final long caller = Binder.clearCallingIdentity(); final long caller = Binder.clearCallingIdentity();
try { try {
mImpl.showSessionLocked(args, flags, null /* showCallback */); mImpl.showSessionLocked(args, flags, null, null);
} finally { } finally {
Binder.restoreCallingIdentity(caller); Binder.restoreCallingIdentity(caller);
} }
@ -463,12 +463,9 @@ public class VoiceInteractionManagerService extends SystemService {
throw new SecurityException( throw new SecurityException(
"deliverNewSession without running voice interaction service"); "deliverNewSession without running voice interaction service");
} }
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long caller = Binder.clearCallingIdentity(); final long caller = Binder.clearCallingIdentity();
try { try {
return mImpl.deliverNewSessionLocked(callingPid, callingUid, token, session, return mImpl.deliverNewSessionLocked(token, session, interactor);
interactor);
} finally { } finally {
Binder.restoreCallingIdentity(caller); Binder.restoreCallingIdentity(caller);
} }
@ -484,7 +481,7 @@ public class VoiceInteractionManagerService extends SystemService {
} }
final long caller = Binder.clearCallingIdentity(); final long caller = Binder.clearCallingIdentity();
try { try {
return mImpl.showSessionLocked(sessionArgs, flags, null /* showCallback */); return mImpl.showSessionLocked(sessionArgs, flags, null, null);
} finally { } finally {
Binder.restoreCallingIdentity(caller); Binder.restoreCallingIdentity(caller);
} }
@ -533,11 +530,9 @@ public class VoiceInteractionManagerService extends SystemService {
Slog.w(TAG, "setKeepAwake without running voice interaction service"); Slog.w(TAG, "setKeepAwake without running voice interaction service");
return; return;
} }
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long caller = Binder.clearCallingIdentity(); final long caller = Binder.clearCallingIdentity();
try { try {
mImpl.setKeepAwakeLocked(callingPid, callingUid, token, keepAwake); mImpl.setKeepAwakeLocked(token, keepAwake);
} finally { } finally {
Binder.restoreCallingIdentity(caller); Binder.restoreCallingIdentity(caller);
} }
@ -551,11 +546,9 @@ public class VoiceInteractionManagerService extends SystemService {
Slog.w(TAG, "closeSystemDialogs without running voice interaction service"); Slog.w(TAG, "closeSystemDialogs without running voice interaction service");
return; return;
} }
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long caller = Binder.clearCallingIdentity(); final long caller = Binder.clearCallingIdentity();
try { try {
mImpl.closeSystemDialogsLocked(callingPid, callingUid, token); mImpl.closeSystemDialogsLocked(token);
} finally { } finally {
Binder.restoreCallingIdentity(caller); Binder.restoreCallingIdentity(caller);
} }
@ -585,16 +578,14 @@ public class VoiceInteractionManagerService extends SystemService {
Slog.w(TAG, "setDisabledShowContext without running voice interaction service"); Slog.w(TAG, "setDisabledShowContext without running voice interaction service");
return; return;
} }
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid(); final int callingUid = Binder.getCallingUid();
final long caller = Binder.clearCallingIdentity(); final long caller = Binder.clearCallingIdentity();
try { try {
mImpl.setDisabledShowContextLocked(callingPid, callingUid, flags); mImpl.setDisabledShowContextLocked(callingUid, flags);
} finally { } finally {
Binder.restoreCallingIdentity(caller); Binder.restoreCallingIdentity(caller);
} }
} }
} }
@Override @Override
@ -604,16 +595,32 @@ public class VoiceInteractionManagerService extends SystemService {
Slog.w(TAG, "getDisabledShowContext without running voice interaction service"); Slog.w(TAG, "getDisabledShowContext without running voice interaction service");
return 0; return 0;
} }
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid(); final int callingUid = Binder.getCallingUid();
final long caller = Binder.clearCallingIdentity(); final long caller = Binder.clearCallingIdentity();
try { try {
return mImpl.getDisabledShowContextLocked(callingPid, callingUid); return mImpl.getDisabledShowContextLocked(callingUid);
} finally { } finally {
Binder.restoreCallingIdentity(caller); Binder.restoreCallingIdentity(caller);
} }
} }
}
@Override
public int getUserDisabledShowContext() {
synchronized (this) {
if (mImpl == null) {
Slog.w(TAG,
"getUserDisabledShowContext without running voice interaction service");
return 0;
}
final int callingUid = Binder.getCallingUid();
final long caller = Binder.clearCallingIdentity();
try {
return mImpl.getUserDisabledShowContextLocked(callingUid);
} finally {
Binder.restoreCallingIdentity(caller);
}
}
} }
//----------------- Model management APIs --------------------------------// //----------------- Model management APIs --------------------------------//
@ -799,22 +806,22 @@ public class VoiceInteractionManagerService extends SystemService {
} }
@Override @Override
public void showSessionForActiveService(Bundle args, public boolean showSessionForActiveService(Bundle args, int sourceFlags,
IVoiceInteractionSessionShowCallback showCallback) { IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken) {
enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE); enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
synchronized (this) { synchronized (this) {
if (mImpl == null) { if (mImpl == null) {
Slog.w(TAG, "showSessionForActiveService without running voice interaction" Slog.w(TAG, "showSessionForActiveService without running voice interaction"
+ "service"); + "service");
return; return false;
} }
final long caller = Binder.clearCallingIdentity(); final long caller = Binder.clearCallingIdentity();
try { try {
mImpl.showSessionLocked(args, return mImpl.showSessionLocked(args,
VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE sourceFlags
| VoiceInteractionSession.SHOW_WITH_ASSIST | VoiceInteractionSession.SHOW_WITH_ASSIST
| VoiceInteractionSession.SHOW_WITH_SCREENSHOT, | VoiceInteractionSession.SHOW_WITH_SCREENSHOT,
showCallback); showCallback, activityToken);
} finally { } finally {
Binder.restoreCallingIdentity(caller); Binder.restoreCallingIdentity(caller);
} }
@ -908,7 +915,8 @@ public class VoiceInteractionManagerService extends SystemService {
} }
private void enforceCallingPermission(String permission) { private void enforceCallingPermission(String permission) {
if (mContext.checkCallingPermission(permission) != PackageManager.PERMISSION_GRANTED) { if (mContext.checkCallingOrSelfPermission(permission)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Caller does not hold the permission " + permission); throw new SecurityException("Caller does not hold the permission " + permission);
} }
} }

View File

@ -142,12 +142,13 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
} }
public boolean showSessionLocked(Bundle args, int flags, public boolean showSessionLocked(Bundle args, int flags,
IVoiceInteractionSessionShowCallback showCallback) { IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken) {
if (mActiveSession == null) { if (mActiveSession == null) {
mActiveSession = new VoiceInteractionSessionConnection(mLock, mSessionComponentName, mActiveSession = new VoiceInteractionSessionConnection(mLock, mSessionComponentName,
mUser, mContext, this, mInfo.getServiceInfo().applicationInfo.uid, mHandler); mUser, mContext, this, mInfo.getServiceInfo().applicationInfo.uid, mHandler);
} }
return mActiveSession.showLocked(args, flags, mDisabledShowContext, showCallback); return mActiveSession.showLocked(args, flags, mDisabledShowContext, showCallback,
activityToken);
} }
public boolean hideSessionLocked() { public boolean hideSessionLocked() {
@ -157,7 +158,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
return false; return false;
} }
public boolean deliverNewSessionLocked(int callingPid, int callingUid, IBinder token, public boolean deliverNewSessionLocked(IBinder token,
IVoiceInteractionSession session, IVoiceInteractor interactor) { IVoiceInteractionSession session, IVoiceInteractor interactor) {
if (mActiveSession == null || token != mActiveSession.mToken) { if (mActiveSession == null || token != mActiveSession.mToken) {
Slog.w(TAG, "deliverNewSession does not match active session"); Slog.w(TAG, "deliverNewSession does not match active session");
@ -189,8 +190,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
} }
} }
public void setKeepAwakeLocked(int callingPid, int callingUid, IBinder token, public void setKeepAwakeLocked(IBinder token, boolean keepAwake) {
boolean keepAwake) {
try { try {
if (mActiveSession == null || token != mActiveSession.mToken) { if (mActiveSession == null || token != mActiveSession.mToken) {
Slog.w(TAG, "setKeepAwake does not match active session"); Slog.w(TAG, "setKeepAwake does not match active session");
@ -202,7 +202,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
} }
} }
public void closeSystemDialogsLocked(int callingPid, int callingUid, IBinder token) { public void closeSystemDialogsLocked(IBinder token) {
try { try {
if (mActiveSession == null || token != mActiveSession.mToken) { if (mActiveSession == null || token != mActiveSession.mToken) {
Slog.w(TAG, "closeSystemDialogs does not match active session"); Slog.w(TAG, "closeSystemDialogs does not match active session");
@ -223,7 +223,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mActiveSession = null; mActiveSession = null;
} }
public void setDisabledShowContextLocked(int callingPid, int callingUid, int flags) { public void setDisabledShowContextLocked(int callingUid, int flags) {
int activeUid = mInfo.getServiceInfo().applicationInfo.uid; int activeUid = mInfo.getServiceInfo().applicationInfo.uid;
if (callingUid != activeUid) { if (callingUid != activeUid) {
throw new SecurityException("Calling uid " + callingUid throw new SecurityException("Calling uid " + callingUid
@ -232,7 +232,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
mDisabledShowContext = flags; mDisabledShowContext = flags;
} }
public int getDisabledShowContextLocked(int callingPid, int callingUid) { public int getDisabledShowContextLocked(int callingUid) {
int activeUid = mInfo.getServiceInfo().applicationInfo.uid; int activeUid = mInfo.getServiceInfo().applicationInfo.uid;
if (callingUid != activeUid) { if (callingUid != activeUid) {
throw new SecurityException("Calling uid " + callingUid throw new SecurityException("Calling uid " + callingUid
@ -241,6 +241,15 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
return mDisabledShowContext; return mDisabledShowContext;
} }
public int getUserDisabledShowContextLocked(int callingUid) {
int activeUid = mInfo.getServiceInfo().applicationInfo.uid;
if (callingUid != activeUid) {
throw new SecurityException("Calling uid " + callingUid
+ " does not match active uid " + activeUid);
}
return mActiveSession != null ? mActiveSession.getUserDisabledShowContextLocked() : 0;
}
public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) { public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!mValid) { if (!mValid) {
pw.print(" NOT VALID: "); pw.print(" NOT VALID: ");

View File

@ -183,8 +183,21 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
} }
} }
public int getUserDisabledShowContextLocked() {
int flags = 0;
if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, mUser) == 0) {
flags |= VoiceInteractionSession.SHOW_WITH_ASSIST;
}
if (Settings.Secure.getIntForUser(mContext.getContentResolver(),
Settings.Secure.ASSIST_SCREENSHOT_ENABLED, 1, mUser) == 0) {
flags |= VoiceInteractionSession.SHOW_WITH_SCREENSHOT;
}
return flags;
}
public boolean showLocked(Bundle args, int flags, int disabledContext, public boolean showLocked(Bundle args, int flags, int disabledContext,
IVoiceInteractionSessionShowCallback showCallback) { IVoiceInteractionSessionShowCallback showCallback, IBinder activityToken) {
if (mBound) { if (mBound) {
if (!mFullyBound) { if (!mFullyBound) {
mFullyBound = mContext.bindServiceAsUser(mBindIntent, mFullConnection, mFullyBound = mContext.bindServiceAsUser(mBindIntent, mFullConnection,
@ -193,18 +206,15 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
new UserHandle(mUser)); new UserHandle(mUser));
} }
mShown = true; mShown = true;
boolean isScreenCaptureAllowed = true; boolean isAssistDataAllowed = true;
try { try {
isScreenCaptureAllowed = mAm.isScreenCaptureAllowedOnCurrentActivity(); isAssistDataAllowed = mAm.isAssistDataAllowedOnCurrentActivity();
} catch (RemoteException e) { } catch (RemoteException e) {
} }
boolean structureEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(), disabledContext |= getUserDisabledShowContextLocked();
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, mUser) != 0 boolean structureEnabled = isAssistDataAllowed
&& isScreenCaptureAllowed
&& (disabledContext&VoiceInteractionSession.SHOW_WITH_ASSIST) == 0; && (disabledContext&VoiceInteractionSession.SHOW_WITH_ASSIST) == 0;
boolean screenshotEnabled = Settings.Secure.getIntForUser(mContext.getContentResolver(), boolean screenshotEnabled = isAssistDataAllowed
Settings.Secure.ASSIST_SCREENSHOT_ENABLED, 1, mUser) != 0
&& isScreenCaptureAllowed
&& (disabledContext&VoiceInteractionSession.SHOW_WITH_SCREENSHOT) == 0; && (disabledContext&VoiceInteractionSession.SHOW_WITH_SCREENSHOT) == 0;
mShowArgs = args; mShowArgs = args;
mShowFlags = flags; mShowFlags = flags;
@ -215,9 +225,15 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED mSessionComponentName.getPackageName()) == AppOpsManager.MODE_ALLOWED
&& structureEnabled) { && structureEnabled) {
try { try {
needDisclosure = true; if (mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL,
mAm.requestAssistContextExtras(ActivityManager.ASSIST_CONTEXT_FULL, mAssistReceiver, activityToken)) {
mAssistReceiver); needDisclosure = true;
} else {
// Wasn't allowed... given that, let's not do the screenshot either.
mHaveAssistData = true;
mAssistData = null;
screenshotEnabled = false;
}
} catch (RemoteException e) { } catch (RemoteException e) {
} }
} else { } else {

View File

@ -80,6 +80,12 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Disallow screenshot" /> android:text="Disallow screenshot" />
<TextView android:id="@+id/options_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -74,21 +74,6 @@ public class MainInteractionService extends VoiceInteractionService {
"Hello There", Locale.forLanguageTag("en-US"), mHotwordCallback); "Hello There", Locale.forLanguageTag("en-US"), mHotwordCallback);
} }
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (isActiveService(this, new ComponentName(this, getClass()))) {
Bundle args = new Bundle();
args.putParcelable("intent", new Intent(this, TestInteractionActivity.class));
args.putBundle("assist", intent.getExtras());
showSession(args, VoiceInteractionSession.SHOW_WITH_ASSIST
| VoiceInteractionSession.SHOW_WITH_SCREENSHOT);
} else {
Log.w(TAG, "Not starting -- not current voice interaction service");
}
stopSelf(startId);
return START_NOT_STICKY;
}
private void hotwordAvailabilityChangeHelper(int availability) { private void hotwordAvailabilityChangeHelper(int availability) {
Log.i(TAG, "Hotword availability = " + availability); Log.i(TAG, "Hotword availability = " + availability);
switch (availability) { switch (availability) {

View File

@ -50,6 +50,7 @@ public class MainInteractionSession extends VoiceInteractionSession
View mOptionsContainer; View mOptionsContainer;
CheckBox mDisallowAssist; CheckBox mDisallowAssist;
CheckBox mDisallowScreenshot; CheckBox mDisallowScreenshot;
TextView mOptionsText;
ImageView mScreenshot; ImageView mScreenshot;
ImageView mFullScreenshot; ImageView mFullScreenshot;
Button mConfirmButton; Button mConfirmButton;
@ -86,8 +87,9 @@ public class MainInteractionSession extends VoiceInteractionSession
@Override @Override
public void onShow(Bundle args, int showFlags) { public void onShow(Bundle args, int showFlags) {
super.onShow(args, showFlags); super.onShow(args, showFlags);
Log.i(TAG, "onShow: flags=0x" + Integer.toHexString(showFlags) + " args=" + args);
mState = STATE_IDLE; mState = STATE_IDLE;
mStartIntent = args.getParcelable("intent"); mStartIntent = args != null ? (Intent)args.getParcelable("intent") : null;
if (mStartIntent == null) { if (mStartIntent == null) {
mStartIntent = new Intent(getContext(), TestInteractionActivity.class); mStartIntent = new Intent(getContext(), TestInteractionActivity.class);
} }
@ -96,6 +98,7 @@ public class MainInteractionSession extends VoiceInteractionSession
} }
onHandleScreenshot(null); onHandleScreenshot(null);
updateState(); updateState();
refreshOptions();
} }
@Override @Override
@ -134,6 +137,7 @@ public class MainInteractionSession extends VoiceInteractionSession
mDisallowAssist.setOnClickListener(this); mDisallowAssist.setOnClickListener(this);
mDisallowScreenshot = (CheckBox)mContentView.findViewById(R.id.disallow_screenshot); mDisallowScreenshot = (CheckBox)mContentView.findViewById(R.id.disallow_screenshot);
mDisallowScreenshot.setOnClickListener(this); mDisallowScreenshot.setOnClickListener(this);
mOptionsText = (TextView)mContentView.findViewById(R.id.options_text);
mConfirmButton = (Button)mContentView.findViewById(R.id.confirm); mConfirmButton = (Button)mContentView.findViewById(R.id.confirm);
mConfirmButton.setOnClickListener(this); mConfirmButton.setOnClickListener(this);
mCompleteButton = (Button)mContentView.findViewById(R.id.complete); mCompleteButton = (Button)mContentView.findViewById(R.id.complete);
@ -145,13 +149,17 @@ public class MainInteractionSession extends VoiceInteractionSession
} }
void refreshOptions() { void refreshOptions() {
if (mOptionsCheck.isChecked()) { if (mOptionsContainer != null) {
mOptionsContainer.setVisibility(View.VISIBLE); if (mOptionsCheck.isChecked()) {
int flags = getDisabledShowContext(); mOptionsContainer.setVisibility(View.VISIBLE);
mDisallowAssist.setChecked((flags & SHOW_WITH_ASSIST) != 0); int flags = getDisabledShowContext();
mDisallowScreenshot.setChecked((flags & SHOW_WITH_SCREENSHOT) != 0); mDisallowAssist.setChecked((flags & SHOW_WITH_ASSIST) != 0);
} else { mDisallowScreenshot.setChecked((flags & SHOW_WITH_SCREENSHOT) != 0);
mOptionsContainer.setVisibility(View.GONE); int disabled = getUserDisabledShowContext();
mOptionsText.setText("Disabled: 0x" + Integer.toHexString(disabled));
} else {
mOptionsContainer.setVisibility(View.GONE);
}
} }
} }

View File

@ -16,7 +16,6 @@
package com.android.test.voiceinteraction; package com.android.test.voiceinteraction;
import android.annotation.Nullable;
import android.app.Activity; import android.app.Activity;
import android.app.VoiceInteractor; import android.app.VoiceInteractor;
import android.content.ComponentName; import android.content.ComponentName;

View File

@ -49,7 +49,7 @@ public class VoiceInteractionMain extends Activity {
View.OnClickListener mStartListener = new View.OnClickListener() { View.OnClickListener mStartListener = new View.OnClickListener() {
public void onClick(View v) { public void onClick(View v) {
startService(new Intent(VoiceInteractionMain.this, MainInteractionService.class)); showAssist(null);
} }
}; };
} }