diff options
| author | 2013-08-05 19:23:41 -0700 | |
|---|---|---|
| committer | 2013-08-07 02:20:44 +0100 | |
| commit | dfc7fd7818cda46b914c8a9d69d1ba00443ffe5b (patch) | |
| tree | bb6f5ca2baf7b31d89725be061db4dc40aa2ca3d | |
| parent | 94fa8956b02f307912746d9ac87be7798dc3464e (diff) | |
Extend assist context to foreground services
Add Service.onProvideAssistData(Bundle) which will be
called on foreground Services that have the new attr
in their manifest of provideAssistData = true;
Rename private reference to e.g. "getTopActivityExtras"
as "getAssistContextExtras" - do not rename the relevant
permission, since it is already public.
In ActivityManagerService, request extras both from the
top activity and from any foreground services with the
above attribute. Extend PendingActivityExtras as
PendingAssistExtras with a list of Services from which
extras are expected.
Reduce the timeout to or reporting extras from 4 sec to
just 500 ms.
Bug: 9526331
Change-Id: Ia03b96e8189033a68ae9c514c8cea0199a19bce8
| -rw-r--r-- | api/current.txt | 4 | ||||
| -rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 19 | ||||
| -rw-r--r-- | core/java/android/app/ActivityThread.java | 29 | ||||
| -rw-r--r-- | core/java/android/app/ApplicationThreadNative.java | 13 | ||||
| -rw-r--r-- | core/java/android/app/IActivityManager.java | 9 | ||||
| -rw-r--r-- | core/java/android/app/IApplicationThread.java | 6 | ||||
| -rw-r--r-- | core/java/android/app/SearchManager.java | 2 | ||||
| -rw-r--r-- | core/java/android/app/Service.java | 13 | ||||
| -rw-r--r-- | core/java/android/content/Intent.java | 33 | ||||
| -rw-r--r-- | core/java/android/content/pm/PackageParser.java | 5 | ||||
| -rw-r--r-- | core/java/android/content/pm/ServiceInfo.java | 8 | ||||
| -rw-r--r-- | core/res/res/values/attrs_manifest.xml | 3 | ||||
| -rw-r--r-- | core/res/res/values/strings.xml | 4 | ||||
| -rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 139 |
14 files changed, 212 insertions, 75 deletions
diff --git a/api/current.txt b/api/current.txt index 0e1bc4b57047..b0e1dabe9849 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4228,6 +4228,7 @@ package android.app { method public void onCreate(); method public void onDestroy(); method public void onLowMemory(); + method public void onProvideAssistData(android.os.Bundle); method public void onRebind(android.content.Intent); method public deprecated void onStart(android.content.Intent, int); method public int onStartCommand(android.content.Intent, int, int); @@ -6272,6 +6273,8 @@ package android.content { 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_ASSIST_SERVICES_CONTEXTS = "android.intent.extra.ASSIST_SERVICES_CONTEXTS"; + field public static final java.lang.String EXTRA_ASSIST_SERVICES_PACKAGES = "android.intent.extra.ASSIST_SERVICES_PACKAGES"; 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"; @@ -7336,6 +7339,7 @@ package android.content.pm { method public void dump(android.util.Printer, java.lang.String); field public static final android.os.Parcelable.Creator CREATOR; field public static final int FLAG_ISOLATED_PROCESS = 2; // 0x2 + field public static final int FLAG_PROVIDE_ASSIST_DATA = 4; // 0x4 field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000 field public static final int FLAG_STOP_WITH_TASK = 1; // 0x1 field public int flags; diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 404f6aae67ac..cc964c29721f 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1921,20 +1921,21 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } - case GET_TOP_ACTIVITY_EXTRAS_TRANSACTION: { + case GET_ASSIST_CONTEXT_EXTRAS_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); int requestType = data.readInt(); - Bundle res = getTopActivityExtras(requestType); + Bundle res = getAssistContextExtras(requestType); reply.writeNoException(); reply.writeBundle(res); return true; } - case REPORT_TOP_ACTIVITY_EXTRAS_TRANSACTION: { + case REPORT_ASSIST_CONTEXT_EXTRAS_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); Bundle extras = data.readBundle(); - reportTopActivityExtras(token, extras); + int index = data.readInt(); + reportAssistContextExtras(token, extras, index); reply.writeNoException(); return true; } @@ -4456,12 +4457,12 @@ class ActivityManagerProxy implements IActivityManager return res; } - public Bundle getTopActivityExtras(int requestType) throws RemoteException { + public Bundle getAssistContextExtras(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); + mRemote.transact(GET_ASSIST_CONTEXT_EXTRAS_TRANSACTION, data, reply, 0); reply.readException(); Bundle res = reply.readBundle(); data.recycle(); @@ -4469,13 +4470,15 @@ class ActivityManagerProxy implements IActivityManager return res; } - public void reportTopActivityExtras(IBinder token, Bundle extras) throws RemoteException { + public void reportAssistContextExtras(IBinder token, Bundle extras, int index) + 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); + data.writeInt(index); + mRemote.transact(REPORT_ASSIST_CONTEXT_EXTRAS_TRANSACTION, data, reply, 0); reply.readException(); data.recycle(); reply.recycle(); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index d9f9d61886d7..64653cd7cdf8 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -529,10 +529,11 @@ public final class ActivityThread { CompatibilityInfo info; } - static final class RequestActivityExtras { + static final class RequestAssistContextExtras { IBinder activityToken; IBinder requestToken; int requestType; + int index; } private native void dumpGraphicsInfo(FileDescriptor fd); @@ -1197,13 +1198,14 @@ public final class ActivityThread { } @Override - public void requestActivityExtras(IBinder activityToken, IBinder requestToken, - int requestType) { - RequestActivityExtras cmd = new RequestActivityExtras(); + public void requestAssistContextExtras(IBinder activityToken, IBinder requestToken, + int requestType, int index) { + RequestAssistContextExtras cmd = new RequestAssistContextExtras(); cmd.activityToken = activityToken; cmd.requestToken = requestToken; cmd.requestType = requestType; - queueOrSendMessage(H.REQUEST_ACTIVITY_EXTRAS, cmd); + cmd.index = index; + queueOrSendMessage(H.REQUEST_ASSIST_CONTEXT_EXTRAS, cmd); } private void printRow(PrintWriter pw, String format, Object...objs) { @@ -1292,7 +1294,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; + public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143; public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144; String codeToString(int code) { if (DEBUG_MESSAGES) { @@ -1340,7 +1342,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"; + case REQUEST_ASSIST_CONTEXT_EXTRAS: return "REQUEST_ASSIST_CONTEXT_EXTRAS"; case TRANSLUCENT_CONVERSION_COMPLETE: return "TRANSLUCENT_CONVERSION_COMPLETE"; } } @@ -1553,8 +1555,8 @@ public final class ActivityThread { case UNSTABLE_PROVIDER_DIED: handleUnstableProviderDied((IBinder)msg.obj, false); break; - case REQUEST_ACTIVITY_EXTRAS: - handleRequestActivityExtras((RequestActivityExtras)msg.obj); + case REQUEST_ASSIST_CONTEXT_EXTRAS: + handleRequestAssistContextExtras((RequestAssistContextExtras)msg.obj); break; case TRANSLUCENT_CONVERSION_COMPLETE: handleTranslucentConversionComplete((IBinder)msg.obj, msg.arg1 == 1); @@ -2275,19 +2277,24 @@ public final class ActivityThread { performNewIntents(data.token, data.intents); } - public void handleRequestActivityExtras(RequestActivityExtras cmd) { + public void handleRequestAssistContextExtras(RequestAssistContextExtras 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); + } else { + Service service = mServices.get(cmd.activityToken); + if (service != null) { + service.onProvideAssistData(data); + } } if (data.isEmpty()) { data = null; } IActivityManager mgr = ActivityManagerNative.getDefault(); try { - mgr.reportTopActivityExtras(cmd.requestToken, data); + mgr.reportAssistContextExtras(cmd.requestToken, data, cmd.index); } catch (RemoteException e) { } } diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index 6f18e84d6855..df5b4761bdeb 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -599,13 +599,14 @@ public abstract class ApplicationThreadNative extends Binder return true; } - case REQUEST_ACTIVITY_EXTRAS_TRANSACTION: + case REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); IBinder activityToken = data.readStrongBinder(); IBinder requestToken = data.readStrongBinder(); int requestType = data.readInt(); - requestActivityExtras(activityToken, requestToken, requestType); + int index = data.readInt(); + requestAssistContextExtras(activityToken, requestToken, requestType, index); reply.writeNoException(); return true; } @@ -1238,14 +1239,16 @@ class ApplicationThreadProxy implements IApplicationThread { } @Override - public void requestActivityExtras(IBinder activityToken, IBinder requestToken, int requestType) - throws RemoteException { + public void requestAssistContextExtras(IBinder activityToken, IBinder requestToken, + int requestType, int index) 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.writeInt(index); + mRemote.transact(REQUEST_ASSIST_CONTEXT_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 3eda58c6a7c9..3851eb3d8581 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -386,9 +386,10 @@ public interface IActivityManager extends IInterface { public long inputDispatchingTimedOut(int pid, boolean aboveSystem) throws RemoteException; - public Bundle getTopActivityExtras(int requestType) throws RemoteException; + public Bundle getAssistContextExtras(int requestType) throws RemoteException; - public void reportTopActivityExtras(IBinder token, Bundle extras) throws RemoteException; + public void reportAssistContextExtras(IBinder token, Bundle extras, int index) + throws RemoteException; public void killUid(int uid, String reason) throws RemoteException; @@ -662,8 +663,8 @@ 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; + int GET_ASSIST_CONTEXT_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+161; + int REPORT_ASSIST_CONTEXT_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+162; int GET_LAUNCHED_FROM_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+163; int KILL_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+164; int SET_USER_IS_MONKEY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+165; diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index 8e882df40ad2..4b46544011c6 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -132,8 +132,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; + void requestAssistContextExtras(IBinder activityToken, IBinder requestToken, int requestType, + int index) throws RemoteException; void scheduleTranslucentConversionComplete(IBinder token, boolean timeout) throws RemoteException; void setProcessState(int state) throws RemoteException; @@ -186,7 +186,7 @@ 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; + int REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+47; int SCHEDULE_TRANSLUCENT_CONVERSION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+48; int SET_PROCESS_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+49; } diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java index 7dfc589f2541..f9c245ef6dfe 100644 --- a/core/java/android/app/SearchManager.java +++ b/core/java/android/app/SearchManager.java @@ -869,7 +869,7 @@ public class SearchManager intent.setComponent(comp); if (inclContext) { IActivityManager am = ActivityManagerNative.getDefault(); - Bundle extras = am.getTopActivityExtras(0); + Bundle extras = am.getAssistContextExtras(0); if (extras != null) { intent.replaceExtras(extras); } diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java index 396774090515..7f8ddfd7a57d 100644 --- a/core/java/android/app/Service.java +++ b/core/java/android/app/Service.java @@ -23,6 +23,7 @@ import android.content.ContextWrapper; import android.content.Context; import android.content.res.Configuration; import android.os.Build; +import android.os.Bundle; import android.os.RemoteException; import android.os.IBinder; import android.util.Log; @@ -307,6 +308,18 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac } /** + * This is called on foreground services when the user is requesting an assist, to build a + * full {@link Intent#ACTION_ASSIST} Intent with all of the context of the current + * running foreground services. You can override this method to place into the bundle + * anything you would like to appear as an item in the + * {@link Intent#EXTRA_SERVICES_ASSIST_CONTEXT} part of the assist Intent. + * This method will not be called if this service is not in the foreground. + * The default implementation does nothing. + */ + public void onProvideAssistData(Bundle data) { + } + + /** * @deprecated Implement {@link #onStartCommand(Intent, int, int)} instead. */ @Deprecated diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 205ca6bd05d8..ff350b92ab8a 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1152,9 +1152,10 @@ public class Intent implements Parcelable, Cloneable { /** * Activity Action: Perform assist action. * <p> - * 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. + * Input: {@link #EXTRA_ASSIST_PACKAGE}, {@link #EXTRA_ASSIST_CONTEXT}, + * {@link #EXTRA_ASSIST_SERVICES_PACKAGES}, and {@link #EXTRA_ASSIST_SERVICES_CONTEXTS} can + * provide additional optional contextual information about where the user was when they + * requested the assist. * Output: nothing. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) @@ -1163,9 +1164,10 @@ public class Intent implements Parcelable, Cloneable { /** * Activity Action: Perform voice assist action. * <p> - * 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 voice assist. + * Input: {@link #EXTRA_ASSIST_PACKAGE}, {@link #EXTRA_ASSIST_CONTEXT}, + * {@link #EXTRA_ASSIST_SERVICES_PACKAGES}, and {@link #EXTRA_ASSIST_SERVICES_CONTEXTS} can + * provide additional optional contextual information about where the user was when they + * requested the voice assist. * Output: nothing. */ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) @@ -1189,6 +1191,25 @@ public class Intent implements Parcelable, Cloneable { = "android.intent.extra.ASSIST_CONTEXT"; /** + * An optional field on {@link #ACTION_ASSIST} and {@link #ACTION_VOICE_ASSIST} + * containing an the names of the application package of foreground services at the time + * of the assist request. This is an array of {@link String}s, with one entry + * per service. + */ + public static final String EXTRA_ASSIST_SERVICES_PACKAGES + = "android.intent.extra.ASSIST_SERVICES_PACKAGES"; + + /** + * An optional field on {@link #ACTION_ASSIST} and {@link #ACTION_VOICE_ASSIST} + * containing additional contextual information supplied by the current + * foreground services at the time of the assist request. This is an array + * of {@link Bundle}s of additional data, with one {@link Bundle} per service. + */ + public static final String EXTRA_ASSIST_SERVICES_CONTEXTS + = "android.intent.extra.ASSIST_SERVICES_CONTEXTS"; + + + /** * Activity Action: List all available applications * <p>Input: Nothing. * <p>Output: nothing. diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index aaa2640a598b..b4321643204b 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -3005,6 +3005,11 @@ public class PackageParser { s.info.flags = 0; if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestService_provideAssistData, + false)) { + s.info.flags |= ServiceInfo.FLAG_PROVIDE_ASSIST_DATA; + } + if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestService_stopWithTask, false)) { s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK; diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java index 796c2a422921..a57a8536afa6 100644 --- a/core/java/android/content/pm/ServiceInfo.java +++ b/core/java/android/content/pm/ServiceInfo.java @@ -49,6 +49,14 @@ public class ServiceInfo extends ComponentInfo public static final int FLAG_ISOLATED_PROCESS = 0x0002; /** + * Bit in {@link #flags}: If set, + * {@link Service#onProvideAssistData(android.os.Bundle)} will be + * called on the service when it is running in the foreground. Set from + * the {@link android.R.attr#provideAssistData} attribute. + */ + public static final int FLAG_PROVIDE_ASSIST_DATA = 0x0004; + + /** * Bit in {@link #flags}: If set, a single instance of the service will * run for all users on the device. Set from the * {@link android.R.attr#singleUser} attribute. diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 728b1b031754..60ed0e5b515f 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -1379,6 +1379,9 @@ component specific values). --> <attr name="enabled" /> <attr name="exported" /> + <!-- If set to true, onProvideAssistData will be called on this service when this service + is running in the foreground. --> + <attr name="provideAssistData" format="boolean" /> <!-- If set to true, this service with be automatically stopped when the user remove a task rooted in an activity owned by the application. The default is false. --> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index d3dbb2ae3114..f267124a52d3 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -831,8 +831,8 @@ <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> - + about the current application and services 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. --> diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index cb1747f9d755..a164ad127772 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -183,6 +183,7 @@ import java.io.StringWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; @@ -305,8 +306,13 @@ 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; + // How long to wait in getAssistContextExtras for the activity and foreground services + // to respond with the result. + static final int PENDING_ASSIST_EXTRAS_TIMEOUT = 500; + + // Index for assist context bundle pertaining to the top activity. Non-negative indices + // correspond to assist context bundles from foreground services. + static final int TOP_ACTIVITY_ASSIST_EXTRAS_INDEX = -1; static final int MY_PID = Process.myPid(); @@ -382,25 +388,38 @@ public final class ActivityManagerService extends ActivityManagerNative */ private final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>(); - public class PendingActivityExtras extends Binder implements Runnable { + public class PendingAssistExtras extends Binder implements Runnable { public final ActivityRecord activity; - public boolean haveResult = false; - public Bundle result = null; - public PendingActivityExtras(ActivityRecord _activity) { + public final List<ServiceRecord> services; + public int numPending; + public int numRespondedServices = 0; + public Bundle activityExtras = null; + public Bundle[] servicesExtras; + public PendingAssistExtras(ActivityRecord _activity, List<ServiceRecord> _services) { activity = _activity; + services = _services; + numPending = services.size() + 1; } @Override public void run() { - Slog.w(TAG, "getTopActivityExtras failed: timeout retrieving from " + activity); + if (activityExtras == null) { + Slog.w(TAG, "getAssistContextExtras failed: timeout retrieving from " + activity); + } + for (int i = 0; i < services.size(); i++) { + if (servicesExtras[i] == null) { + Slog.w(TAG, "getAssistContextExtras failed: timeout retrieving from " + + services.get(i)); + } + } synchronized (this) { - haveResult = true; + numPending = 0; notifyAll(); } } } - final ArrayList<PendingActivityExtras> mPendingActivityExtras - = new ArrayList<PendingActivityExtras>(); + final ArrayList<PendingAssistExtras> mPendingAssistExtras + = new ArrayList<PendingAssistExtras>(); /** * Process management. @@ -7983,60 +8002,110 @@ public final class ActivityManagerService extends ActivityManagerNative return true; } - public Bundle getTopActivityExtras(int requestType) { + public Bundle getAssistContextExtras(int requestType) { enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO, - "getTopActivityExtras()"); - PendingActivityExtras pae; + "getAssistContextExtras()"); + PendingAssistExtras pae; Bundle extras = new Bundle(); + List<ServiceRecord> foregroundServices; synchronized (this) { + Collection<ServiceRecord> allServices = mServices.mServiceMap.getAllServices( + Binder.getCallingUid()); + foregroundServices = new ArrayList<ServiceRecord>(); + for (ServiceRecord record : allServices) { + if ((record.serviceInfo.flags & ServiceInfo.FLAG_PROVIDE_ASSIST_DATA) > 0 && + record.isForeground) { + if (record.app == null || record.app.thread == null) { + Slog.w(TAG, "getAssistContextExtras error: no process for " + record); + continue; + } + if (record.app.pid == Binder.getCallingPid()) { + Slog.w(TAG, "getAssistContextExtras error: request process same as " + + record); + continue; + } + foregroundServices.add(record); + } + } + ActivityRecord activity = getFocusedStack().mResumedActivity; + boolean validActivity = true; if (activity == null) { - Slog.w(TAG, "getTopActivityExtras failed: no resumed activity"); - return null; + Slog.w(TAG, "getAssistContextExtras error: no resumed activity"); + validActivity = false; } - 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; + Slog.w(TAG, "getAssistContextExtras error: no process for " + activity); + validActivity = false; } if (activity.app.pid == Binder.getCallingPid()) { - Slog.w(TAG, "getTopActivityExtras failed: request process same as " + activity); - return extras; + Slog.w(TAG, "getAssistContextExtras error: request process same as " + activity); + validActivity = false; } - pae = new PendingActivityExtras(activity); + + pae = new PendingAssistExtras(activity, foregroundServices); try { - activity.app.thread.requestActivityExtras(activity.appToken, pae, requestType); - mPendingActivityExtras.add(pae); - mHandler.postDelayed(pae, PENDING_ACTIVITY_RESULT_TIMEOUT); + if (validActivity) { + activity.app.thread.requestAssistContextExtras(activity.appToken, pae, + requestType, -1); + } + for (int i = 0; i < foregroundServices.size(); i++) { + ServiceRecord record = foregroundServices.get(i); + record.app.thread.requestAssistContextExtras(record, pae, requestType, i); + } + mPendingAssistExtras.add(pae); + mHandler.postDelayed(pae, PENDING_ASSIST_EXTRAS_TIMEOUT); } catch (RemoteException e) { - Slog.w(TAG, "getTopActivityExtras failed: crash calling " + activity); - return extras; + Slog.w(TAG, "getAssistContextExtras failed: crash fetching extras.", e); } } synchronized (pae) { - while (!pae.haveResult) { + while (pae.numPending > 0) { try { pae.wait(); } catch (InterruptedException e) { } } - if (pae.result != null) { - extras.putBundle(Intent.EXTRA_ASSIST_CONTEXT, pae.result); + if (pae.activityExtras != null) { + extras.putBundle(Intent.EXTRA_ASSIST_CONTEXT, pae.activityExtras); + extras.putString(Intent.EXTRA_ASSIST_PACKAGE, pae.activity.packageName); + } + if (pae.numRespondedServices > 0) { + Bundle[] servicesExtras = new Bundle[pae.numRespondedServices]; + String[] servicesPackages = new String[pae.numRespondedServices]; + int extrasIndex = 0; + for (int i = 0; i < foregroundServices.size(); i++) { + if (pae.servicesExtras[i] != null) { + servicesExtras[extrasIndex] = pae.servicesExtras[i]; + ServiceRecord record = foregroundServices.get(i); + servicesPackages[extrasIndex] = record.packageName; + extrasIndex++; + } + } + extras.putParcelableArray(Intent.EXTRA_ASSIST_SERVICES_CONTEXTS, servicesExtras); + extras.putStringArray(Intent.EXTRA_ASSIST_SERVICES_PACKAGES, servicesPackages); } } synchronized (this) { - mPendingActivityExtras.remove(pae); + mPendingAssistExtras.remove(pae); mHandler.removeCallbacks(pae); } return extras; } - public void reportTopActivityExtras(IBinder token, Bundle extras) { - PendingActivityExtras pae = (PendingActivityExtras)token; + public void reportAssistContextExtras(IBinder token, Bundle extras, int index) { + PendingAssistExtras pae = (PendingAssistExtras)token; synchronized (pae) { - pae.result = extras; - pae.haveResult = true; - pae.notifyAll(); + if (index == TOP_ACTIVITY_ASSIST_EXTRAS_INDEX) { + pae.activityExtras = extras; + } else { + pae.servicesExtras[index] = extras; + pae.numRespondedServices++; + } + pae.numPending--; + if (pae.numPending == 0) { + pae.notifyAll(); + } } } |