summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk7
-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
-rw-r--r--core/java/android/widget/FastScroller.java11
-rw-r--r--core/jni/android_hardware_Camera.cpp9
-rwxr-xr-xpackages/TtsService/src/android/tts/TtsService.java127
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java84
-rw-r--r--tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java4
21 files changed, 443 insertions, 187 deletions
diff --git a/Android.mk b/Android.mk
index f32129e..038af0d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -67,10 +67,11 @@ LOCAL_SRC_FILES += \
core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl \
core/java/android/accessibilityservice/IEventListener.aidl \
core/java/android/accounts/IAccountsService.aidl \
+ core/java/android/app/IActivityController.aidl \
core/java/android/app/IActivityPendingResult.aidl \
core/java/android/app/IActivityWatcher.aidl \
core/java/android/app/IAlarmManager.aidl \
- core/java/android/app/IBackupAgent.aidl \
+ core/java/android/app/IBackupAgent.aidl \
core/java/android/app/IInstrumentationWatcher.aidl \
core/java/android/app/INotificationManager.aidl \
core/java/android/app/ISearchManager.aidl \
@@ -88,12 +89,12 @@ LOCAL_SRC_FILES += \
core/java/android/bluetooth/IBluetoothDevice.aidl \
core/java/android/bluetooth/IBluetoothDeviceCallback.aidl \
core/java/android/bluetooth/IBluetoothHeadset.aidl \
- core/java/android/content/IContentService.aidl \
+ core/java/android/content/IContentService.aidl \
core/java/android/content/IIntentReceiver.aidl \
core/java/android/content/IIntentSender.aidl \
core/java/android/content/ISyncAdapter.aidl \
core/java/android/content/ISyncContext.aidl \
- core/java/android/content/ISyncStatusObserver.aidl \
+ core/java/android/content/ISyncStatusObserver.aidl \
core/java/android/content/pm/IPackageDataObserver.aidl \
core/java/android/content/pm/IPackageDeleteObserver.aidl \
core/java/android/content/pm/IPackageInstallObserver.aidl \
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);
}
/**
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index cd965fc..2da777a 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -26,6 +26,7 @@ import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.SystemClock;
+import android.util.TypedValue;
import android.view.MotionEvent;
/**
@@ -116,17 +117,19 @@ class FastScroller {
mThumbDrawable.setAlpha(ScrollFade.ALPHA_MAX);
}
- private void useThumbDrawable(Drawable drawable) {
+ private void useThumbDrawable(Context context, Drawable drawable) {
mThumbDrawable = drawable;
- mThumbW = 64; //mCurrentThumb.getIntrinsicWidth();
- mThumbH = 52; //mCurrentThumb.getIntrinsicHeight();
+ mThumbW = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ 64, context.getResources().getDisplayMetrics());
+ mThumbH = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ 52, context.getResources().getDisplayMetrics());
mChangedBounds = true;
}
private void init(Context context) {
// Get both the scrollbar states drawables
final Resources res = context.getResources();
- useThumbDrawable(res.getDrawable(
+ useThumbDrawable(context, res.getDrawable(
com.android.internal.R.drawable.scrollbar_handle_accelerated_anim2));
mOverlayDrawable = res.getDrawable(
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 85408d0..e9f8ea1 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -29,15 +29,6 @@
using namespace android;
-enum CallbackMessageID {
- kShutterCallback = 0,
- kRawCallback = 1,
- kJpegCallback = 2,
- kPreviewCallback = 3,
- kAutoFocusCallback = 4,
- kErrorCallback = 5
-};
-
struct fields_t {
jfieldID context;
jfieldID surface;
diff --git a/packages/TtsService/src/android/tts/TtsService.java b/packages/TtsService/src/android/tts/TtsService.java
index 09bb8f9..4d25183 100755
--- a/packages/TtsService/src/android/tts/TtsService.java
+++ b/packages/TtsService/src/android/tts/TtsService.java
@@ -69,13 +69,15 @@ public class TtsService extends Service implements OnCompletionListener {
mCallingApp = source;
}
- public SpeechItem(String source, long silenceTime) {
+ public SpeechItem(String source, long silenceTime, ArrayList<String> params) {
mDuration = silenceTime;
+ mParams = params;
mType = SILENCE;
mCallingApp = source;
}
- public SpeechItem(String source, String text, ArrayList<String> params, int itemType, String filename) {
+ public SpeechItem(String source, String text, ArrayList<String> params,
+ int itemType, String filename) {
mText = text;
mParams = params;
mType = itemType;
@@ -117,14 +119,17 @@ public class TtsService extends Service implements OnCompletionListener {
private static final String CATEGORY = "android.intent.category.TTS";
private static final String PKGNAME = "android.tts";
- private final RemoteCallbackList<android.speech.tts.ITtsCallback> mCallbacks = new RemoteCallbackList<ITtsCallback>();
- private HashMap<String, android.speech.tts.ITtsCallback> mCallbacksMap;
+ private final RemoteCallbackList<ITtsCallback> mCallbacks
+ = new RemoteCallbackList<ITtsCallback>();
+
+ private HashMap<String, ITtsCallback> mCallbacksMap;
private Boolean mIsSpeaking;
private ArrayList<SpeechItem> mSpeechQueue;
private HashMap<String, SoundResource> mEarcons;
private HashMap<String, SoundResource> mUtterances;
private MediaPlayer mPlayer;
+ private SpeechItem mCurrentSpeechItem;
private TtsService mSelf;
private ContentResolver mResolver;
@@ -152,6 +157,7 @@ public class TtsService extends Service implements OnCompletionListener {
mSpeechQueue = new ArrayList<SpeechItem>();
mPlayer = null;
+ mCurrentSpeechItem = null;
setDefaultSettings();
}
@@ -401,6 +407,7 @@ public class TtsService extends Service implements OnCompletionListener {
} finally {
// This check is needed because finally will always run; even if the
// method returns somewhere in the try block.
+ mCurrentSpeechItem = null;
if (speechQueueAvailable) {
speechQueueLock.unlock();
}
@@ -409,6 +416,21 @@ public class TtsService extends Service implements OnCompletionListener {
}
public void onCompletion(MediaPlayer arg0) {
+ String callingApp = mCurrentSpeechItem.mCallingApp;
+ ArrayList<String> params = mCurrentSpeechItem.mParams;
+ String utteranceId = "";
+ if (params != null){
+ for (int i = 0; i < params.size() - 1; i = i + 2){
+ String param = params.get(i);
+ if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_UTTERANCE_ID)){
+ utteranceId = params.get(i+1);
+ }
+ }
+ }
+ if (utteranceId.length() > 0){
+ dispatchUtteranceCompletedCallback(utteranceId, callingApp);
+ }
+ mCurrentSpeechItem = null;
processSpeechQueue();
}
@@ -417,21 +439,34 @@ public class TtsService extends Service implements OnCompletionListener {
if (queueMode == TextToSpeech.TTS_QUEUE_FLUSH) {
stop(callingApp);
}
- mSpeechQueue.add(new SpeechItem(callingApp, duration));
+ mSpeechQueue.add(new SpeechItem(callingApp, duration, params));
if (!mIsSpeaking) {
processSpeechQueue();
}
return TextToSpeech.TTS_SUCCESS;
}
- private void silence(final long duration) {
+ private void silence(final SpeechItem speechItem) {
class SilenceThread implements Runnable {
public void run() {
+ String utteranceId = "";
+ if (speechItem.mParams != null){
+ for (int i = 0; i < speechItem.mParams.size() - 1; i = i + 2){
+ String param = speechItem.mParams.get(i);
+ if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_UTTERANCE_ID)){
+ utteranceId = speechItem.mParams.get(i+1);
+ }
+ }
+ }
try {
- Thread.sleep(duration);
+ Thread.sleep(speechItem.mDuration);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
+ if (utteranceId.length() > 0){
+ dispatchUtteranceCompletedCallback(utteranceId, speechItem.mCallingApp);
+ }
+ mCurrentSpeechItem = null;
processSpeechQueue();
}
}
@@ -444,9 +479,6 @@ public class TtsService extends Service implements OnCompletionListener {
private void speakInternalOnly(final SpeechItem speechItem) {
class SynthThread implements Runnable {
public void run() {
- String text = speechItem.mText;
- ArrayList<String> params = speechItem.mParams;
- String callingApp = speechItem.mCallingApp;
boolean synthAvailable = false;
String utteranceId = "";
try {
@@ -459,26 +491,28 @@ public class TtsService extends Service implements OnCompletionListener {
return;
}
int streamType = DEFAULT_STREAM_TYPE;
- if (params != null){
+ if (speechItem.mParams != null){
String language = "";
String country = "";
String variant = "";
- for (int i = 0; i < params.size() - 1; i = i + 2){
- String param = params.get(i);
+ for (int i = 0; i < speechItem.mParams.size() - 1; i = i + 2){
+ String param = speechItem.mParams.get(i);
if (param != null) {
if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_RATE)) {
- setSpeechRate("", Integer.parseInt(params.get(i+1)));
+ setSpeechRate("",
+ Integer.parseInt(speechItem.mParams.get(i+1)));
} else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_LANGUAGE)){
- language = params.get(i+1);
+ language = speechItem.mParams.get(i+1);
} else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_COUNTRY)){
- country = params.get(i+1);
+ country = speechItem.mParams.get(i+1);
} else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_VARIANT)){
- variant = params.get(i+1);
+ variant = speechItem.mParams.get(i+1);
} else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_UTTERANCE_ID)){
- utteranceId = params.get(i+1);
+ utteranceId = speechItem.mParams.get(i+1);
} else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_STREAM)) {
try {
- streamType = Integer.parseInt(params.get(i + 1));
+ streamType
+ = Integer.parseInt(speechItem.mParams.get(i + 1));
} catch (NumberFormatException e) {
streamType = DEFAULT_STREAM_TYPE;
}
@@ -489,7 +523,7 @@ public class TtsService extends Service implements OnCompletionListener {
setLanguage("", language, country, variant);
}
}
- nativeSynth.speak(text, streamType);
+ nativeSynth.speak(speechItem.mText, streamType);
} catch (InterruptedException e) {
Log.e("TTS speakInternalOnly", "tryLock interrupted");
e.printStackTrace();
@@ -501,8 +535,9 @@ public class TtsService extends Service implements OnCompletionListener {
synthesizerLock.unlock();
}
if (utteranceId.length() > 0){
- dispatchUtteranceCompletedCallback(utteranceId, callingApp);
+ dispatchUtteranceCompletedCallback(utteranceId, speechItem.mCallingApp);
}
+ mCurrentSpeechItem = null;
processSpeechQueue();
}
}
@@ -512,12 +547,12 @@ public class TtsService extends Service implements OnCompletionListener {
synth.start();
}
- private void synthToFileInternalOnly(final String text,
- final ArrayList<String> params, final String filename) {
+ private void synthToFileInternalOnly(final SpeechItem speechItem) {
class SynthThread implements Runnable {
public void run() {
- Log.i("TTS", "Synthesizing to " + filename);
boolean synthAvailable = false;
+ String utteranceId = "";
+ Log.i("TTS", "Synthesizing to " + speechItem.mFilename);
try {
synthAvailable = synthesizerLock.tryLock();
if (!synthAvailable) {
@@ -527,21 +562,24 @@ public class TtsService extends Service implements OnCompletionListener {
synth.start();
return;
}
- if (params != null){
+ if (speechItem.mParams != null){
String language = "";
String country = "";
String variant = "";
- for (int i = 0; i < params.size() - 1; i = i + 2){
- String param = params.get(i);
+ for (int i = 0; i < speechItem.mParams.size() - 1; i = i + 2){
+ String param = speechItem.mParams.get(i);
if (param != null){
if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_RATE)){
- setSpeechRate("", Integer.parseInt(params.get(i+1)));
+ setSpeechRate("",
+ Integer.parseInt(speechItem.mParams.get(i+1)));
} else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_LANGUAGE)){
- language = params.get(i+1);
+ language = speechItem.mParams.get(i+1);
} else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_COUNTRY)){
- country = params.get(i+1);
+ country = speechItem.mParams.get(i+1);
} else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_VARIANT)){
- variant = params.get(i+1);
+ variant = speechItem.mParams.get(i+1);
+ } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_UTTERANCE_ID)){
+ utteranceId = speechItem.mParams.get(i+1);
}
}
}
@@ -549,7 +587,7 @@ public class TtsService extends Service implements OnCompletionListener {
setLanguage("", language, country, variant);
}
}
- nativeSynth.synthesizeToFile(text, filename);
+ nativeSynth.synthesizeToFile(speechItem.mText, speechItem.mFilename);
} catch (InterruptedException e) {
Log.e("TTS synthToFileInternalOnly", "tryLock interrupted");
e.printStackTrace();
@@ -560,6 +598,10 @@ public class TtsService extends Service implements OnCompletionListener {
if (synthAvailable) {
synthesizerLock.unlock();
}
+ if (utteranceId.length() > 0){
+ dispatchUtteranceCompletedCallback(utteranceId, speechItem.mCallingApp);
+ }
+ mCurrentSpeechItem = null;
processSpeechQueue();
}
}
@@ -647,22 +689,21 @@ public class TtsService extends Service implements OnCompletionListener {
return;
}
- SpeechItem currentSpeechItem = mSpeechQueue.get(0);
+ mCurrentSpeechItem = mSpeechQueue.get(0);
mIsSpeaking = true;
- SoundResource sr = getSoundResource(currentSpeechItem);
+ SoundResource sr = getSoundResource(mCurrentSpeechItem);
// Synth speech as needed - synthesizer should call
// processSpeechQueue to continue running the queue
- Log.i("TTS processing: ", currentSpeechItem.mText);
+ Log.i("TTS processing: ", mCurrentSpeechItem.mText);
if (sr == null) {
- if (currentSpeechItem.mType == SpeechItem.TEXT) {
- currentSpeechItem = splitCurrentTextIfNeeded(currentSpeechItem);
- speakInternalOnly(currentSpeechItem);
- } else if (currentSpeechItem.mType == SpeechItem.TEXT_TO_FILE) {
- synthToFileInternalOnly(currentSpeechItem.mText,
- currentSpeechItem.mParams, currentSpeechItem.mFilename);
+ if (mCurrentSpeechItem.mType == SpeechItem.TEXT) {
+ mCurrentSpeechItem = splitCurrentTextIfNeeded(mCurrentSpeechItem);
+ speakInternalOnly(mCurrentSpeechItem);
+ } else if (mCurrentSpeechItem.mType == SpeechItem.TEXT_TO_FILE) {
+ synthToFileInternalOnly(mCurrentSpeechItem);
} else {
// This is either silence or an earcon that was missing
- silence(currentSpeechItem.mDuration);
+ silence(mCurrentSpeechItem);
}
} else {
cleanUpPlayer();
@@ -696,7 +737,7 @@ public class TtsService extends Service implements OnCompletionListener {
}
mPlayer.setOnCompletionListener(this);
try {
- mPlayer.setAudioStreamType(getStreamTypeFromParams(currentSpeechItem.mParams));
+ mPlayer.setAudioStreamType(getStreamTypeFromParams(mCurrentSpeechItem.mParams));
mPlayer.start();
} catch (IllegalStateException e) {
mSpeechQueue.clear();
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 134ab80..442e9ce 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -32,6 +32,7 @@ import android.app.ActivityThread;
import android.app.AlertDialog;
import android.app.ApplicationErrorReport;
import android.app.Dialog;
+import android.app.IActivityController;
import android.app.IActivityWatcher;
import android.app.IApplicationThread;
import android.app.IInstrumentationWatcher;
@@ -76,6 +77,7 @@ import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.Process;
+import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -825,8 +827,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
String mOrigDebugApp = null;
boolean mOrigWaitForDebugger = false;
boolean mAlwaysFinishActivities = false;
- IActivityWatcher mWatcher = null;
+ IActivityController mController = null;
+ final RemoteCallbackList<IActivityWatcher> mWatchers
+ = new RemoteCallbackList<IActivityWatcher>();
+
/**
* Callback of last caller to {@link #requestPss}.
*/
@@ -1623,7 +1628,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
/**
* This is a simplified version of topRunningActivityLocked that provides a number of
- * optional skip-over modes. It is intended for use with the ActivityWatcher hook only.
+ * optional skip-over modes. It is intended for use with the ActivityController hook only.
*
* @param token If non-null, any history records matching this token will be skipped.
* @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
@@ -1728,10 +1733,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
ensurePackageDexOpt(r.intent.getComponent().getPackageName());
app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
+ System.identityHashCode(r),
r.info, r.icicle, results, newIntents, !andResume,
isNextTransitionForward());
- // Update usage stats for launched activity
- updateUsageStats(r, true);
} catch (RemoteException e) {
if (r.launchFailed) {
// This is the second time we failed -- finish activity
@@ -2184,6 +2188,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
mHandler.sendMessage(msg);
}
+ reportResumedActivity(next);
+
next.thumbnail = null;
setFocusedActivityLocked(next);
next.resumeKeyDispatchingLocked();
@@ -2454,6 +2460,26 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
+ private void reportResumedActivity(HistoryRecord r) {
+ //Log.i(TAG, "**** REPORT RESUME: " + r);
+
+ final int identHash = System.identityHashCode(r);
+ updateUsageStats(r, true);
+
+ int i = mWatchers.beginBroadcast();
+ while (i > 0) {
+ i--;
+ IActivityWatcher w = mWatchers.getBroadcastItem(i);
+ if (w != null) {
+ try {
+ w.activityResuming(identHash);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+ mWatchers.finishBroadcast();
+ }
+
/**
* Ensure that the top activity in the stack is resumed.
*
@@ -2642,10 +2668,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
EventLog.writeEvent(LOG_AM_RESUME_ACTIVITY,
System.identityHashCode(next),
next.task.taskId, next.shortComponentName);
- updateUsageStats(next, true);
next.app.thread.scheduleResumeActivity(next,
isNextTransitionForward());
+
pauseIfSleepingLocked();
} catch (Exception e) {
@@ -3062,16 +3088,16 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
throw new SecurityException(msg);
}
- if (mWatcher != null) {
+ if (mController != null) {
boolean abort = false;
try {
// The Intent we give to the watcher has the extra data
// stripped off, since it can contain private information.
Intent watchIntent = intent.cloneFilter();
- abort = !mWatcher.activityStarting(watchIntent,
+ abort = !mController.activityStarting(watchIntent,
aInfo.applicationInfo.packageName);
} catch (RemoteException e) {
- mWatcher = null;
+ mController = null;
}
if (abort) {
@@ -3968,16 +3994,16 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
synchronized(this) {
- if (mWatcher != null) {
+ if (mController != null) {
// Find the first activity that is not finishing.
HistoryRecord next = topRunningActivityLocked(token, 0);
if (next != null) {
// ask watcher if this is allowed
boolean resumeOK = true;
try {
- resumeOK = mWatcher.activityResuming(next.packageName);
+ resumeOK = mController.activityResuming(next.packageName);
} catch (RemoteException e) {
- mWatcher = null;
+ mController = null;
}
if (!resumeOK) {
@@ -4469,9 +4495,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
- if (mWatcher != null) {
+ if (mController != null) {
try {
- int res = mWatcher.appNotResponding(app.processName,
+ int res = mController.appNotResponding(app.processName,
app.pid, info.toString());
if (res != 0) {
if (res < 0) {
@@ -4487,7 +4513,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
} catch (RemoteException e) {
- mWatcher = null;
+ mController = null;
}
}
@@ -6612,7 +6638,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
/**
- * TODO: Add mWatcher hook
+ * TODO: Add mController hook
*/
public void moveTaskToFront(int task) {
enforceCallingPermission(android.Manifest.permission.REORDER_TASKS,
@@ -6757,7 +6783,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
// If we have a watcher, preflight the move before committing to it. First check
// for *other* available tasks, but if none are available, then try again allowing the
// current task to be selected.
- if (mWatcher != null) {
+ if (mController != null) {
HistoryRecord next = topRunningActivityLocked(null, task);
if (next == null) {
next = topRunningActivityLocked(null, 0);
@@ -6766,9 +6792,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
// ask watcher if this is allowed
boolean moveOK = true;
try {
- moveOK = mWatcher.activityResuming(next.packageName);
+ moveOK = mController.activityResuming(next.packageName);
} catch (RemoteException e) {
- mWatcher = null;
+ mController = null;
}
if (!moveOK) {
return false;
@@ -7679,14 +7705,22 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
- public void setActivityWatcher(IActivityWatcher watcher) {
+ public void setActivityController(IActivityController controller) {
enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
- "setActivityWatcher()");
+ "setActivityController()");
synchronized (this) {
- mWatcher = watcher;
+ mController = controller;
}
}
+ public void registerActivityWatcher(IActivityWatcher watcher) {
+ mWatchers.register(watcher);
+ }
+
+ public void unregisterActivityWatcher(IActivityWatcher watcher) {
+ mWatchers.unregister(watcher);
+ }
+
public final void enterSafeMode() {
synchronized(this) {
// It only makes sense to do this before the system is ready
@@ -8247,11 +8281,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
//Process.sendSignal(MY_PID, Process.SIGNAL_QUIT);
}
- if (mWatcher != null) {
+ if (mController != null) {
try {
String name = r != null ? r.processName : null;
int pid = r != null ? r.pid : Binder.getCallingPid();
- if (!mWatcher.appCrashed(name, pid,
+ if (!mController.appCrashed(name, pid,
shortMsg, longMsg, crashData)) {
Log.w(TAG, "Force-killing crashed app " + name
+ " at watcher's request");
@@ -8259,7 +8293,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
return 0;
}
} catch (RemoteException e) {
- mWatcher = null;
+ mController = null;
}
}
@@ -8685,7 +8719,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
+ " mDebugTransient=" + mDebugTransient
+ " mOrigWaitForDebugger=" + mOrigWaitForDebugger);
pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities
- + " mWatcher=" + mWatcher);
+ + " mController=" + mController);
}
}
diff --git a/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java
index 14d3d73..c782045 100644
--- a/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/ActivityManagerPermissionTests.java
@@ -134,8 +134,8 @@ public class ActivityManagerPermissionTests extends TestCase {
@SmallTest
public void testSET_ACTIVITY_WATCHER() {
try {
- mAm.setActivityWatcher(null);
- fail("IActivityManager.setActivityWatcher did not throw SecurityException as"
+ mAm.setActivityController(null);
+ fail("IActivityManager.setActivityController did not throw SecurityException as"
+ " expected");
} catch (SecurityException e) {
// expected