summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt10
-rw-r--r--core/java/android/app/Activity.java14
-rw-r--r--core/java/android/app/ActivityManagerNative.java43
-rw-r--r--core/java/android/app/ActivityThread.java38
-rw-r--r--core/java/android/app/Application.java51
-rw-r--r--core/java/android/app/ApplicationThreadNative.java22
-rw-r--r--core/java/android/app/IActivityManager.java6
-rw-r--r--core/java/android/app/IApplicationThread.java3
-rw-r--r--core/java/android/app/SearchManager.java13
-rw-r--r--core/java/android/content/Intent.java21
-rw-r--r--core/java/android/view/SimulatedDpad.java2
-rw-r--r--core/res/AndroidManifest.xml7
-rw-r--r--core/res/res/values/strings.xml6
-rw-r--r--packages/SystemUI/AndroidManifest.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/SearchPanelView.java6
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindowManager.java2
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java2
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java6
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java2
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java81
20 files changed, 322 insertions, 16 deletions
diff --git a/api/current.txt b/api/current.txt
index 1995416..81e5d4f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -57,6 +57,7 @@ package android {
field public static final java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
field public static final java.lang.String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
field public static final java.lang.String GET_TASKS = "android.permission.GET_TASKS";
+ field public static final java.lang.String GET_TOP_ACTIVITY_INFO = "android.permission.GET_TOP_ACTIVITY_INFO";
field public static final java.lang.String GLOBAL_SEARCH = "android.permission.GLOBAL_SEARCH";
field public static final java.lang.String HARDWARE_TEST = "android.permission.HARDWARE_TEST";
field public static final java.lang.String INJECT_EVENTS = "android.permission.INJECT_EVENTS";
@@ -2738,6 +2739,7 @@ package android.app {
method public void onPrepareNavigateUpTaskStack(android.app.TaskStackBuilder);
method public boolean onPrepareOptionsMenu(android.view.Menu);
method public boolean onPreparePanel(int, android.view.View, android.view.Menu);
+ method public void onProvideAssistData(android.os.Bundle);
method protected void onRestart();
method protected void onRestoreInstanceState(android.os.Bundle);
method protected void onResume();
@@ -3077,7 +3079,9 @@ package android.app {
method public void onTerminate();
method public void onTrimMemory(int);
method public void registerActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks);
+ method public void registerOnProvideAssistData(android.app.Application.OnProvideAssistData);
method public void unregisterActivityLifecycleCallbacks(android.app.Application.ActivityLifecycleCallbacks);
+ method public void unregisterOnProvideAssistData(android.app.Application.OnProvideAssistData);
}
public static abstract interface Application.ActivityLifecycleCallbacks {
@@ -3090,6 +3094,10 @@ package android.app {
method public abstract void onActivityStopped(android.app.Activity);
}
+ public static abstract interface Application.OnProvideAssistData {
+ method public abstract void onProvideAssistData(android.app.Activity, android.os.Bundle);
+ }
+
public class ApplicationErrorReport implements android.os.Parcelable {
ctor public ApplicationErrorReport();
method public int describeContents();
@@ -5901,6 +5909,8 @@ package android.content {
field public static final android.os.Parcelable.Creator CREATOR;
field public static final java.lang.String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT";
field public static final deprecated java.lang.String EXTRA_ALLOW_REPLACE = "android.intent.extra.ALLOW_REPLACE";
+ field public static final java.lang.String EXTRA_ASSIST_CONTEXT = "android.intent.extra.ASSIST_CONTEXT";
+ field public static final java.lang.String EXTRA_ASSIST_PACKAGE = "android.intent.extra.ASSIST_PACKAGE";
field public static final java.lang.String EXTRA_BCC = "android.intent.extra.BCC";
field public static final java.lang.String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT";
field public static final java.lang.String EXTRA_CC = "android.intent.extra.CC";
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d6ddeb6..18ccd53 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1346,6 +1346,20 @@ public class Activity extends ContextThemeWrapper
}
/**
+ * This is called when the user is requesting an assist, to build a full
+ * {@link Intent#ACTION_ASSIST} Intent with all of the context of the current
+ * application. You can override this method to place into the bundle anything
+ * you would like to appear in the {@link Intent#EXTRA_ASSIST_CONTEXT} part
+ * of the assist Intent. The default implementation does nothing.
+ *
+ * <p>This function will be called after any global assist callbacks that had
+ * been registered with {@link Application#registerOnProvideAssistData
+ * Application.registerOnProvideAssistData}.
+ */
+ public void onProvideAssistData(Bundle data) {
+ }
+
+ /**
* Called when you are no longer visible to the user. You will next
* receive either {@link #onRestart}, {@link #onDestroy}, or nothing,
* depending on later user activity.
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 61b2067..bc27a57 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1818,6 +1818,24 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case GET_TOP_ACTIVITY_EXTRAS_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ int requestType = data.readInt();
+ Bundle res = getTopActivityExtras(requestType);
+ reply.writeNoException();
+ reply.writeBundle(res);
+ return true;
+ }
+
+ case REPORT_TOP_ACTIVITY_EXTRAS_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder token = data.readStrongBinder();
+ Bundle extras = data.readBundle();
+ reportTopActivityExtras(token, extras);
+ reply.writeNoException();
+ return true;
+ }
+
}
return super.onTransact(code, data, reply, flags);
@@ -4149,5 +4167,30 @@ class ActivityManagerProxy implements IActivityManager
return res;
}
+ public Bundle getTopActivityExtras(int requestType) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeInt(requestType);
+ mRemote.transact(GET_TOP_ACTIVITY_EXTRAS_TRANSACTION, data, reply, 0);
+ reply.readException();
+ Bundle res = reply.readBundle();
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
+
+ public void reportTopActivityExtras(IBinder token, Bundle extras) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(token);
+ data.writeBundle(extras);
+ mRemote.transact(REPORT_TOP_ACTIVITY_EXTRAS_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 1271645..570fb80 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -533,6 +533,12 @@ public final class ActivityThread {
String pkg;
CompatibilityInfo info;
}
+
+ static final class RequestActivityExtras {
+ IBinder activityToken;
+ IBinder requestToken;
+ int requestType;
+ }
private native void dumpGraphicsInfo(FileDescriptor fd);
@@ -1108,6 +1114,16 @@ public final class ActivityThread {
queueOrSendMessage(H.UNSTABLE_PROVIDER_DIED, provider);
}
+ @Override
+ public void requestActivityExtras(IBinder activityToken, IBinder requestToken,
+ int requestType) {
+ RequestActivityExtras cmd = new RequestActivityExtras();
+ cmd.activityToken = activityToken;
+ cmd.requestToken = requestToken;
+ cmd.requestType = requestType;
+ queueOrSendMessage(H.REQUEST_ACTIVITY_EXTRAS, cmd);
+ }
+
private void printRow(PrintWriter pw, String format, Object...objs) {
pw.println(String.format(format, objs));
}
@@ -1173,6 +1189,7 @@ public final class ActivityThread {
public static final int TRIM_MEMORY = 140;
public static final int DUMP_PROVIDER = 141;
public static final int UNSTABLE_PROVIDER_DIED = 142;
+ public static final int REQUEST_ACTIVITY_EXTRAS = 143;
String codeToString(int code) {
if (DEBUG_MESSAGES) {
switch (code) {
@@ -1219,6 +1236,7 @@ public final class ActivityThread {
case TRIM_MEMORY: return "TRIM_MEMORY";
case DUMP_PROVIDER: return "DUMP_PROVIDER";
case UNSTABLE_PROVIDER_DIED: return "UNSTABLE_PROVIDER_DIED";
+ case REQUEST_ACTIVITY_EXTRAS: return "REQUEST_ACTIVITY_EXTRAS";
}
}
return Integer.toString(code);
@@ -1430,6 +1448,9 @@ public final class ActivityThread {
case UNSTABLE_PROVIDER_DIED:
handleUnstableProviderDied((IBinder)msg.obj, false);
break;
+ case REQUEST_ACTIVITY_EXTRAS:
+ handleRequestActivityExtras((RequestActivityExtras)msg.obj);
+ break;
}
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
}
@@ -2322,6 +2343,23 @@ public final class ActivityThread {
performNewIntents(data.token, data.intents);
}
+ public void handleRequestActivityExtras(RequestActivityExtras cmd) {
+ Bundle data = new Bundle();
+ ActivityClientRecord r = mActivities.get(cmd.activityToken);
+ if (r != null) {
+ r.activity.getApplication().dispatchOnProvideAssistData(r.activity, data);
+ r.activity.onProvideAssistData(data);
+ }
+ if (data.isEmpty()) {
+ data = null;
+ }
+ IActivityManager mgr = ActivityManagerNative.getDefault();
+ try {
+ mgr.reportTopActivityExtras(cmd.requestToken, data);
+ } catch (RemoteException e) {
+ }
+ }
+
private static final ThreadLocal<Intent> sCurrentBroadcastIntent = new ThreadLocal<Intent>();
/**
diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java
index 3a67cec..132388e 100644
--- a/core/java/android/app/Application.java
+++ b/core/java/android/app/Application.java
@@ -22,6 +22,7 @@ import android.content.ComponentCallbacks;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.ContextWrapper;
+import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
@@ -45,6 +46,7 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 {
new ArrayList<ComponentCallbacks>();
private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
new ArrayList<ActivityLifecycleCallbacks>();
+ private ArrayList<OnProvideAssistData> mAssistCallbacks = null;
/** @hide */
public LoadedApk mLoadedApk;
@@ -59,6 +61,21 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 {
void onActivityDestroyed(Activity activity);
}
+ /**
+ * Callback interface for use with {@link Application#registerOnProvideAssistData}
+ * and {@link Application#unregisterOnProvideAssistData}.
+ */
+ public interface OnProvideAssistData {
+ /**
+ * This is called when the user is requesting an assist, to build a full
+ * {@link Intent#ACTION_ASSIST} Intent with all of the context of the current
+ * application. You can override this method to place into the bundle anything
+ * you would like to appear in the {@link Intent#EXTRA_ASSIST_CONTEXT} part
+ * of the assist Intent.
+ */
+ public void onProvideAssistData(Activity activity, Bundle data);
+ }
+
public Application() {
super(null);
}
@@ -137,7 +154,24 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 {
mActivityLifecycleCallbacks.remove(callback);
}
}
-
+
+ public void registerOnProvideAssistData(OnProvideAssistData callback) {
+ synchronized (this) {
+ if (mAssistCallbacks == null) {
+ mAssistCallbacks = new ArrayList<OnProvideAssistData>();
+ }
+ mAssistCallbacks.add(callback);
+ }
+ }
+
+ public void unregisterOnProvideAssistData(OnProvideAssistData callback) {
+ synchronized (this) {
+ if (mAssistCallbacks != null) {
+ mAssistCallbacks.remove(callback);
+ }
+ }
+ }
+
// ------------------ Internal API ------------------
/**
@@ -232,4 +266,19 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 {
}
return callbacks;
}
+
+ /* package */ void dispatchOnProvideAssistData(Activity activity, Bundle data) {
+ Object[] callbacks;
+ synchronized (this) {
+ if (mAssistCallbacks == null) {
+ return;
+ }
+ callbacks = mAssistCallbacks.toArray();
+ }
+ if (callbacks != null) {
+ for (int i=0; i<callbacks.length; i++) {
+ ((OnProvideAssistData)callbacks[i]).onProvideAssistData(activity, data);
+ }
+ }
+ }
}
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 63aa5f9..f0e367c 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -587,6 +587,17 @@ public abstract class ApplicationThreadNative extends Binder
reply.writeNoException();
return true;
}
+
+ case REQUEST_ACTIVITY_EXTRAS_TRANSACTION:
+ {
+ data.enforceInterface(IApplicationThread.descriptor);
+ IBinder activityToken = data.readStrongBinder();
+ IBinder requestToken = data.readStrongBinder();
+ int requestType = data.readInt();
+ requestActivityExtras(activityToken, requestToken, requestType);
+ reply.writeNoException();
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -1185,4 +1196,15 @@ class ApplicationThreadProxy implements IApplicationThread {
mRemote.transact(UNSTABLE_PROVIDER_DIED_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
data.recycle();
}
+
+ public void requestActivityExtras(IBinder activityToken, IBinder requestToken, int requestType)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ data.writeInterfaceToken(IApplicationThread.descriptor);
+ data.writeStrongBinder(activityToken);
+ data.writeStrongBinder(requestToken);
+ data.writeInt(requestType);
+ mRemote.transact(REQUEST_ACTIVITY_EXTRAS_TRANSACTION, data, null, IBinder.FLAG_ONEWAY);
+ data.recycle();
+ }
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 8af17a4..baac07f 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -368,6 +368,10 @@ public interface IActivityManager extends IInterface {
public long inputDispatchingTimedOut(int pid, boolean aboveSystem) throws RemoteException;
+ public Bundle getTopActivityExtras(int requestType) throws RemoteException;
+
+ public void reportTopActivityExtras(IBinder token, Bundle extras) throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -624,4 +628,6 @@ public interface IActivityManager extends IInterface {
int INPUT_DISPATCHING_TIMED_OUT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+158;
int CLEAR_PENDING_BACKUP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+159;
int GET_INTENT_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+160;
+ int GET_TOP_ACTIVITY_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+161;
+ int REPORT_TOP_ACTIVITY_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+162;
}
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 03a26d4..8516694 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -130,6 +130,8 @@ public interface IApplicationThread extends IInterface {
void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException;
void dumpDbInfo(FileDescriptor fd, String[] args) throws RemoteException;
void unstableProviderDied(IBinder provider) throws RemoteException;
+ void requestActivityExtras(IBinder activityToken, IBinder requestToken, int requestType)
+ throws RemoteException;
String descriptor = "android.app.IApplicationThread";
@@ -179,4 +181,5 @@ public interface IApplicationThread extends IInterface {
int DUMP_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+44;
int DUMP_DB_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+45;
int UNSTABLE_PROVIDER_DIED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+46;
+ int REQUEST_ACTIVITY_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+47;
}
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 6382cee..7dfc589 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -846,8 +846,8 @@ public class SearchManager
*
* @hide
*/
- public Intent getAssistIntent(Context context) {
- return getAssistIntent(context, UserHandle.myUserId());
+ public Intent getAssistIntent(Context context, boolean inclContext) {
+ return getAssistIntent(context, inclContext, UserHandle.myUserId());
}
/**
@@ -856,7 +856,7 @@ public class SearchManager
*
* @hide
*/
- public Intent getAssistIntent(Context context, int userHandle) {
+ public Intent getAssistIntent(Context context, boolean inclContext, int userHandle) {
try {
if (mService == null) {
return null;
@@ -867,6 +867,13 @@ public class SearchManager
}
Intent intent = new Intent(Intent.ACTION_ASSIST);
intent.setComponent(comp);
+ if (inclContext) {
+ IActivityManager am = ActivityManagerNative.getDefault();
+ Bundle extras = am.getTopActivityExtras(0);
+ if (extras != null) {
+ intent.replaceExtras(extras);
+ }
+ }
return intent;
} catch (RemoteException re) {
Log.e(TAG, "getAssistIntent() failed: " + re);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index b5349fd..dc367dd 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1140,14 +1140,33 @@ public class Intent implements Parcelable, Cloneable {
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH";
+
/**
* Activity Action: Perform assist action.
* <p>
- * Input: nothing
+ * Input: {@link #EXTRA_ASSIST_PACKAGE} and {@link #EXTRA_ASSIST_CONTEXT} can provide
+ * additional optional contextual information about where the user was when they requested
+ * the assist.
* Output: nothing.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_ASSIST = "android.intent.action.ASSIST";
+
+ /**
+ * An optional field on {@link #ACTION_ASSIST} containing the name of the current
+ * foreground application package at the time the assist was invoked.
+ */
+ public static final String EXTRA_ASSIST_PACKAGE
+ = "android.intent.extra.ASSIST_PACKAGE";
+
+ /**
+ * An optional field on {@link #ACTION_ASSIST} containing additional contextual
+ * information supplied by the current foreground app at the time of the assist
+ * request. This is a {@link Bundle} of additional data.
+ */
+ public static final String EXTRA_ASSIST_CONTEXT
+ = "android.intent.extra.ASSIST_CONTEXT";
+
/**
* Activity Action: List all available applications
* <p>Input: Nothing.
diff --git a/core/java/android/view/SimulatedDpad.java b/core/java/android/view/SimulatedDpad.java
index 0a37fdd..1ee416c 100644
--- a/core/java/android/view/SimulatedDpad.java
+++ b/core/java/android/view/SimulatedDpad.java
@@ -182,7 +182,7 @@ class SimulatedDpad {
Intent intent =
((SearchManager)mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, UserHandle.USER_CURRENT_OR_SELF);
+ .getAssistIntent(mContext, false, UserHandle.USER_CURRENT_OR_SELF);
if (intent != null) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a69870b..aafc4bf 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1702,6 +1702,13 @@
android:description="@string/permdesc_stopAppSwitches"
android:protectionLevel="signature|system" />
+ <!-- Allows an application to retrieve private information about
+ the current top activity, such as any assist context it can provide. -->
+ <permission android:name="android.permission.GET_TOP_ACTIVITY_INFO"
+ android:label="@string/permlab_getTopActivityInfo"
+ android:description="@string/permdesc_getTopActivityInfo"
+ android:protectionLevel="signature" />
+
<!-- Allows an application to retrieve the current state of keys and
switches. This is only for use by the system.
@deprecated The API that used this permission has been removed. -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index fa26089..7f0fc0b 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -784,6 +784,12 @@
another app.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_getTopActivityInfo">get current app info</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_getTopActivityInfo">Allows the holder to retrieve private information
+ about the current application in the foreground of the screen.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_runSetActivityWatcher">monitor and control all app launching</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_runSetActivityWatcher">Allows the app to
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 14fe6af..b85121e 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -49,7 +49,8 @@
<uses-permission android:name="android.permission.SET_SCREEN_COMPATIBILITY" />
<uses-permission android:name="android.permission.START_ANY_ACTIVITY" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
-
+ <uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO" />
+
<!-- WindowManager -->
<uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
index c0a6f56..1f29990 100644
--- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
@@ -103,7 +103,7 @@ public class SearchPanelView extends FrameLayout implements
} else {
// Otherwise, keyguard isn't showing so launch it from here.
Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+ .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
if (intent == null) return;
try {
@@ -180,7 +180,7 @@ public class SearchPanelView extends FrameLayout implements
private void maybeSwapSearchIcon() {
Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+ .getAssistIntent(mContext, false, UserHandle.USER_CURRENT);
if (intent != null) {
ComponentName component = intent.getComponent();
if (component == null || !mGlowPadView.replaceTargetDrawablesIfPresent(component,
@@ -329,6 +329,6 @@ public class SearchPanelView extends FrameLayout implements
public boolean isAssistantAvailable() {
return ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
+ .getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
}
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index b5cbdd1..35ff3d6 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2206,7 +2206,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private void launchAssistAction() {
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+ .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
if (intent != null) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_SINGLE_TOP
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
index 217e5d7..27d808b 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java
@@ -1567,7 +1567,7 @@ public class KeyguardHostView extends KeyguardViewBase {
public void showAssistant() {
final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+ .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
if (intent == null) return;
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
index 76cbbd5..6859042 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardSelectorView.java
@@ -61,7 +61,7 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
case com.android.internal.R.drawable.ic_action_assist_generic:
Intent assistIntent =
((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+ .getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
if (assistIntent != null) {
mActivityLauncher.launchActivity(assistIntent, false, true, null, null);
} else {
@@ -195,7 +195,7 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
currentUserHandle);
boolean searchActionAvailable =
((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
+ .getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
mCameraDisabled = cameraDisabledByAdmin || disabledBySimState || !cameraTargetPresent
|| !currentUserSetup;
mSearchDisabled = disabledBySimState || !searchActionAvailable || !searchTargetPresent
@@ -207,7 +207,7 @@ public class KeyguardSelectorView extends LinearLayout implements KeyguardSecuri
// Update the search icon with drawable from the search .apk
if (!mSearchDisabled) {
Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
- .getAssistIntent(mContext, UserHandle.USER_CURRENT);
+ .getAssistIntent(mContext, false, UserHandle.USER_CURRENT);
if (intent != null) {
// XXX Hack. We need to substitute the icon here but haven't formalized
// the public API. The "_google" metadata will be going away, so
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
index fef0613..8e10528 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewMediator.java
@@ -1428,6 +1428,6 @@ public class KeyguardViewMediator {
private boolean isAssistantAvailable() {
return mSearchManager != null
- && mSearchManager.getAssistIntent(mContext, UserHandle.USER_CURRENT) != null;
+ && mSearchManager.getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
}
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index d8e199b..e0046ad 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -262,6 +262,9 @@ public final class ActivityManagerService extends ActivityManagerNative
// Maximum number of users we allow to be running at a time.
static final int MAX_RUNNING_USERS = 3;
+ // How long to wait in getTopActivityExtras for the activity to respond with the result.
+ static final int PENDING_ACTIVITY_RESULT_TIMEOUT = 2*2000;
+
static final int MY_PID = Process.myPid();
static final String[] EMPTY_STRING_ARRAY = new String[0];
@@ -319,11 +322,32 @@ public final class ActivityManagerService extends ActivityManagerNative
* Activity we have told the window manager to have key focus.
*/
ActivityRecord mFocusedActivity = null;
+
/**
* List of intents that were used to start the most recent tasks.
*/
final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
+ public class PendingActivityExtras extends Binder implements Runnable {
+ public final ActivityRecord activity;
+ public boolean haveResult = false;
+ public Bundle result = null;
+ public PendingActivityExtras(ActivityRecord _activity) {
+ activity = _activity;
+ }
+ @Override
+ public void run() {
+ Slog.w(TAG, "getTopActivityExtras failed: timeout retrieving from " + activity);
+ synchronized (this) {
+ haveResult = true;
+ notifyAll();
+ }
+ }
+ }
+
+ final ArrayList<PendingActivityExtras> mPendingActivityExtras
+ = new ArrayList<PendingActivityExtras>();
+
/**
* Process management.
*/
@@ -7451,6 +7475,63 @@ public final class ActivityManagerService extends ActivityManagerNative
return KEY_DISPATCHING_TIMEOUT;
}
+ public Bundle getTopActivityExtras(int requestType) {
+ enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO,
+ "getTopActivityExtras()");
+ PendingActivityExtras pae;
+ Bundle extras = new Bundle();
+ synchronized (this) {
+ ActivityRecord activity = mMainStack.mResumedActivity;
+ if (activity == null) {
+ Slog.w(TAG, "getTopActivityExtras failed: no resumed activity");
+ return null;
+ }
+ extras.putString(Intent.EXTRA_ASSIST_PACKAGE, activity.packageName);
+ if (activity.app == null || activity.app.thread == null) {
+ Slog.w(TAG, "getTopActivityExtras failed: no process for " + activity);
+ return extras;
+ }
+ if (activity.app.pid == Binder.getCallingPid()) {
+ Slog.w(TAG, "getTopActivityExtras failed: request process same as " + activity);
+ return extras;
+ }
+ pae = new PendingActivityExtras(activity);
+ try {
+ activity.app.thread.requestActivityExtras(activity.appToken, pae, requestType);
+ mPendingActivityExtras.add(pae);
+ mHandler.postDelayed(pae, PENDING_ACTIVITY_RESULT_TIMEOUT);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "getTopActivityExtras failed: crash calling " + activity);
+ return extras;
+ }
+ }
+ synchronized (pae) {
+ while (!pae.haveResult) {
+ try {
+ pae.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ if (pae.result != null) {
+ extras.putBundle(Intent.EXTRA_ASSIST_CONTEXT, pae.result);
+ }
+ }
+ synchronized (this) {
+ mPendingActivityExtras.remove(pae);
+ mHandler.removeCallbacks(pae);
+ }
+ return extras;
+ }
+
+ public void reportTopActivityExtras(IBinder token, Bundle extras) {
+ PendingActivityExtras pae = (PendingActivityExtras)token;
+ synchronized (pae) {
+ pae.result = extras;
+ pae.haveResult = true;
+ pae.notifyAll();
+ }
+ }
+
public void registerProcessObserver(IProcessObserver observer) {
enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
"registerProcessObserver()");