diff options
author | Dianne Hackborn <hackbod@google.com> | 2009-07-14 12:51:00 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2009-07-14 12:51:00 -0700 |
commit | dace230043314d6fab1c5ced4b031eaccd814c25 (patch) | |
tree | 0c2fbb477f5d94641cee6aa892600b6d34bc96d3 /core | |
parent | ae4f31706fa0589ede00dfce344779a1570cd2f3 (diff) | |
parent | b06ea706530e6d19eb2a1a9a7ae6c5dd77d80af0 (diff) | |
download | frameworks_base-dace230043314d6fab1c5ced4b031eaccd814c25.zip frameworks_base-dace230043314d6fab1c5ced4b031eaccd814c25.tar.gz frameworks_base-dace230043314d6fab1c5ced4b031eaccd814c25.tar.bz2 |
resolved conflicts for merge of b06ea706 to master
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/app/Activity.java | 41 | ||||
-rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 50 | ||||
-rw-r--r-- | core/java/android/app/ActivityThread.java | 24 | ||||
-rw-r--r-- | core/java/android/app/ApplicationThreadNative.java | 7 | ||||
-rw-r--r-- | core/java/android/app/IActivityController.aidl | 55 | ||||
-rw-r--r-- | core/java/android/app/IActivityManager.java | 11 | ||||
-rw-r--r-- | core/java/android/app/IActivityWatcher.aidl | 39 | ||||
-rw-r--r-- | core/java/android/app/IApplicationThread.java | 2 | ||||
-rw-r--r-- | core/java/android/app/ISearchManager.aidl | 3 | ||||
-rw-r--r-- | core/java/android/app/SearchDialog.java | 3 | ||||
-rw-r--r-- | core/java/android/app/SearchManager.java | 13 | ||||
-rw-r--r-- | core/java/android/content/SyncStorageEngine.java | 1 | ||||
-rw-r--r-- | core/java/android/os/RemoteCallbackList.java | 24 | ||||
-rw-r--r-- | core/java/android/server/search/SearchDialogWrapper.java | 91 | ||||
-rw-r--r-- | core/java/android/server/search/SearchManagerService.java | 24 |
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 13bcdd3..9d2efb5 100644 --- a/core/java/android/content/SyncStorageEngine.java +++ b/core/java/android/content/SyncStorageEngine.java @@ -326,6 +326,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 5ab305e..b74af16 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 { @@ -196,15 +197,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) { @@ -223,7 +225,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; } @@ -282,12 +289,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); } /** |