am d8ba6cc9: Merge "Add new API to propagate contextual data to the assist action"

# Via Android (Google) Code Review (1) and Dianne Hackborn (1)
* commit 'd8ba6cc9217e2e042106870e9d2e70cfd80426d6':
  Add new API to propagate contextual data to the assist action
This commit is contained in:
Dianne Hackborn
2013-01-23 14:51:07 -08:00
committed by Android Git Automerger
20 changed files with 322 additions and 16 deletions

View File

@ -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";

View File

@ -1345,6 +1345,20 @@ public class Activity extends ContextThemeWrapper
return null;
}
/**
* 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,

View File

@ -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;
}

View File

@ -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>();
/**

View File

@ -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);
}
}
}
}

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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.

View File

@ -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 {

View File

@ -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. -->

View File

@ -783,6 +783,12 @@
<string name="permdesc_stopAppSwitches">Prevents the user from switching to
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. -->

View File

@ -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" />

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;
}
}

View File

@ -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()");