summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2009-07-13 13:07:51 -0700
committerDianne Hackborn <hackbod@google.com>2009-07-14 11:37:11 -0700
commitb06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0 (patch)
tree2fcae8f89195ef4b162627892aeca97f06d42ef7 /core/java
parent3660c09500a4d01eb6a733b5f0b15545855f8fe8 (diff)
downloadframeworks_base-b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0.zip
frameworks_base-b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0.tar.gz
frameworks_base-b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0.tar.bz2
Add reporting of activity movement for search manager.
This adds a new API with the activity manager to find out about movement between activities. For my sanity, the old IActivityWatcher is now renamed to IActivityController, and the new activity movement interface is named IActivityWatcher. This changes the search manager itself to use the new API to manage its state. Note that there are still problems when going back to the search dialog after it was hidden -- the suggestions window no longer appears until you explicitly dismiss and re-show it.
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/Activity.java41
-rw-r--r--core/java/android/app/ActivityManagerNative.java50
-rw-r--r--core/java/android/app/ActivityThread.java24
-rw-r--r--core/java/android/app/ApplicationThreadNative.java7
-rw-r--r--core/java/android/app/IActivityController.aidl55
-rw-r--r--core/java/android/app/IActivityManager.java11
-rw-r--r--core/java/android/app/IActivityWatcher.aidl39
-rw-r--r--core/java/android/app/IApplicationThread.java2
-rw-r--r--core/java/android/app/ISearchManager.aidl3
-rw-r--r--core/java/android/app/SearchDialog.java3
-rw-r--r--core/java/android/app/SearchManager.java13
-rw-r--r--core/java/android/content/SyncStorageEngine.java1
-rw-r--r--core/java/android/os/RemoteCallbackList.java24
-rw-r--r--core/java/android/server/search/SearchDialogWrapper.java91
-rw-r--r--core/java/android/server/search/SearchManagerService.java24
15 files changed, 287 insertions, 101 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 6c2560d..4ac3b9e 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -612,6 +612,7 @@ public class Activity extends ContextThemeWrapper
// set by the thread after the constructor and before onCreate(Bundle savedInstanceState) is called.
private Instrumentation mInstrumentation;
private IBinder mToken;
+ private int mIdent;
/*package*/ String mEmbeddedID;
private Application mApplication;
/*package*/ Intent mIntent;
@@ -789,9 +790,6 @@ public class Activity extends ContextThemeWrapper
protected void onCreate(Bundle savedInstanceState) {
mVisibleFromClient = mWindow.getWindowStyle().getBoolean(
com.android.internal.R.styleable.Window_windowNoDisplay, true);
- // uses super.getSystemService() since this.getSystemService() looks at the
- // mSearchManager field.
- mSearchManager = (SearchManager) super.getSystemService(Context.SEARCH_SERVICE);
mCalled = true;
}
@@ -2531,6 +2529,7 @@ public class Activity extends ContextThemeWrapper
*/
public void startSearch(String initialQuery, boolean selectInitialQuery,
Bundle appSearchData, boolean globalSearch) {
+ ensureSearchManager();
mSearchManager.startSearch(initialQuery, selectInitialQuery, getComponentName(),
appSearchData, globalSearch);
}
@@ -3241,6 +3240,24 @@ public class Activity extends ContextThemeWrapper
return getSharedPreferences(getLocalClassName(), mode);
}
+ private void ensureSearchManager() {
+ if (mSearchManager != null) {
+ return;
+ }
+
+ // uses super.getSystemService() since this.getSystemService() looks at the
+ // mSearchManager field.
+ mSearchManager = (SearchManager) super.getSystemService(Context.SEARCH_SERVICE);
+ int ident = mIdent;
+ if (ident == 0) {
+ if (mParent != null) ident = mParent.mIdent;
+ if (ident == 0) {
+ throw new IllegalArgumentException("no ident");
+ }
+ }
+ mSearchManager.setIdent(ident);
+ }
+
@Override
public Object getSystemService(String name) {
if (getBaseContext() == null) {
@@ -3251,6 +3268,7 @@ public class Activity extends ContextThemeWrapper
if (WINDOW_SERVICE.equals(name)) {
return mWindowManager;
} else if (SEARCH_SERVICE.equals(name)) {
+ ensureSearchManager();
return mSearchManager;
}
return super.getSystemService(name);
@@ -3450,14 +3468,17 @@ public class Activity extends ContextThemeWrapper
Application application, Intent intent, ActivityInfo info, CharSequence title,
Activity parent, String id, Object lastNonConfigurationInstance,
Configuration config) {
- attach(context, aThread, instr, token, application, intent, info, title, parent, id,
+ attach(context, aThread, instr, token, 0, application, intent, info, title, parent, id,
lastNonConfigurationInstance, null, config);
}
- final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token,
- Application application, Intent intent, ActivityInfo info, CharSequence title,
- Activity parent, String id, Object lastNonConfigurationInstance,
- HashMap<String,Object> lastNonConfigurationChildInstances, Configuration config) {
+ final void attach(Context context, ActivityThread aThread,
+ Instrumentation instr, IBinder token, int ident,
+ Application application, Intent intent, ActivityInfo info,
+ CharSequence title, Activity parent, String id,
+ Object lastNonConfigurationInstance,
+ HashMap<String,Object> lastNonConfigurationChildInstances,
+ Configuration config) {
attachBaseContext(context);
mWindow = PolicyManager.makeNewWindow(this);
@@ -3470,6 +3491,7 @@ public class Activity extends ContextThemeWrapper
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
+ mIdent = ident;
mApplication = application;
mIntent = intent;
mComponent = intent.getComponent();
@@ -3554,9 +3576,6 @@ public class Activity extends ContextThemeWrapper
final void performPause() {
onPause();
-
- // dismiss the search dialog if it is open
- mSearchManager.stopSearch();
}
final void performUserLeaving() {
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index dfa8139..ec7714d 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -881,11 +881,11 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
- case SET_ACTIVITY_WATCHER_TRANSACTION: {
+ case SET_ACTIVITY_CONTROLLER_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
- IActivityWatcher watcher = IActivityWatcher.Stub.asInterface(
+ IActivityController watcher = IActivityController.Stub.asInterface(
data.readStrongBinder());
- setActivityWatcher(watcher);
+ setActivityController(watcher);
return true;
}
@@ -1052,6 +1052,22 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeNoException();
return true;
}
+
+ case REGISTER_ACTIVITY_WATCHER_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IActivityWatcher watcher = IActivityWatcher.Stub.asInterface(
+ data.readStrongBinder());
+ registerActivityWatcher(watcher);
+ return true;
+ }
+
+ case UNREGISTER_ACTIVITY_WATCHER_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IActivityWatcher watcher = IActivityWatcher.Stub.asInterface(
+ data.readStrongBinder());
+ unregisterActivityWatcher(watcher);
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -2105,13 +2121,13 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
reply.recycle();
}
- public void setActivityWatcher(IActivityWatcher watcher) throws RemoteException
+ public void setActivityController(IActivityController watcher) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(watcher != null ? watcher.asBinder() : null);
- mRemote.transact(SET_ACTIVITY_WATCHER_TRANSACTION, data, reply, 0);
+ mRemote.transact(SET_ACTIVITY_CONTROLLER_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
@@ -2290,5 +2306,29 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
}
+ public void registerActivityWatcher(IActivityWatcher watcher)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(watcher != null ? watcher.asBinder() : null);
+ mRemote.transact(REGISTER_ACTIVITY_WATCHER_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
+ public void unregisterActivityWatcher(IActivityWatcher watcher)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(watcher != null ? watcher.asBinder() : null);
+ mRemote.transact(UNREGISTER_ACTIVITY_WATCHER_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 27e8fb5..f2814f2 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1090,6 +1090,7 @@ public final class ActivityThread {
private static final class ActivityRecord {
IBinder token;
+ int ident;
Intent intent;
Bundle state;
Activity activity;
@@ -1299,12 +1300,13 @@ public final class ActivityThread {
// we use token to identify this activity without having to send the
// activity itself back to the activity manager. (matters more with ipc)
- public final void scheduleLaunchActivity(Intent intent, IBinder token,
+ public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward) {
ActivityRecord r = new ActivityRecord();
r.token = token;
+ r.ident = ident;
r.intent = intent;
r.activityInfo = info;
r.state = state;
@@ -2197,21 +2199,11 @@ public final class ActivityThread {
}
public final Activity startActivityNow(Activity parent, String id,
- Intent intent, IBinder token, Bundle state) {
- ActivityInfo aInfo = resolveActivityInfo(intent);
- return startActivityNow(parent, id, intent, aInfo, token, state);
- }
-
- public final Activity startActivityNow(Activity parent, String id,
- Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state) {
- return startActivityNow(parent, id, intent, activityInfo, token, state, null);
- }
-
- public final Activity startActivityNow(Activity parent, String id,
Intent intent, ActivityInfo activityInfo, IBinder token, Bundle state,
Object lastNonConfigurationInstance) {
ActivityRecord r = new ActivityRecord();
r.token = token;
+ r.ident = 0;
r.intent = intent;
r.state = state;
r.parent = parent;
@@ -2335,10 +2327,10 @@ public final class ActivityThread {
appContext.setOuterContext(activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mConfiguration);
- activity.attach(appContext, this, getInstrumentation(), r.token, app,
- r.intent, r.activityInfo, title, r.parent, r.embeddedID,
- r.lastNonConfigurationInstance, r.lastNonConfigurationChildInstances,
- config);
+ activity.attach(appContext, this, getInstrumentation(), r.token,
+ r.ident, app, r.intent, r.activityInfo, title, r.parent,
+ r.embeddedID, r.lastNonConfigurationInstance,
+ r.lastNonConfigurationChildInstances, config);
if (customIntent != null) {
activity.mIntent = customIntent;
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index b052c99..a3c6325 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -119,13 +119,15 @@ public abstract class ApplicationThreadNative extends Binder
data.enforceInterface(IApplicationThread.descriptor);
Intent intent = Intent.CREATOR.createFromParcel(data);
IBinder b = data.readStrongBinder();
+ int ident = data.readInt();
ActivityInfo info = ActivityInfo.CREATOR.createFromParcel(data);
Bundle state = data.readBundle();
List<ResultInfo> ri = data.createTypedArrayList(ResultInfo.CREATOR);
List<Intent> pi = data.createTypedArrayList(Intent.CREATOR);
boolean notResumed = data.readInt() != 0;
boolean isForward = data.readInt() != 0;
- scheduleLaunchActivity(intent, b, info, state, ri, pi, notResumed, isForward);
+ scheduleLaunchActivity(intent, b, ident, info, state, ri, pi,
+ notResumed, isForward);
return true;
}
@@ -442,7 +444,7 @@ class ApplicationThreadProxy implements IApplicationThread {
data.recycle();
}
- public final void scheduleLaunchActivity(Intent intent, IBinder token,
+ public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward)
throws RemoteException {
@@ -450,6 +452,7 @@ class ApplicationThreadProxy implements IApplicationThread {
data.writeInterfaceToken(IApplicationThread.descriptor);
intent.writeToParcel(data, 0);
data.writeStrongBinder(token);
+ data.writeInt(ident);
info.writeToParcel(data, 0);
data.writeBundle(state);
data.writeTypedList(pendingResults);
diff --git a/core/java/android/app/IActivityController.aidl b/core/java/android/app/IActivityController.aidl
new file mode 100644
index 0000000..8f6b252
--- /dev/null
+++ b/core/java/android/app/IActivityController.aidl
@@ -0,0 +1,55 @@
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.app;
+
+import android.content.Intent;
+
+/**
+ * Testing interface to monitor what is happening in the activity manager
+ * while tests are running. Not for normal application development.
+ * {@hide}
+ */
+interface IActivityController
+{
+ /**
+ * The system is trying to start an activity. Return true to allow
+ * it to be started as normal, or false to cancel/reject this activity.
+ */
+ boolean activityStarting(in Intent intent, String pkg);
+
+ /**
+ * The system is trying to return to an activity. Return true to allow
+ * it to be resumed as normal, or false to cancel/reject this activity.
+ */
+ boolean activityResuming(String pkg);
+
+ /**
+ * An application process has crashed (in Java). Return true for the
+ * normal error recovery (app crash dialog) to occur, false to kill
+ * it immediately.
+ */
+ boolean appCrashed(String processName, int pid, String shortMsg,
+ String longMsg, in byte[] crashData);
+
+ /**
+ * An application process is not responding. Return 0 to show the "app
+ * not responding" dialog, 1 to continue waiting, or -1 to kill it
+ * immediately.
+ */
+ int appNotResponding(String processName, int pid, String processStats);
+}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 3ec7938..ee1b69b 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -216,7 +216,7 @@ public interface IActivityManager extends IInterface {
String packageName, boolean waitForDebugger, boolean persistent)
throws RemoteException;
public void setAlwaysFinish(boolean enabled) throws RemoteException;
- public void setActivityWatcher(IActivityWatcher watcher)
+ public void setActivityController(IActivityController watcher)
throws RemoteException;
public void enterSafeMode() throws RemoteException;
@@ -257,6 +257,11 @@ public interface IActivityManager extends IInterface {
public void stopAppSwitches() throws RemoteException;
public void resumeAppSwitches() throws RemoteException;
+ public void registerActivityWatcher(IActivityWatcher watcher)
+ throws RemoteException;
+ public void unregisterActivityWatcher(IActivityWatcher watcher)
+ throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -372,7 +377,7 @@ public interface IActivityManager extends IInterface {
int CHECK_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+53;
int GRANT_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+54;
int REVOKE_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+55;
- int SET_ACTIVITY_WATCHER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+56;
+ int SET_ACTIVITY_CONTROLLER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+56;
int SHOW_WAITING_FOR_DEBUGGER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+57;
int SIGNAL_PERSISTENT_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+58;
int GET_RECENT_TASKS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+59;
@@ -408,4 +413,6 @@ public interface IActivityManager extends IInterface {
int START_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+89;
int BACKUP_AGENT_CREATED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+90;
int UNBIND_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+91;
+ int REGISTER_ACTIVITY_WATCHER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+92;
+ int UNREGISTER_ACTIVITY_WATCHER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+93;
}
diff --git a/core/java/android/app/IActivityWatcher.aidl b/core/java/android/app/IActivityWatcher.aidl
index f13a385..5d36e3f 100644
--- a/core/java/android/app/IActivityWatcher.aidl
+++ b/core/java/android/app/IActivityWatcher.aidl
@@ -1,6 +1,6 @@
-/* //device/java/android/android/app/IInstrumentationWatcher.aidl
+/*
**
-** Copyright 2007, The Android Open Source Project
+** Copyright 2009, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
@@ -17,39 +17,10 @@
package android.app;
-import android.content.Intent;
-
/**
- * Testing interface to monitor what is happening in the activity manager
- * while tests are running. Not for normal application development.
+ * Callback interface to watch the user's traversal through activities.
* {@hide}
*/
-interface IActivityWatcher
-{
- /**
- * The system is trying to start an activity. Return true to allow
- * it to be started as normal, or false to cancel/reject this activity.
- */
- boolean activityStarting(in Intent intent, String pkg);
-
- /**
- * The system is trying to return to an activity. Return true to allow
- * it to be resumed as normal, or false to cancel/reject this activity.
- */
- boolean activityResuming(String pkg);
-
- /**
- * An application process has crashed (in Java). Return true for the
- * normal error recovery (app crash dialog) to occur, false to kill
- * it immediately.
- */
- boolean appCrashed(String processName, int pid, String shortMsg,
- String longMsg, in byte[] crashData);
-
- /**
- * An application process is not responding. Return 0 to show the "app
- * not responding" dialog, 1 to continue waiting, or -1 to kill it
- * immediately.
- */
- int appNotResponding(String processName, int pid, String processStats);
+oneway interface IActivityWatcher {
+ void activityResuming(int activityId);
}
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index c0bc2a0..c915770 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -49,7 +49,7 @@ public interface IApplicationThread extends IInterface {
void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;
void scheduleResumeActivity(IBinder token, boolean isForward) throws RemoteException;
void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;
- void scheduleLaunchActivity(Intent intent, IBinder token,
+ void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward)
throws RemoteException;
diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl
index 5b62192..84a6085 100644
--- a/core/java/android/app/ISearchManager.aidl
+++ b/core/java/android/app/ISearchManager.aidl
@@ -34,6 +34,7 @@ interface ISearchManager {
in ComponentName launchActivity,
in Bundle appSearchData,
boolean globalSearch,
- ISearchManagerCallback searchManagerCallback);
+ ISearchManagerCallback searchManagerCallback,
+ int ident);
void stopSearch();
}
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 9f44c7e..13eb034 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -752,6 +752,9 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
}
public void afterTextChanged(Editable s) {
+ if (mSearchable == null) {
+ return;
+ }
if (mSearchable.autoUrlDetect() && !mSearchAutoComplete.isPerformingCompletion()) {
// The user changed the query, check if it is a URL and if so change the search
// button in the soft keyboard to the 'Go' button.
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 0291882..b795a54 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1531,6 +1531,8 @@ public class SearchManager
private final Context mContext;
+ private int mIdent;
+
// package private since they are used by the inner class SearchManagerCallback
/* package */ boolean mIsShowing = false;
/* package */ final Handler mHandler;
@@ -1546,6 +1548,13 @@ public class SearchManager
ServiceManager.getService(Context.SEARCH_SERVICE));
}
+ /*package*/ void setIdent(int ident) {
+ if (mIdent != 0) {
+ throw new IllegalStateException("mIdent already set");
+ }
+ mIdent = ident;
+ }
+
/**
* Launch search UI.
*
@@ -1593,11 +1602,13 @@ public class SearchManager
boolean globalSearch) {
if (DBG) debug("startSearch(), mIsShowing=" + mIsShowing);
if (mIsShowing) return;
+ if (mIdent == 0) throw new IllegalArgumentException(
+ "Called from outside of an Activity context");
try {
mIsShowing = true;
// activate the search manager and start it up!
mService.startSearch(initialQuery, selectInitialQuery, launchActivity, appSearchData,
- globalSearch, mSearchManagerCallback);
+ globalSearch, mSearchManagerCallback, mIdent);
} catch (RemoteException ex) {
Log.e(TAG, "startSearch() failed: " + ex);
}
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index f781e0d..756f35c 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -338,6 +338,7 @@ public class SyncStorageEngine extends Handler {
}
reports.add(mChangeListeners.getBroadcastItem(i));
}
+ mChangeListeners.finishBroadcast();
}
if (DEBUG) Log.v(TAG, "reportChange " + which + " to: " + reports);
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index 23c0a7b..584224f 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -50,6 +50,7 @@ public class RemoteCallbackList<E extends IInterface> {
/*package*/ HashMap<IBinder, Callback> mCallbacks
= new HashMap<IBinder, Callback>();
private Object[] mActiveBroadcast;
+ private int mBroadcastCount = -1;
private boolean mKilled = false;
private final class Callback implements IBinder.DeathRecipient {
@@ -195,15 +196,16 @@ public class RemoteCallbackList<E extends IInterface> {
* This creates a copy of the callback list, which you can retrieve items
* from using {@link #getBroadcastItem}. Note that only one broadcast can
* be active at a time, so you must be sure to always call this from the
- * same thread (usually by scheduling with {@link Handler} or
+ * same thread (usually by scheduling with {@link Handler}) or
* do your own synchronization. You must call {@link #finishBroadcast}
* when done.
*
* <p>A typical loop delivering a broadcast looks like this:
*
* <pre>
- * final int N = callbacks.beginBroadcast();
- * for (int i=0; i<N; i++) {
+ * int i = callbacks.beginBroadcast();
+ * while (i > 0) {
+ * i--;
* try {
* callbacks.getBroadcastItem(i).somethingHappened();
* } catch (RemoteException e) {
@@ -222,7 +224,12 @@ public class RemoteCallbackList<E extends IInterface> {
*/
public int beginBroadcast() {
synchronized (mCallbacks) {
- final int N = mCallbacks.size();
+ if (mBroadcastCount > 0) {
+ throw new IllegalStateException(
+ "beginBroadcast() called while already in a broadcast");
+ }
+
+ final int N = mBroadcastCount = mCallbacks.size();
if (N <= 0) {
return 0;
}
@@ -281,12 +288,19 @@ public class RemoteCallbackList<E extends IInterface> {
* @see #beginBroadcast
*/
public void finishBroadcast() {
+ if (mBroadcastCount < 0) {
+ throw new IllegalStateException(
+ "finishBroadcast() called outside of a broadcast");
+ }
+
Object[] active = mActiveBroadcast;
if (active != null) {
- final int N = active.length;
+ final int N = mBroadcastCount;
for (int i=0; i<N; i++) {
active[i] = null;
}
}
+
+ mBroadcastCount = -1;
}
}
diff --git a/core/java/android/server/search/SearchDialogWrapper.java b/core/java/android/server/search/SearchDialogWrapper.java
index dbc1e7f..67be6a6 100644
--- a/core/java/android/server/search/SearchDialogWrapper.java
+++ b/core/java/android/server/search/SearchDialogWrapper.java
@@ -63,12 +63,13 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
private static final int MSG_START_SEARCH = 1;
// Takes no arguments
private static final int MSG_STOP_SEARCH = 2;
- // Takes no arguments
- private static final int MSG_ON_CONFIGURATION_CHANGED = 3;
+ // arg1 is activity id
+ private static final int MSG_ACTIVITY_RESUMING = 3;
private static final String KEY_INITIAL_QUERY = "q";
private static final String KEY_LAUNCH_ACTIVITY = "a";
private static final String KEY_APP_SEARCH_DATA = "d";
+ private static final String KEY_IDENT= "i";
// Context used for getting search UI resources
private final Context mContext;
@@ -82,9 +83,18 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
// If the search UI is visible, this is the callback for the client that showed it.
ISearchManagerCallback mCallback = null;
+ // Identity of last activity that started search.
+ private int mStartedIdent = 0;
+
+ // Identity of currently resumed activity.
+ private int mResumedIdent = 0;
+
// Allows disabling of search dialog for stress testing runs
private final boolean mDisabledOnBoot;
+ // True if we have registered our receivers.
+ private boolean mReceiverRegistered;
+
/**
* Creates a new search dialog wrapper and a search UI thread. The search dialog itself will
* be created some asynchronously on the search UI thread.
@@ -116,15 +126,21 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
}
private void registerBroadcastReceiver() {
- IntentFilter closeDialogsFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
- mContext.registerReceiver(mBroadcastReceiver, closeDialogsFilter);
- IntentFilter configurationChangedFilter =
- new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED);
- mContext.registerReceiver(mBroadcastReceiver, configurationChangedFilter);
+ if (!mReceiverRegistered) {
+ IntentFilter filter = new IntentFilter(
+ Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+ mContext.registerReceiver(mBroadcastReceiver, filter, null,
+ mSearchUiThread);
+ mReceiverRegistered = true;
+ }
}
private void unregisterBroadcastReceiver() {
- mContext.unregisterReceiver(mBroadcastReceiver);
+ if (mReceiverRegistered) {
+ mContext.unregisterReceiver(mBroadcastReceiver);
+ mReceiverRegistered = false;
+ }
}
/**
@@ -136,10 +152,10 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
String action = intent.getAction();
if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
if (DBG) debug(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
- stopSearch();
+ performStopSearch();
} else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
if (DBG) debug(Intent.ACTION_CONFIGURATION_CHANGED);
- onConfigurationChanged();
+ performOnConfigurationChanged();
}
}
};
@@ -159,7 +175,8 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
final ComponentName launchActivity,
final Bundle appSearchData,
final boolean globalSearch,
- final ISearchManagerCallback searchManagerCallback) {
+ final ISearchManagerCallback searchManagerCallback,
+ int ident) {
if (DBG) debug("startSearch()");
Message msg = Message.obtain();
msg.what = MSG_START_SEARCH;
@@ -170,6 +187,7 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
msgData.putString(KEY_INITIAL_QUERY, initialQuery);
msgData.putParcelable(KEY_LAUNCH_ACTIVITY, launchActivity);
msgData.putBundle(KEY_APP_SEARCH_DATA, appSearchData);
+ msgData.putInt(KEY_IDENT, ident);
mSearchUiThread.sendMessage(msg);
}
@@ -183,12 +201,15 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
}
/**
- * Updates the search UI in response to a configuration change.
+ * Updates the currently resumed activity.
* Can be called from any thread.
*/
- void onConfigurationChanged() {
- if (DBG) debug("onConfigurationChanged()");
- mSearchUiThread.sendEmptyMessage(MSG_ON_CONFIGURATION_CHANGED);
+ public void activityResuming(int ident) {
+ if (DBG) debug("startSearch()");
+ Message msg = Message.obtain();
+ msg.what = MSG_ACTIVITY_RESUMING;
+ msg.arg1 = ident;
+ mSearchUiThread.sendMessage(msg);
}
//
@@ -213,8 +234,8 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
case MSG_STOP_SEARCH:
performStopSearch();
break;
- case MSG_ON_CONFIGURATION_CHANGED:
- performOnConfigurationChanged();
+ case MSG_ACTIVITY_RESUMING:
+ performActivityResuming(msg.arg1);
break;
}
}
@@ -228,12 +249,27 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
Bundle appSearchData = msgData.getBundle(KEY_APP_SEARCH_DATA);
boolean globalSearch = msg.arg2 != 0;
ISearchManagerCallback searchManagerCallback = (ISearchManagerCallback) msg.obj;
+ int ident = msgData.getInt(KEY_IDENT);
performStartSearch(initialQuery, selectInitialQuery, launchActivity,
- appSearchData, globalSearch, searchManagerCallback);
+ appSearchData, globalSearch, searchManagerCallback, ident);
}
}
+ void updateDialogVisibility() {
+ if (mStartedIdent != 0) {
+ // mResumedIdent == 0 means we have just booted and the user
+ // hasn't yet gone anywhere.
+ if (mResumedIdent == 0 || mStartedIdent == mResumedIdent) {
+ if (DBG) Log.v(TAG, "******************* DIALOG: show");
+ mSearchDialog.show();
+ } else {
+ if (DBG) Log.v(TAG, "******************* DIALOG: hide");
+ mSearchDialog.hide();
+ }
+ }
+ }
+
/**
* Actually launches the search UI.
* This must be called on the search UI thread.
@@ -243,7 +279,8 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
ComponentName launchActivity,
Bundle appSearchData,
boolean globalSearch,
- ISearchManagerCallback searchManagerCallback) {
+ ISearchManagerCallback searchManagerCallback,
+ int ident) {
if (DBG) debug("performStartSearch()");
if (mDisabledOnBoot) {
@@ -254,8 +291,11 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
registerBroadcastReceiver();
mCallback = searchManagerCallback;
+ mStartedIdent = ident;
+ if (DBG) Log.v(TAG, "******************* DIALOG: start");
mSearchDialog.show(initialQuery, selectInitialQuery, launchActivity, appSearchData,
globalSearch);
+ updateDialogVisibility();
}
/**
@@ -264,7 +304,20 @@ implements DialogInterface.OnCancelListener, DialogInterface.OnDismissListener {
*/
void performStopSearch() {
if (DBG) debug("performStopSearch()");
+ if (DBG) Log.v(TAG, "******************* DIALOG: cancel");
mSearchDialog.cancel();
+ mStartedIdent = 0;
+ }
+
+ /**
+ * Updates the resumed activity
+ * This must be called on the search UI thread.
+ */
+ void performActivityResuming(int ident) {
+ if (DBG) debug("performResumingActivity(): mStartedIdent="
+ + mStartedIdent + ", resuming: " + ident);
+ this.mResumedIdent = ident;
+ updateDialogVisibility();
}
/**
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index f9c0f1a..7629912 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -16,6 +16,8 @@
package android.server.search;
+import android.app.ActivityManagerNative;
+import android.app.IActivityWatcher;
import android.app.ISearchManager;
import android.app.ISearchManagerCallback;
import android.app.SearchManager;
@@ -26,6 +28,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
+import android.os.RemoteException;
import android.util.Log;
import java.util.List;
@@ -71,8 +74,11 @@ public class SearchManagerService extends ISearchManager.Stub {
* Initializes the list of searchable activities and the search UI.
*/
void initialize() {
- ensureSearchablesCreated();
- ensureSearchDialogCreated();
+ try {
+ ActivityManagerNative.getDefault().registerActivityWatcher(
+ mActivityWatcher);
+ } catch (RemoteException e) {
+ }
}
private synchronized void ensureSearchablesCreated() {
@@ -126,6 +132,14 @@ public class SearchManagerService extends ISearchManager.Stub {
}
};
+ private IActivityWatcher.Stub mActivityWatcher = new IActivityWatcher.Stub() {
+ public void activityResuming(int activityId) throws RemoteException {
+ if (DBG) Log.i("foo", "********************** resuming: " + activityId);
+ if (mSearchDialog == null) return;
+ mSearchDialog.activityResuming(activityId);
+ }
+ };
+
/**
* Informs all listeners that the list of searchables has been updated.
*/
@@ -206,13 +220,15 @@ public class SearchManagerService extends ISearchManager.Stub {
ComponentName launchActivity,
Bundle appSearchData,
boolean globalSearch,
- ISearchManagerCallback searchManagerCallback) {
+ ISearchManagerCallback searchManagerCallback,
+ int ident) {
getSearchDialog().startSearch(initialQuery,
selectInitialQuery,
launchActivity,
appSearchData,
globalSearch,
- searchManagerCallback);
+ searchManagerCallback,
+ ident);
}
/**