From f1e484acb594a726fb57ad0ae4cfe902c7f35858 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Thu, 22 Jan 2009 00:13:42 -0800 Subject: [PATCH] auto import from //branches/cupcake/...@127436 --- api/current.xml | 166 ++++++++++++ cmds/installd/commands.c | 6 +- core/java/android/app/Activity.java | 15 ++ core/java/android/app/ActivityThread.java | 21 +- core/java/android/app/ApplicationContext.java | 22 +- core/java/android/app/ApplicationThreadNative.java | 6 +- core/java/android/app/IApplicationThread.java | 2 +- core/java/android/app/Instrumentation.java | 10 + core/java/android/app/SearchDialog.java | 34 ++- core/java/android/bluetooth/BluetoothDevice.java | 102 ++++---- core/java/android/bluetooth/BluetoothIntent.java | 23 +- core/java/android/bluetooth/IBluetoothDevice.aidl | 10 +- .../bluetooth/IBluetoothDeviceCallback.aidl | 1 - core/java/android/content/Intent.java | 34 +++ core/java/android/content/pm/IPackageManager.aidl | 60 +++-- core/java/android/content/pm/PackageManager.java | 60 +++-- core/java/android/gadget/GadgetManager.java | 22 +- .../inputmethodservice/InputMethodService.java | 35 ++- .../android/inputmethodservice/KeyboardView.java | 22 +- core/java/android/os/BatteryStats.java | 17 +- core/java/android/provider/Gmail.java | 12 +- core/java/android/provider/MediaStore.java | 7 + core/java/android/provider/Settings.java | 22 ++ core/java/android/server/BluetoothA2dpService.java | 19 +- .../android/server/BluetoothDeviceService.java | 270 +++++++++++-------- core/java/android/server/BluetoothEventLoop.java | 92 +++---- .../java/android/server/search/SearchableInfo.java | 2 + core/java/android/text/TextUtils.java | 6 +- core/java/android/view/WindowManagerPolicy.java | 12 +- .../android/view/inputmethod/InputConnection.java | 13 + .../view/inputmethod/InputConnectionWrapper.java | 8 + .../view/inputmethod/InputMethodManager.java | 14 + core/java/android/webkit/LoadListener.java | 23 +- core/java/android/webkit/WebView.java | 7 +- core/java/android/widget/Button.java | 2 + core/java/android/widget/ImageButton.java | 2 + core/java/android/widget/RemoteViews.java | 66 ++++- core/java/android/widget/TextView.java | 40 ++- .../android/internal/gadget/IGadgetService.aidl | 1 + .../internal/view/IInputConnectionWrapper.java | 18 ++ .../com/android/internal/view/IInputContext.aidl | 4 + .../internal/view/InputConnectionWrapper.java | 18 ++ .../internal/widget/EditableInputConnection.java | 12 + core/jni/android/graphics/Bitmap.cpp | 25 +- core/jni/android_server_BluetoothDeviceService.cpp | 43 +-- core/jni/android_server_BluetoothEventLoop.cpp | 31 ++- core/res/res/anim/status_bar_enter.xml | 24 ++ core/res/res/anim/status_bar_exit.xml | 24 ++ core/res/res/values-cs/arrays.xml | 4 - core/res/res/values-cs/strings.xml | 14 + core/res/res/values-de/arrays.xml | 4 - core/res/res/values-de/strings.xml | 14 + core/res/res/values-es/arrays.xml | 4 - core/res/res/values-es/strings.xml | 14 + core/res/res/values-fr/arrays.xml | 4 - core/res/res/values-fr/strings.xml | 14 + core/res/res/values-it/arrays.xml | 4 - core/res/res/values-it/strings.xml | 14 + core/res/res/values-ja/arrays.xml | 4 - core/res/res/values-ja/strings.xml | 14 + core/res/res/values-mcc204-cs/strings.xml | 14 + core/res/res/values-mcc204-de/strings.xml | 14 + core/res/res/values-mcc204-es/strings.xml | 14 + core/res/res/values-mcc204-fr/strings.xml | 14 + core/res/res/values-mcc204-it/strings.xml | 14 + core/res/res/values-mcc204-ja/strings.xml | 14 + core/res/res/values-mcc204-nl/strings.xml | 14 + core/res/res/values-mcc204-pl/strings.xml | 14 + core/res/res/values-mcc204-ru/strings.xml | 14 + core/res/res/values-mcc204-zh-rCN/strings.xml | 14 + core/res/res/values-mcc204-zh-rTW/strings.xml | 14 + core/res/res/values-mcc230-cs/strings.xml | 14 + core/res/res/values-mcc230-de/strings.xml | 14 + core/res/res/values-mcc230-es/strings.xml | 14 + core/res/res/values-mcc230-fr/strings.xml | 14 + core/res/res/values-mcc230-it/strings.xml | 14 + core/res/res/values-mcc230-ja/strings.xml | 14 + core/res/res/values-mcc230-nl/strings.xml | 14 + core/res/res/values-mcc230-pl/strings.xml | 14 + core/res/res/values-mcc230-ru/strings.xml | 14 + core/res/res/values-mcc230-zh-rCN/strings.xml | 14 + core/res/res/values-mcc230-zh-rTW/strings.xml | 14 + core/res/res/values-mcc232-cs/strings.xml | 14 + core/res/res/values-mcc232-de/strings.xml | 14 + core/res/res/values-mcc232-es/strings.xml | 14 + core/res/res/values-mcc232-fr/strings.xml | 14 + core/res/res/values-mcc232-it/strings.xml | 14 + core/res/res/values-mcc232-ja/strings.xml | 14 + core/res/res/values-mcc232-nl/strings.xml | 14 + core/res/res/values-mcc232-pl/strings.xml | 14 + core/res/res/values-mcc232-ru/strings.xml | 14 + core/res/res/values-mcc232-zh-rCN/strings.xml | 14 + core/res/res/values-mcc232-zh-rTW/strings.xml | 14 + core/res/res/values-mcc234-cs/strings.xml | 14 + core/res/res/values-mcc234-de/strings.xml | 14 + core/res/res/values-mcc234-es/strings.xml | 14 + core/res/res/values-mcc234-fr/strings.xml | 14 + core/res/res/values-mcc234-it/strings.xml | 14 + core/res/res/values-mcc234-ja/strings.xml | 14 + core/res/res/values-mcc234-nl/strings.xml | 14 + core/res/res/values-mcc234-pl/strings.xml | 14 + core/res/res/values-mcc234-ru/strings.xml | 14 + core/res/res/values-mcc234-zh-rCN/strings.xml | 14 + core/res/res/values-mcc234-zh-rTW/strings.xml | 14 + core/res/res/values-mcc260-cs/strings.xml | 14 + core/res/res/values-mcc260-de/strings.xml | 14 + core/res/res/values-mcc260-es/strings.xml | 14 + core/res/res/values-mcc260-fr/strings.xml | 14 + core/res/res/values-mcc260-it/strings.xml | 14 + core/res/res/values-mcc260-ja/strings.xml | 14 + core/res/res/values-mcc260-nl/strings.xml | 14 + core/res/res/values-mcc260-pl/strings.xml | 14 + core/res/res/values-mcc260-ru/strings.xml | 14 + core/res/res/values-mcc260-zh-rCN/strings.xml | 14 + core/res/res/values-mcc260-zh-rTW/strings.xml | 14 + core/res/res/values-mcc262-cs/strings.xml | 14 + core/res/res/values-mcc262-de/strings.xml | 14 + core/res/res/values-mcc262-es/strings.xml | 14 + core/res/res/values-mcc262-fr/strings.xml | 14 + core/res/res/values-mcc262-it/strings.xml | 14 + core/res/res/values-mcc262-ja/strings.xml | 14 + core/res/res/values-mcc262-nl/strings.xml | 14 + core/res/res/values-mcc262-pl/strings.xml | 14 + core/res/res/values-mcc262-ru/strings.xml | 14 + core/res/res/values-mcc262-zh-rCN/strings.xml | 14 + core/res/res/values-mcc262-zh-rTW/strings.xml | 14 + core/res/res/values-nl/arrays.xml | 4 - core/res/res/values-nl/strings.xml | 14 + core/res/res/values-pl/arrays.xml | 4 - core/res/res/values-pl/strings.xml | 14 + core/res/res/values-ru/arrays.xml | 4 - core/res/res/values-ru/strings.xml | 14 + core/res/res/values-zh-rCN/arrays.xml | 4 - core/res/res/values-zh-rCN/strings.xml | 14 + core/res/res/values-zh-rTW/arrays.xml | 4 - core/res/res/values-zh-rTW/strings.xml | 14 + core/res/res/values/attrs.xml | 17 ++ core/res/res/values/public.xml | 2 + core/res/res/values/styles.xml | 6 + core/res/res/values/themes.xml | 2 +- data/localization/import-from-xtb | 7 +- graphics/java/android/graphics/Bitmap.java | 32 +++ graphics/java/android/graphics/BitmapFactory.java | 5 - .../android/graphics/drawable/LayerDrawable.java | 8 +- libs/audioflinger/AudioFlinger.cpp | 80 +++++- libs/audioflinger/AudioFlinger.h | 13 + .../internal/location/GpsLocationProvider.java | 34 ++- .../com/android/server/DeviceMemoryMonitor.java | 288 --------------------- .../server/DeviceStorageMonitorService.java | 2 +- .../java/com/android/server/GadgetService.java | 248 +++++++++++++++++- .../com/android/server/PackageManagerService.java | 47 +++- .../com/android/server/WindowManagerService.java | 56 +++- .../android/server/am/ActivityManagerService.java | 43 ++- .../android/server/status/StatusBarService.java | 1 + .../internal/telephony/gsm/stk/StkService.java | 19 +- .../android/test/mock/MockPackageManager.java | 12 +- .../src/com/android/unit_tests/AppCacheTest.java | 82 +++++- .../src/com/android/unit_tests/BluetoothTest.java | 21 +- .../res/layout/remote_view_test_good.xml | 9 + .../view/RemoteViewsActivityTest.java | 2 + tests/GadgetHost/AndroidManifest.xml | 4 + tests/GadgetHost/res/xml/gadget_info.xml | 7 + .../com/android/gadgethost/GadgetHostActivity.java | 3 - .../com/android/gadgethost/GadgetPickActivity.java | 17 +- tests/ImfTest/Android.mk | 15 ++ tests/ImfTest/AndroidManifest.xml | 24 ++ tests/ImfTest/res/layout/sample_edit_text.xml | 53 ++++ tests/ImfTest/res/values/strings.xml | 39 +++ .../android/imftest/samples/ButtonActivity.java | 52 ++++ .../android/imftest/samples/InputTypeActivity.java | 140 ++++++++++ 170 files changed, 3180 insertions(+), 817 deletions(-) create mode 100644 core/res/res/anim/status_bar_enter.xml create mode 100644 core/res/res/anim/status_bar_exit.xml delete mode 100644 core/res/res/values-cs/arrays.xml delete mode 100644 core/res/res/values-de/arrays.xml delete mode 100644 core/res/res/values-es/arrays.xml delete mode 100644 core/res/res/values-fr/arrays.xml delete mode 100644 core/res/res/values-it/arrays.xml delete mode 100644 core/res/res/values-ja/arrays.xml delete mode 100644 core/res/res/values-nl/arrays.xml delete mode 100644 core/res/res/values-pl/arrays.xml delete mode 100644 core/res/res/values-ru/arrays.xml delete mode 100644 core/res/res/values-zh-rCN/arrays.xml delete mode 100644 core/res/res/values-zh-rTW/arrays.xml delete mode 100644 services/java/com/android/server/DeviceMemoryMonitor.java create mode 100644 tests/GadgetHost/res/xml/gadget_info.xml create mode 100755 tests/ImfTest/Android.mk create mode 100755 tests/ImfTest/AndroidManifest.xml create mode 100755 tests/ImfTest/res/layout/sample_edit_text.xml create mode 100755 tests/ImfTest/res/values/strings.xml create mode 100644 tests/ImfTest/src/com/android/imftest/samples/ButtonActivity.java create mode 100755 tests/ImfTest/src/com/android/imftest/samples/InputTypeActivity.java diff --git a/api/current.xml b/api/current.xml index e183217d003c..935454a19e53 100644 --- a/api/current.xml +++ b/api/current.xml @@ -3738,6 +3738,17 @@ visibility="public" > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + free_size) return 0; + if (avail >= free_size) return 0; d = opendir(PKG_DIR_PREFIX); if (d == NULL) { LOGE("cannot open %s\n", PKG_DIR_PREFIX); - return 0; + return -1; } dfd = dirfd(d); @@ -144,7 +144,7 @@ int free_cache(int free_size) close(subfd); avail = disk_free(); - if (avail > free_size) { + if (avail >= free_size) { closedir(d); return 0; } diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index c98cf1bbd356..4dc4b6a48b85 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -1132,6 +1132,17 @@ public class Activity extends ContextThemeWrapper } /** + * Called as part of the activity lifecycle when an activity is about to go + * into the background as the result of user choice. For example, when the + * user presses the Home key, {@link #onUserLeaving} will be called, but + * when an incoming phone call causes the in-call Activity to be automatically + * brought to the foreground, {@link #onUserLeaving} will not be called on + * the activity being interrupted. + */ + protected void onUserLeaving() { + } + + /** * Generate a new thumbnail for this activity. This method is called before * pausing the activity, and should draw into outBitmap the * imagery for the desired thumbnail in the dimensions of that bitmap. It @@ -3470,6 +3481,10 @@ public class Activity extends ContextThemeWrapper onPause(); } + final void performUserLeaving() { + onUserLeaving(); + } + final void performStop() { if (!mStopped) { if (mWindow != null) { diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index a98e29594aac..e4c1057e3878 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -1207,10 +1207,12 @@ public final class ActivityThread { private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d"; public final void schedulePauseActivity(IBinder token, boolean finished, - int configChanges) { + boolean userLeaving, int configChanges) { queueOrSendMessage( finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY, - token, configChanges); + token, + (userLeaving ? 1 : 0), + configChanges); } public final void scheduleStopActivity(IBinder token, boolean showWindow, @@ -1588,10 +1590,10 @@ public final class ActivityThread { handleRelaunchActivity(r, msg.arg1); } break; case PAUSE_ACTIVITY: - handlePauseActivity((IBinder)msg.obj, false, msg.arg2); + handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2); break; case PAUSE_ACTIVITY_FINISHING: - handlePauseActivity((IBinder)msg.obj, true, msg.arg2); + handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2); break; case STOP_ACTIVITY_SHOW: handleStopActivity((IBinder)msg.obj, true, msg.arg2); @@ -2647,9 +2649,14 @@ public final class ActivityThread { } private final void handlePauseActivity(IBinder token, boolean finished, - int configChanges) { + boolean userLeaving, int configChanges) { ActivityRecord r = mActivities.get(token); if (r != null) { + //Log.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r); + if (userLeaving) { + performUserLeavingActivity(r); + } + r.activity.mConfigChangeFlags |= configChanges; Bundle state = performPauseActivity(token, finished, true); @@ -2661,6 +2668,10 @@ public final class ActivityThread { } } + final void performUserLeavingActivity(ActivityRecord r) { + mInstrumentation.callActivityOnUserLeaving(r.activity); + } + final Bundle performPauseActivity(IBinder token, boolean finished, boolean saveState) { ActivityRecord r = mActivities.get(token); diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java index 0e41ae6f2faf..4236a00e1b58 100644 --- a/core/java/android/app/ApplicationContext.java +++ b/core/java/android/app/ApplicationContext.java @@ -315,8 +315,13 @@ class ApplicationContext extends Context { backup.renameTo(f); } + // Debugging + if (f.exists() && !f.canRead()) { + Log.w(TAG, "Attempt to read preferences file " + f + " without permission"); + } + Map map = null; - if (f.exists()) { + if (f.exists() && f.canRead()) { try { str = new FileInputStream(f); map = XmlUtils.readMapXml(str); @@ -2264,14 +2269,23 @@ class ApplicationContext extends Context { } } @Override - public void freeApplicationCache(long idealStorageSize, - IPackageDataObserver observer) { + public void freeStorageAndNotify(long idealStorageSize, IPackageDataObserver observer) { try { - mPM.freeApplicationCache(idealStorageSize, observer); + mPM.freeStorageAndNotify(idealStorageSize, observer); } catch (RemoteException e) { // Should never happen! } } + + @Override + public void freeStorage(long idealStorageSize, PendingIntent opFinishedIntent) { + try { + mPM.freeStorage(idealStorageSize, opFinishedIntent); + } catch (RemoteException e) { + // Should never happen! + } + } + @Override public void getPackageSizeInfo(String packageName, IPackageStatsObserver observer) { diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index 54237aea53d8..d2cf55a427cc 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -69,8 +69,9 @@ public abstract class ApplicationThreadNative extends Binder data.enforceInterface(IApplicationThread.descriptor); IBinder b = data.readStrongBinder(); boolean finished = data.readInt() != 0; + boolean userLeaving = data.readInt() != 0; int configChanges = data.readInt(); - schedulePauseActivity(b, finished, configChanges); + schedulePauseActivity(b, finished, userLeaving, configChanges); return true; } @@ -344,11 +345,12 @@ class ApplicationThreadProxy implements IApplicationThread { } public final void schedulePauseActivity(IBinder token, boolean finished, - int configChanges) throws RemoteException { + boolean userLeaving, int configChanges) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeStrongBinder(token); data.writeInt(finished ? 1 : 0); + data.writeInt(userLeaving ? 1 :0); data.writeInt(configChanges); mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index a35158136422..47476b5da211 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -40,7 +40,7 @@ import java.util.Map; * {@hide} */ public interface IApplicationThread extends IInterface { - void schedulePauseActivity(IBinder token, boolean finished, + void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges) throws RemoteException; void scheduleStopActivity(IBinder token, boolean showWindow, int configChanges) throws RemoteException; diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java index 17618ff26fd4..f96d78710463 100644 --- a/core/java/android/app/Instrumentation.java +++ b/core/java/android/app/Instrumentation.java @@ -1266,6 +1266,16 @@ public class Instrumentation { activity.performPause(); } + /** + * Perform calling of an activity's {@link Activity#onUserLeaving} method. + * The default implementation simply calls through to that method. + * + * @param activity The activity being notified that the user has navigated away + */ + public void callActivityOnUserLeaving(Activity activity) { + activity.performUserLeaving(); + } + /* * Starts allocation counting. This triggers a gc and resets the counts. */ diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index 5af08f77298a..2e2a1a17a52e 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -222,17 +222,27 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS // configure the autocomplete aspects of the input box mSearchTextField.setOnItemClickListener(this); mSearchTextField.setOnItemSelectedListener(this); - - // attach the suggestions adapter - mSuggestionsAdapter = new SuggestionsAdapter(getContext(), mSearchable); - mSearchTextField.setAdapter(mSuggestionsAdapter); - // finally, load the user's initial text (which may trigger suggestions) - mSuggestionsAdapter.setNonUserQuery(false); + // This conversion is necessary to force a preload of the EditText and thus force + // suggestions to be presented (even for an empty query) if (initialQuery == null) { initialQuery = ""; // This forces the preload to happen, triggering suggestions } - mSearchTextField.setText(initialQuery); + + // attach the suggestions adapter, if suggestions are available + // The existence of a suggestions authority is the proxy for "suggestions available here" + if (mSearchable.getSuggestAuthority() == null) { + mSuggestionsAdapter = null; + mSearchTextField.setAdapter(mSuggestionsAdapter); + mSearchTextField.setText(initialQuery); + } else { + mSuggestionsAdapter = new SuggestionsAdapter(getContext(), mSearchable); + mSearchTextField.setAdapter(mSuggestionsAdapter); + + // finally, load the user's initial text (which may trigger suggestions) + mSuggestionsAdapter.setNonUserQuery(false); + mSearchTextField.setText(initialQuery); + } if (selectInitialQuery) { mSearchTextField.selectAll(); @@ -344,7 +354,9 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS return; } - mSuggestionsAdapter.setNonUserQuery(true); + if (mSuggestionsAdapter != null) { + mSuggestionsAdapter.setNonUserQuery(true); + } mSearchTextField.setText(displayQuery); // TODO because the new query is (not) processed in another thread, we can't just // take away this flag (yet). The better solution here is going to require a new API @@ -539,7 +551,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS } updateWidgetState(); // Only do suggestions if actually typed by user - if (!mSuggestionsAdapter.getNonUserQuery()) { + if ((mSuggestionsAdapter != null) && !mSuggestionsAdapter.getNonUserQuery()) { mPreviousSuggestionQuery = s.toString(); mUserQuery = mSearchTextField.getText().toString(); mUserQuerySelStart = mSearchTextField.getSelectionStart(); @@ -822,6 +834,10 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS * React to the user typing an action key while in the suggestions list */ private boolean doSuggestionsKey(View v, int keyCode, KeyEvent event) { + // Exit early in case of race condition + if (mSuggestionsAdapter == null) { + return false; + } if (event.getAction() == KeyEvent.ACTION_DOWN) { if (DBG_LOG_TIMING == 1) { dbgLogTiming("doSuggestionsKey()"); diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index d1f71c55f05a..d613e1cfba27 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -39,6 +39,28 @@ public class BluetoothDevice { public static final int RESULT_FAILURE = -1; public static final int RESULT_SUCCESS = 0; + /** We do not have a link key for the remote device, and are therefore not + * bonded */ + public static final int BOND_NOT_BONDED = 0; + /** We have a link key for the remote device, and are probably bonded. */ + public static final int BOND_BONDED = 1; + /** We are currently attempting bonding */ + public static final int BOND_BONDING = 2; + + //TODO: Unify these result codes in BluetoothResult or BluetoothError + /** A bond attempt failed because pins did not match, or remote device did + * not respond to pin request in time */ + public static final int UNBOND_REASON_AUTH_FAILED = 1; + /** A bond attempt failed because the other side explicilty rejected + * bonding */ + public static final int UNBOND_REASON_AUTH_REJECTED = 2; + /** A bond attempt failed because we cancelled the bonding process */ + public static final int UNBOND_REASON_CANCELLED = 3; + /** A bond attempt failed because we could not contact the remote device */ + public static final int UNBOND_REASON_AUTH_REMOTE_DEVICE_DOWN = 4; + /** An existing bond was explicitly revoked */ + public static final int UNBOND_REASON_REMOVED = 5; + private static final String TAG = "BluetoothDevice"; private final IBluetoothDevice mService; @@ -325,42 +347,36 @@ public class BluetoothDevice { /** * Create a bonding with a remote bluetooth device. * - * This is an asynchronous call. BluetoothIntent.BONDING_CREATED_ACTION - * will be broadcast if and when the remote device is successfully bonded. + * This is an asynchronous call. The result of this bonding attempt can be + * observed through BluetoothIntent.BOND_STATE_CHANGED_ACTION intents. * * @param address the remote device Bluetooth address. - * @return false if we cannot create a bonding to that device, true if - * there were no problems beginning the bonding process. + * @return false If there was an immediate problem creating the bonding, + * true otherwise. */ - public boolean createBonding(String address) { - return createBonding(address, null); + public boolean createBond(String address) { + try { + return mService.createBond(address); + } catch (RemoteException e) {Log.e(TAG, "", e);} + return false; } /** - * Create a bonding with a remote bluetooth device. - * - * This is an asynchronous call. onCreateBondingResult() of your callback - * will be called when the call is complete, with either RESULT_SUCCESS or - * RESULT_FAILURE. - * - * In addition to the callback, BluetoothIntent.BONDING_CREATED_ACTION will - * be broadcast if the remote device is successfully bonded. - * - * @param address The remote device Bluetooth address. - * @param callback Your callback, null is ok. - * @return true if your callback was successfully registered, or false if - * there was an error, implying your callback will never be called. + * Cancel an in-progress bonding request started with createBond. */ - public boolean createBonding(String address, IBluetoothDeviceCallback callback) { + public boolean cancelBondProcess(String address) { try { - return mService.createBonding(address, callback); + return mService.cancelBondProcess(address); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; } - public boolean cancelBondingProcess(String address) { + /** + * Remove an already exisiting bonding (delete the link key). + */ + public boolean removeBond(String address) { try { - return mService.cancelBondingProcess(address); + return mService.removeBond(address); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; } @@ -382,48 +398,34 @@ public class BluetoothDevice { * * This function does not check if the remote device is in range. * + * Remote devices that have an in-progress bonding attempt are not + * returned. + * * @return bluetooth hardware addresses of remote devices that are * bonded. Array size is 0 if no devices are bonded. Null on error. */ - public String[] listBondings() { + public String[] listBonds() { try { - return mService.listBondings(); + return mService.listBonds(); } catch (RemoteException e) {Log.e(TAG, "", e);} return null; } /** - * Check if a remote device is bonded (paired) to the local device. + * Get the bonding state of a remote device. * - * Bonding (pairing) is the process by which the user enters a pin code for - * the device, which generates a shared link key, allowing for - * authentication and encryption of future connections. In Android we - * require bonding before RFCOMM or SCO connections can be made to a remote - * device. - * - * This function checks if we have a link key with the remote device. It - * does not cause any RF transmission, and does not check if the remote - * device still has it's link key with us. If the other side no longer has - * a link key then the RFCOMM or SCO connection attempt will result in an - * error. - * - * This function does not check if the remote device is in range. + * Result is one of: + * BluetoothError.* + * BOND_* * * @param address Bluetooth hardware address of the remote device to check. - * @return true if bonded, false otherwise and on error. + * @return Result code */ - public boolean hasBonding(String address) { + public int getBondState(String address) { try { - return mService.hasBonding(address); + return mService.getBondState(address); } catch (RemoteException e) {Log.e(TAG, "", e);} - return false; - } - - public boolean removeBonding(String address) { - try { - return mService.removeBonding(address); - } catch (RemoteException e) {Log.e(TAG, "", e);} - return false; + return BluetoothError.ERROR_IPC; } public String getRemoteName(String address) { diff --git a/core/java/android/bluetooth/BluetoothIntent.java b/core/java/android/bluetooth/BluetoothIntent.java index 8e2279189035..57c46f98c299 100644 --- a/core/java/android/bluetooth/BluetoothIntent.java +++ b/core/java/android/bluetooth/BluetoothIntent.java @@ -45,6 +45,12 @@ public interface BluetoothIntent { "android.bluetooth.intent.HEADSET_STATE"; public static final String HEADSET_PREVIOUS_STATE = "android.bluetooth.intent.HEADSET_PREVIOUS_STATE"; + public static final String BOND_STATE = + "android.bluetooth.intent.BOND_STATE"; + public static final String BOND_PREVIOUS_STATE = + "android.bluetooth.intent.BOND_PREVIOUS_STATE"; + public static final String REASON = + "android.bluetooth.intent.REASON"; @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ENABLED_ACTION = @@ -105,12 +111,17 @@ public interface BluetoothIntent { public static final String REMOTE_ALIAS_CLEARED_ACTION = "android.bluetooth.intent.action.REMOTE_ALIAS_CLEARED"; - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String BONDING_CREATED_ACTION = - "android.bluetooth.intent.action.BONDING_CREATED"; - @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) - public static final String BONDING_REMOVED_ACTION = - "android.bluetooth.intent.action.BONDING_REMOVED"; + /** + * Broadcast when the bond state of a remote device changes. + * Has string extra ADDRESS and int extras BOND_STATE and + * BOND_PREVIOUS_STATE. + * If BOND_STATE is BluetoothDevice.BOND_NOT_BONDED then will + * also have an int extra REASON with a value of: + * BluetoothDevice.BOND_RESULT_* + * */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String BOND_STATE_CHANGED_ACTION = + "android.bluetooth.intent.action.BOND_STATE_CHANGED_ACTION"; @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String HEADSET_STATE_CHANGED_ACTION = diff --git a/core/java/android/bluetooth/IBluetoothDevice.aidl b/core/java/android/bluetooth/IBluetoothDevice.aidl index e7cc8edc9c6c..59f679f3cd6a 100644 --- a/core/java/android/bluetooth/IBluetoothDevice.aidl +++ b/core/java/android/bluetooth/IBluetoothDevice.aidl @@ -57,11 +57,11 @@ interface IBluetoothDevice boolean isAclConnected(in String address); boolean disconnectRemoteDeviceAcl(in String address); - boolean createBonding(in String address, in IBluetoothDeviceCallback callback); - boolean cancelBondingProcess(in String address); - String[] listBondings(); - boolean hasBonding(in String address); - boolean removeBonding(in String address); + boolean createBond(in String address); + boolean cancelBondProcess(in String address); + boolean removeBond(in String address); + String[] listBonds(); + int getBondState(in String address); String getRemoteName(in String address); String getRemoteAlias(in String address); diff --git a/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl b/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl index 86f44dde9ac4..d25bd560d034 100644 --- a/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl +++ b/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl @@ -21,7 +21,6 @@ package android.bluetooth; */ oneway interface IBluetoothDeviceCallback { - void onCreateBondingResult(in String address, int result); void onGetRemoteServiceChannelResult(in String address, int channel); void onEnableResult(int result); diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 4a92b4c8fb7f..e2d357694bba 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1225,6 +1225,22 @@ public class Intent implements Parcelable { public static final String ACTION_MEDIA_UNMOUNTED = "android.intent.action.MEDIA_UNMOUNTED"; /** + * Broadcast Action: External media is present, and being disk-checked + * The path to the mount point for the checking media is contained in the Intent.mData field. + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_MEDIA_CHECKING = "android.intent.action.MEDIA_CHECKING"; + + /** + * Broadcast Action: External media is present, but is using an incompatible fs (or is blank) + * The path to the mount point for the checking media is contained in the Intent.mData field. + * @hide + */ + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) + public static final String ACTION_MEDIA_NOFS = "android.intent.action.MEDIA_NOFS"; + + /** * Broadcast Action: External media is present and mounted at its mount point. * The path to the mount point for the removed media is contained in the Intent.mData field. * The Intent contains an extra with name "read-only" and Boolean value to indicate if the @@ -1838,6 +1854,23 @@ public class Intent implements Parcelable { * to mail. */ public static final int FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET = 0x00080000; + /** + * If set, this flag will prevent the normal {@link android.app.Activity#onUserLeaving} + * callback from occurring on the current frontmost activity before it is + * paused as the newly-started activity is brought to the front. + * + *

Typically, an activity can rely on that callback to indicate that an + * explicit user action has caused their activity to be moved out of the + * foreground. The callback marks an appropriate point in the activity's + * lifecycle for it to dismiss any notifications that it intends to display + * "until the user has seen them," such as a blinking LED. + * + *

If an activity is ever started via any non-user-driven events such as + * phone-call receipt or an alarm handler, this flag should be passed to {@link + * Context#startActivity Context.startActivity}, ensuring that the pausing + * activity does not think the user has acknowledged its notification. + */ + public static final int FLAG_ACTIVITY_NO_USER_ACTION = 0x00040000; /** * If set, when sending a broadcast only registered receivers will be @@ -3836,6 +3869,7 @@ public class Intent implements Parcelable { * @see #FLAG_ACTIVITY_MULTIPLE_TASK * @see #FLAG_ACTIVITY_NEW_TASK * @see #FLAG_ACTIVITY_NO_HISTORY + * @see #FLAG_ACTIVITY_NO_USER_ACTION * @see #FLAG_ACTIVITY_PREVIOUS_IS_TOP * @see #FLAG_ACTIVITY_RESET_TASK_IF_NEEDED * @see #FLAG_ACTIVITY_SINGLE_TOP diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index fdb2a2f4a3b6..ea86188d2bf9 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -34,6 +34,7 @@ import android.content.pm.PermissionInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.net.Uri; +import android.app.PendingIntent; /** * See {@link PackageManager} for documentation on most of the APIs @@ -184,22 +185,51 @@ interface IPackageManager { int getApplicationEnabledSetting(in String packageName); /** - * Free storage by deleting LRU sorted list of cache files across all applications. - * If the currently available free storage on the device is greater than or equal to the - * requested free storage, no cache files are cleared. If the currently available storage on the - * device is less than the requested free storage, some or all of the cache files across - * all applications are deleted(based on last accessed time) to increase the free storage - * space on the device to the requested value. There is no gurantee that clearing all - * the cache files from all applications will clear up enough storage to achieve the desired - * value. - * @param freeStorageSize The number of bytes of storage to be - * freed by the system. Say if freeStorageSize is XX, - * and the current free storage is YY, - * if XX is less than YY, just return. if not free XX-YY number of - * bytes if possible. - * @param observer callback used to notify when the operation is completed + * Free storage by deleting LRU sorted list of cache files across + * all applications. If the currently available free storage + * on the device is greater than or equal to the requested + * free storage, no cache files are cleared. If the currently + * available storage on the device is less than the requested + * free storage, some or all of the cache files across + * all applications are deleted (based on last accessed time) + * to increase the free storage space on the device to + * the requested value. There is no guarantee that clearing all + * the cache files from all applications will clear up + * enough storage to achieve the desired value. + * @param freeStorageSize The number of bytes of storage to be + * freed by the system. Say if freeStorageSize is XX, + * and the current free storage is YY, + * if XX is less than YY, just return. if not free XX-YY number + * of bytes if possible. + * @param observer call back used to notify when + * the operation is completed */ - void freeApplicationCache(in long freeStorageSize, IPackageDataObserver observer); + void freeStorageAndNotify(in long freeStorageSize, + IPackageDataObserver observer); + + /** + * Free storage by deleting LRU sorted list of cache files across + * all applications. If the currently available free storage + * on the device is greater than or equal to the requested + * free storage, no cache files are cleared. If the currently + * available storage on the device is less than the requested + * free storage, some or all of the cache files across + * all applications are deleted (based on last accessed time) + * to increase the free storage space on the device to + * the requested value. There is no guarantee that clearing all + * the cache files from all applications will clear up + * enough storage to achieve the desired value. + * @param freeStorageSize The number of bytes of storage to be + * freed by the system. Say if freeStorageSize is XX, + * and the current free storage is YY, + * if XX is less than YY, just return. if not free XX-YY number + * of bytes if possible. + * @param opFinishedIntent PendingIntent call back used to + * notify when the operation is completed.May be null + * to indicate that no call back is desired. + */ + void freeStorage(in long freeStorageSize, + in PendingIntent opFinishedIntent); /** * Delete all the cache files in an applications cache directory diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index a5445507a043..4b902e9fe944 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -17,6 +17,7 @@ package android.content.pm; +import android.app.PendingIntent; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -1357,28 +1358,53 @@ public abstract class PackageManager { IPackageDataObserver observer); /** - * Free storage by deleting LRU sorted list of cache files across all applications. - * If the currently available free storage on the device is greater than or equal to the - * requested free storage, no cache files are cleared. If the currently available storage on the - * device is less than the requested free storage, some or all of the cache files across - * all applications are deleted(based on last accessed time) to increase the free storage - * space on the device to the requested value. There is no gurantee that clearing all - * the cache files from all applications will clear up enough storage to achieve the desired - * value. + * Free storage by deleting LRU sorted list of cache files across + * all applications. If the currently available free storage + * on the device is greater than or equal to the requested + * free storage, no cache files are cleared. If the currently + * available storage on the device is less than the requested + * free storage, some or all of the cache files across + * all applications are deleted (based on last accessed time) + * to increase the free storage space on the device to + * the requested value. There is no guarantee that clearing all + * the cache files from all applications will clear up + * enough storage to achieve the desired value. * @param freeStorageSize The number of bytes of storage to be * freed by the system. Say if freeStorageSize is XX, * and the current free storage is YY, - * if XX is less than YY, just return. if not free XX-YY number of - * bytes if possible. - * @param observer callback used to notify when the operation is completed - * {@link android.content.pm.IPackageDataObserver#onRemoveCompleted(String, boolean)} - * will be called when that happens. observer may be null to indicate that - * no callback is desired. - * + * if XX is less than YY, just return. if not free XX-YY number + * of bytes if possible. + * @param observer call back used to notify when + * the operation is completed + * * @hide */ - public abstract void freeApplicationCache(long freeStorageSize, - IPackageDataObserver observer); + public abstract void freeStorageAndNotify(long freeStorageSize, IPackageDataObserver observer); + + /** + * Free storage by deleting LRU sorted list of cache files across + * all applications. If the currently available free storage + * on the device is greater than or equal to the requested + * free storage, no cache files are cleared. If the currently + * available storage on the device is less than the requested + * free storage, some or all of the cache files across + * all applications are deleted (based on last accessed time) + * to increase the free storage space on the device to + * the requested value. There is no guarantee that clearing all + * the cache files from all applications will clear up + * enough storage to achieve the desired value. + * @param freeStorageSize The number of bytes of storage to be + * freed by the system. Say if freeStorageSize is XX, + * and the current free storage is YY, + * if XX is less than YY, just return. if not free XX-YY number + * of bytes if possible. + * @param opFinishedIntent PendingIntent call back used to + * notify when the operation is completed.May be null + * to indicate that no call back is desired. + * + * @hide + */ + public abstract void freeStorage(long freeStorageSize, PendingIntent opFinishedIntent); /** * Retrieve the size information for a package. diff --git a/core/java/android/gadget/GadgetManager.java b/core/java/android/gadget/GadgetManager.java index 49c706e83add..088dc86f9d58 100644 --- a/core/java/android/gadget/GadgetManager.java +++ b/core/java/android/gadget/GadgetManager.java @@ -54,17 +54,22 @@ public class GadgetManager { /** * Sent when it is time to update your gadget. */ - public static final String GADGET_UPDATE_ACTION = "android.gadget.GADGET_UPDATE"; + public static final String GADGET_UPDATE_ACTION = "android.gadget.action.GADGET_UPDATE"; /** * Sent when the gadget is added to a host for the first time. TODO: Maybe we don't want this. */ - public static final String GADGET_ENABLE_ACTION = "android.gadget.GADGET_ENABLE"; + public static final String GADGET_ENABLE_ACTION = "android.gadget.action.GADGET_ENABLE"; /** * Sent when the gadget is removed from the last host. TODO: Maybe we don't want this. */ - public static final String GADGET_DISABLE_ACTION = "android.gadget.GADGET_DISABLE"; + public static final String GADGET_DISABLE_ACTION = "android.gadget.action.GADGET_DISABLE"; + + /** + * Field for the manifest meta-data tag. + */ + public static final String GADGET_PROVIDER_META_DATA = "android.gadget.provider"; static WeakHashMap> sManagerCache = new WeakHashMap(); static IGadgetService sService; @@ -108,10 +113,15 @@ public class GadgetManager { } /** - * Return a list of the gadgets that are currently installed. + * Return a list of the gadget providers that are currently installed. */ - public List getAvailableGadgets() { - return null; + public List getInstalledProviders() { + try { + return sService.getInstalledProviders(); + } + catch (RemoteException e) { + throw new RuntimeException("system server dead?", e); + } } /** diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 1a7547df6da0..3a9b26a9c6f5 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -498,7 +498,15 @@ public class InputMethodService extends AbstractInputMethodService { if (showingCandidates) { setCandidatesViewShown(true); } - showWindow(showingInput); + if (showingInput) { + // If we are showing the full soft keyboard, then go through + // this path to take care of current decisions about fullscreen + // etc. + onShowRequested(InputMethod.SHOW_EXPLICIT); + } else { + // Otherwise just put it back for its candidates. + showWindow(false); + } } } @@ -649,16 +657,14 @@ public class InputMethodService extends AbstractInputMethodService { /** * Override this to control when the input method should run in * fullscreen mode. The default implementation runs in fullsceen only - * when the screen is in landscape mode and the input view is being - * shown ({@link #onEvaluateInputViewShown} returns true). If you change what + * when the screen is in landscape mode. If you change what * this returns, you will need to call {@link #updateFullscreenMode()} * yourself whenever the returned value may have changed to have it * re-evaluated and applied. */ public boolean onEvaluateFullscreenMode() { Configuration config = getResources().getConfiguration(); - return config.orientation == Configuration.ORIENTATION_LANDSCAPE - && onEvaluateInputViewShown(); + return config.orientation == Configuration.ORIENTATION_LANDSCAPE; } /** @@ -870,7 +876,11 @@ public class InputMethodService extends AbstractInputMethodService { } /** - * Called when an input session is starting or restarting. + * Called when the input view is being shown and input has started on + * a new editor. This will always be called after {@link #onStartInput}, + * allowing you to do your general setup there and just view-specific + * setup here. You are guaranteed that {@link #onCreateInputView()} will + * have been called some time before this function is called. * * @param info Description of the type of text being edited. * @param restarting Set to true if we are restarting input on the @@ -892,6 +902,9 @@ public class InputMethodService extends AbstractInputMethodService { * as per {@link InputMethod#showSoftInput(int) InputMethod.showSoftInput(int)}. */ public void onShowRequested(int flags) { + if (!onEvaluateInputViewShown()) { + return; + } if ((flags&InputMethod.SHOW_EXPLICIT) == 0 && onEvaluateFullscreenMode()) { // Don't show if this is not explicit requested by the user and // the input method is fullscreen. That would be too disruptive. @@ -911,9 +924,11 @@ public class InputMethodService extends AbstractInputMethodService { boolean wasVisible = mWindowVisible; mWindowVisible = true; if (!mShowInputRequested) { - if (showInput) { - doShowInput = true; - mShowInputRequested = true; + if (mInputStarted) { + if (showInput) { + doShowInput = true; + mShowInputRequested = true; + } } } else { showInput = true; @@ -1001,7 +1016,7 @@ public class InputMethodService extends AbstractInputMethodService { mInputEditorInfo = attribute; onStartInput(attribute, restarting); if (mWindowVisible) { - if (mWindowCreated) { + if (mShowInputRequested) { onStartInputView(mInputEditorInfo, restarting); } startExtractingText(); diff --git a/core/java/android/inputmethodservice/KeyboardView.java b/core/java/android/inputmethodservice/KeyboardView.java index 6f044b61ada6..2f3b54bee716 100755 --- a/core/java/android/inputmethodservice/KeyboardView.java +++ b/core/java/android/inputmethodservice/KeyboardView.java @@ -153,9 +153,10 @@ public class KeyboardView extends View implements View.OnClickListener { /** Listener for {@link OnKeyboardActionListener}. */ private OnKeyboardActionListener mKeyboardActionListener; - private static final int MSG_REMOVE_PREVIEW = 1; - private static final int MSG_REPEAT = 2; - private static final int MSG_LONGPRESS = 3; + private static final int MSG_SHOW_PREVIEW = 1; + private static final int MSG_REMOVE_PREVIEW = 2; + private static final int MSG_REPEAT = 3; + private static final int MSG_LONGPRESS = 4; private int mVerticalCorrection; private int mProximityThreshold; @@ -198,7 +199,8 @@ public class KeyboardView extends View implements View.OnClickListener { private static final int REPEAT_INTERVAL = 50; // ~20 keys per second private static final int REPEAT_START_DELAY = 400; - private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout(); + private static final int LONGPRESS_TIMEOUT = 800; + // Deemed to be too short : ViewConfiguration.getLongPressTimeout(); private static int MAX_NEARBY_KEYS = 12; private int[] mDistances = new int[MAX_NEARBY_KEYS]; @@ -215,6 +217,9 @@ public class KeyboardView extends View implements View.OnClickListener { @Override public void handleMessage(Message msg) { switch (msg.what) { + case MSG_SHOW_PREVIEW: + mPreviewText.setVisibility(VISIBLE); + break; case MSG_REMOVE_PREVIEW: mPreviewText.setVisibility(INVISIBLE); break; @@ -731,7 +736,7 @@ public class KeyboardView extends View implements View.OnClickListener { return adjustCase(key.label); } } - + private void showPreview(int keyIndex) { int oldKeyIndex = mCurrentKeyIndex; final PopupWindow previewPopup = mPreviewPopup; @@ -751,6 +756,7 @@ public class KeyboardView extends View implements View.OnClickListener { } // If key changed and preview is on ... if (oldKeyIndex != mCurrentKeyIndex && mShowPreview) { + mHandler.removeMessages(MSG_SHOW_PREVIEW); if (previewPopup.isShowing()) { if (keyIndex == NOT_A_KEY) { mHandler.sendMessageDelayed(mHandler @@ -803,7 +809,7 @@ public class KeyboardView extends View implements View.OnClickListener { mPreviewText.getBackground().setState( key.popupResId != 0 ? LONG_PRESSABLE_STATE_SET : EMPTY_STATE_SET); if (previewPopup.isShowing()) { - previewPopup.update(mPopupPreviewX + mOffsetInWindow[0], + previewPopup.update(mPopupParent, mPopupPreviewX + mOffsetInWindow[0], mPopupPreviewY + mOffsetInWindow[1], popupWidth, popupHeight); } else { @@ -811,7 +817,8 @@ public class KeyboardView extends View implements View.OnClickListener { mPopupPreviewX + mOffsetInWindow[0], mPopupPreviewY + mOffsetInWindow[1]); } - mPreviewText.setVisibility(VISIBLE); + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SHOW_PREVIEW, keyIndex, 0), + ViewConfiguration.getTapTimeout()); } } } @@ -1014,6 +1021,7 @@ public class KeyboardView extends View implements View.OnClickListener { break; case MotionEvent.ACTION_UP: + mHandler.removeMessages(MSG_SHOW_PREVIEW); mHandler.removeMessages(MSG_REPEAT); mHandler.removeMessages(MSG_LONGPRESS); if (keyIndex == mCurrentKey) { diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index e065063c21b0..ed7c3663ce28 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -237,7 +237,7 @@ public abstract class BatteryStats { public abstract long computeBatteryRealtime(long curTime, int which); /** - * Returns the total, last, or current uptime in micropeconds. + * Returns the total, last, or current uptime in microseconds. * * @param curTime the current elapsed realtime in microseconds. * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT. @@ -299,6 +299,9 @@ public abstract class BatteryStats { } private final String formatRatioLocked(long num, long den) { + if (den == 0L) { + return "---%"; + } float perc = ((float)num) / ((float)den) * 100; mFormatBuilder.setLength(0); mFormatter.format("%.1f%%", perc); @@ -352,18 +355,20 @@ public abstract class BatteryStats { long batteryUptime = computeBatteryUptime(uSecNow, which); long batteryRealtime = computeBatteryRealtime(getBatteryRealtime(uSecTime), which); long elapsedRealtime = computeRealtime(uSecTime, which); + long uptime = computeUptime(SystemClock.uptimeMillis() * 1000, which); + pw.println(prefix - + " On battery: " + formatTimeMs(batteryUptime) + "(" + + " On battery: " + formatTimeMs(batteryUptime / 1000) + "(" + formatRatioLocked(batteryUptime, batteryRealtime) + ") uptime, " - + formatTimeMs(batteryRealtime) + "(" + + formatTimeMs(batteryRealtime / 1000) + "(" + formatRatioLocked(batteryRealtime, elapsedRealtime) + ") realtime"); pw.println(prefix + " Total: " - + formatTimeMs(computeUptime(SystemClock.uptimeMillis() * 1000, which)) + + formatTimeMs(uptime / 1000) + "uptime, " - + formatTimeMs(elapsedRealtime) + + formatTimeMs(elapsedRealtime / 1000) + "realtime"); pw.println(" "); @@ -479,7 +484,7 @@ public abstract class BatteryStats { if (startTime != 0 || starts != 0 || launches != 0) { pw.println(prefix + " Service " + sent.getKey() + ":"); pw.println(prefix + " Time spent started: " - + formatTimeMs(startTime)); + + formatTimeMs(startTime / 1000)); pw.println(prefix + " Starts: " + starts + ", launches: " + launches); apkActivity = true; diff --git a/core/java/android/provider/Gmail.java b/core/java/android/provider/Gmail.java index 1bbcc3342335..325f19db98a9 100644 --- a/core/java/android/provider/Gmail.java +++ b/core/java/android/provider/Gmail.java @@ -554,13 +554,15 @@ public final class Gmail { * * @param account the account of the conversation * @param conversationId the conversation - * @param maxMessageId the highest message id to whose labels should be changed + * @param maxServerMessageId the highest message id to whose labels should be changed. Note that + * everywhere else in this file messageId means local message id but here you need to use a + * server message id. * @param label the label to add or remove * @param add true to add the label, false to remove it * @throws NonexistentLabelException thrown if the label does not exist */ public void addOrRemoveLabelOnConversation( - String account, long conversationId, long maxMessageId, String label, + String account, long conversationId, long maxServerMessageId, String label, boolean add) throws NonexistentLabelException { if (TextUtils.isEmpty(account)) { @@ -571,7 +573,7 @@ public final class Gmail { AUTHORITY_PLUS_CONVERSATIONS + account + "/" + conversationId + "/labels"); ContentValues values = new ContentValues(); values.put(LabelColumns.CANONICAL_NAME, label); - values.put(ConversationColumns.MAX_MESSAGE_ID, maxMessageId); + values.put(ConversationColumns.MAX_MESSAGE_ID, maxServerMessageId); mContentResolver.insert(uri, values); } else { String encodedLabel; @@ -584,7 +586,7 @@ public final class Gmail { AUTHORITY_PLUS_CONVERSATIONS + account + "/" + conversationId + "/labels/" + encodedLabel); mContentResolver.delete( - uri, ConversationColumns.MAX_MESSAGE_ID, new String[]{"" + maxMessageId}); + uri, ConversationColumns.MAX_MESSAGE_ID, new String[]{"" + maxServerMessageId}); } } @@ -2373,7 +2375,7 @@ public final class Gmail { /** * @return the max message id in the conversation */ - public long getMaxMessageId() { + public long getMaxServerMessageId() { return mCursor.getLong(mMaxMessageIdIndex); } diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java index 0184db83ff7b..87a02e6c2ae2 100644 --- a/core/java/android/provider/MediaStore.java +++ b/core/java/android/provider/MediaStore.java @@ -148,6 +148,13 @@ public final class MediaStore public final static String EXTRA_VIDEO_QUALITY = "android.intent.extra.videoQuality"; /** + * The name of the Intent-extra used to indicate a Uri to be used to + * store the requested image or video. + * @hide + */ + public final static String EXTRA_OUTPUT = "output"; + + /** * Common fields for most MediaProvider tables */ diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index a18f37c3ca1c..abbfd5bdb8e1 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -2121,6 +2121,12 @@ public final class Settings { = "youtube_use_proxy"; /** + * MMS - maximum message size in bytes for a MMS message. + */ + public static final String MMS_MAXIMUM_MESSAGE_SIZE + = "mms_maximum_message_size"; + + /** * Event tags from the kernel event log to upload during checkin. */ public static final String CHECKIN_EVENTS = "checkin_events"; @@ -2685,6 +2691,22 @@ public final class Settings { "short_keylight_delay_ms"; /** + * URL that points to the voice search servers. To be factored out of this class. + */ + public static final String VOICE_SEARCH_URL = "voice_search_url"; + + /** + * Speech encoding used with voice search on 3G networks. To be factored out of this class. + */ + public static final String VOICE_SEARCH_ENCODING_THREE_G = "voice_search_encoding_three_g"; + + /** + * Speech encoding used with voice search on WIFI networks. To be factored out of this class. + */ + public static final String VOICE_SEARCH_ENCODING_WIFI = "voice_search_encoding_wifi"; + + + /** * @deprecated * @hide */ diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java index be784ff3e2fc..8486e4b5acd1 100644 --- a/core/java/android/server/BluetoothA2dpService.java +++ b/core/java/android/server/BluetoothA2dpService.java @@ -84,8 +84,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { mIntentFilter = new IntentFilter(BluetoothIntent.ENABLED_ACTION); mIntentFilter.addAction(BluetoothIntent.DISABLED_ACTION); - mIntentFilter.addAction(BluetoothIntent.BONDING_CREATED_ACTION); - mIntentFilter.addAction(BluetoothIntent.BONDING_REMOVED_ACTION); + mIntentFilter.addAction(BluetoothIntent.BOND_STATE_CHANGED_ACTION); mContext.registerReceiver(mReceiver, mIntentFilter); if (device.isEnabled()) { @@ -111,10 +110,18 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { onBluetoothEnable(); } else if (action.equals(BluetoothIntent.DISABLED_ACTION)) { onBluetoothDisable(); - } else if (action.equals(BluetoothIntent.BONDING_CREATED_ACTION)) { - setSinkPriority(address, BluetoothA2dp.PRIORITY_AUTO); - } else if (action.equals(BluetoothIntent.BONDING_REMOVED_ACTION)) { - setSinkPriority(address, BluetoothA2dp.PRIORITY_OFF); + } else if (action.equals(BluetoothIntent.BOND_STATE_CHANGED_ACTION)) { + int bondState = intent.getIntExtra(BluetoothIntent.BOND_STATE, + BluetoothError.ERROR); + switch(bondState) { + case BluetoothDevice.BOND_BONDED: + setSinkPriority(address, BluetoothA2dp.PRIORITY_AUTO); + break; + case BluetoothDevice.BOND_BONDING: + case BluetoothDevice.BOND_NOT_BONDED: + setSinkPriority(address, BluetoothA2dp.PRIORITY_OFF); + break; + } } } }; diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java index 9bdab9f2957a..3ce34c30a198 100644 --- a/core/java/android/server/BluetoothDeviceService.java +++ b/core/java/android/server/BluetoothDeviceService.java @@ -26,6 +26,7 @@ package android.server; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; // just for dump() +import android.bluetooth.BluetoothError; import android.bluetooth.BluetoothIntent; import android.bluetooth.IBluetoothDevice; import android.bluetooth.IBluetoothDeviceCallback; @@ -49,14 +50,19 @@ import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; +import java.util.ArrayList; import java.util.HashMap; +import java.util.Map; public class BluetoothDeviceService extends IBluetoothDevice.Stub { private static final String TAG = "BluetoothDeviceService"; + private static final boolean DBG = true; + private int mNativeData; private BluetoothEventLoop mEventLoop; private IntentFilter mIntentFilter; private boolean mIsAirplaneSensitive; + private final BondState mBondState = new BondState(); // local cache of bondings private volatile boolean mIsEnabled; // local cache of isEnabledNative() private boolean mIsDiscovering; @@ -79,10 +85,13 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { public synchronized void init() { initializeNativeDataNative(); mIsEnabled = (isEnabledNative() == 1); + if (mIsEnabled) { + mBondState.loadBondState(); + } mIsDiscovering = false; mEventLoop = new BluetoothEventLoop(mContext, this); registerForAirplaneMode(); - + disableEsco(); // TODO: enable eSCO support once its fully supported } private native void initializeNativeDataNative(); @@ -112,7 +121,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { public synchronized boolean disable() { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); - + if (mEnableThread != null && mEnableThread.isAlive()) { return false; } @@ -171,7 +180,6 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { }; private EnableThread mEnableThread; - private String mOutgoingBondingDevAddress = null; private class EnableThread extends Thread { private final IBluetoothDeviceCallback mEnableCallback; @@ -198,6 +206,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { Settings.Secure.BLUETOOTH_ON, 1); mIsDiscovering = false; Intent intent = new Intent(BluetoothIntent.ENABLED_ACTION); + mBondState.loadBondState(); mContext.sendBroadcast(intent, BLUETOOTH_PERM); mHandler.sendMessageDelayed(mHandler.obtainMessage(REGISTER_SDP_RECORDS), 3000); } @@ -208,6 +217,119 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { private native int enableNative(); private native int disableNative(); + /* package */ BondState getBondState() { + return mBondState; + } + + /** local cache of bonding state. + /* we keep our own state to track the intermediate state BONDING, which + /* bluez does not track. + * All addreses must be passed in upper case. + */ + public class BondState { + private final HashMap mState = new HashMap(); + private final HashMap mPinAttempt = new HashMap(); + + public synchronized void loadBondState() { + if (!mIsEnabled) { + return; + } + String[] bonds = listBondingsNative(); + if (bonds == null) { + return; + } + mState.clear(); + if (DBG) log("found " + bonds.length + " bonded devices"); + for (String address : bonds) { + mState.put(address.toUpperCase(), BluetoothDevice.BOND_BONDED); + } + } + + public synchronized void setBondState(String address, int state) { + setBondState(address, state, 0); + } + + /** reason is ignored unless state == BOND_NOT_BONDED */ + public synchronized void setBondState(String address, int state, int reason) { + int oldState = getBondState(address); + if (oldState == state) { + return; + } + if (DBG) log(address + " bond state " + oldState + " -> " + state + " (" + + reason + ")"); + Intent intent = new Intent(BluetoothIntent.BOND_STATE_CHANGED_ACTION); + intent.putExtra(BluetoothIntent.ADDRESS, address); + intent.putExtra(BluetoothIntent.BOND_STATE, state); + intent.putExtra(BluetoothIntent.BOND_PREVIOUS_STATE, oldState); + if (state == BluetoothDevice.BOND_NOT_BONDED) { + if (reason <= 0) { + Log.w(TAG, "setBondState() called to unbond device with invalid reason code " + + "Setting reason = BOND_RESULT_REMOVED"); + reason = BluetoothDevice.UNBOND_REASON_REMOVED; + } + intent.putExtra(BluetoothIntent.REASON, reason); + mState.remove(address); + } else { + mState.put(address, state); + } + if (state == BluetoothDevice.BOND_BONDING) { + mPinAttempt.put(address, Integer.valueOf(0)); + } else { + mPinAttempt.remove(address); + } + mContext.sendBroadcast(intent, BLUETOOTH_PERM); + } + + public synchronized int getBondState(String address) { + Integer state = mState.get(address); + if (state == null) { + return BluetoothDevice.BOND_NOT_BONDED; + } + return state.intValue(); + } + + public synchronized String[] listBonds() { + ArrayList result = new ArrayList(mState.size()); + for (Map.Entry e : mState.entrySet()) { + if (e.getValue().intValue() == BluetoothDevice.BOND_BONDED) { + result.add(e.getKey()); + } + } + return result.toArray(new String[result.size()]); + } + + public synchronized int getAttempt(String address) { + Integer attempt = mPinAttempt.get(address); + if (attempt == null) { + return 0; + } + return attempt.intValue(); + } + + public synchronized void attempt(String address) { + Integer attempt = mPinAttempt.get(address); + if (attempt == null) { + return; + } + mPinAttempt.put(address, new Integer(attempt.intValue() + 1)); + } + + } + private native String[] listBondingsNative(); + + private static String toBondStateString(int bondState) { + switch (bondState) { + case BluetoothDevice.BOND_NOT_BONDED: + return "not bonded"; + case BluetoothDevice.BOND_BONDING: + return "bonding"; + case BluetoothDevice.BOND_BONDED: + return "bonded"; + default: + return "??????"; + } + } + public synchronized String getAddress() { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); return getAddressNative(); @@ -231,12 +353,6 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { } private native boolean setNameNative(String name); - public synchronized String[] listBondings() { - mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); - return listBondingsNative(); - } - private native String[] listBondingsNative(); - public synchronized String getMajorClass() { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); return getMajorClassNative(); @@ -551,106 +667,45 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { } private native boolean disconnectRemoteDeviceNative(String address); - private static final int MAX_OUTSTANDING_ASYNC = 32; - /** - * This method initiates a Bonding request to a remote device. - * - * - * @param address The Bluetooth address of the remote device - * - * @see #createBonding - * @see #cancelBondingProcess - * @see #removeBonding - * @see #hasBonding - * @see #listBondings - * - * @see android.bluetooth.PasskeyAgent - */ - public synchronized boolean createBonding(String address, IBluetoothDeviceCallback callback) { + public synchronized boolean createBond(String address) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); if (!BluetoothDevice.checkBluetoothAddress(address)) { return false; } - - HashMap callbacks = mEventLoop.getCreateBondingCallbacks(); - if (callbacks.containsKey(address)) { - Log.w(TAG, "createBonding() already in progress for " + address); + address = address.toUpperCase(); + if (mBondState.getBondState(address) != BluetoothDevice.BOND_NOT_BONDED) { return false; } - // Protect from malicious clients - limit number of outstanding requests - if (callbacks.size() > MAX_OUTSTANDING_ASYNC) { - Log.w(TAG, "Too many outstanding bonding requests, dropping request for " + address); - return false; - } - - callbacks.put(address, callback); if (!createBondingNative(address, 60000 /* 1 minute */)) { - callbacks.remove(address); return false; } - mOutgoingBondingDevAddress = address; + + mBondState.setBondState(address, BluetoothDevice.BOND_BONDING); return true; } - private native boolean createBondingNative(String address, int timeout_ms); - - /*package*/ String getOutgoingBondingDevAddress() { - return mOutgoingBondingDevAddress; - } - /*package*/ void setOutgoingBondingDevAddress(String outgoingBondingDevAddress) { - mOutgoingBondingDevAddress = outgoingBondingDevAddress; - } - - /** - * This method cancels a pending bonding request. - * - * @param address The Bluetooth address of the remote device to which a - * bonding request has been initiated. - * - * Note: When a request is canceled, method - * {@link CreateBondingResultNotifier#notifyAuthenticationFailed} - * will be called on the object passed to method - * {@link #createBonding}. - * - * Note: it is safe to call this method when there is no outstanding - * bonding request. - * - * @see #createBonding - * @see #cancelBondingProcess - * @see #removeBonding - * @see #hasBonding - * @see #listBondings - */ - public synchronized boolean cancelBondingProcess(String address) { + public synchronized boolean cancelBondProcess(String address) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); if (!BluetoothDevice.checkBluetoothAddress(address)) { return false; } - return cancelBondingProcessNative(address); + address = address.toUpperCase(); + if (mBondState.getBondState(address) != BluetoothDevice.BOND_BONDING) { + return false; + } + + mBondState.setBondState(address, BluetoothDevice.BOND_NOT_BONDED, + BluetoothDevice.UNBOND_REASON_CANCELLED); + cancelBondingProcessNative(address); + return true; } private native boolean cancelBondingProcessNative(String address); - /** - * This method removes a bonding to a remote device. This is a local - * operation only, resulting in this adapter "forgetting" the bonding - * information about the specified remote device. The other device itself - * does not know what the bonding has been torn down. The next time either - * device attemps to connect to the other, the connection will fail, and - * the pairing procedure will have to be re-initiated. - * - * @param address The Bluetooth address of the remote device. - * - * @see #createBonding - * @see #cancelBondingProcess - * @see #removeBonding - * @see #hasBonding - * @see #listBondings - */ - public synchronized boolean removeBonding(String address) { + public synchronized boolean removeBond(String address) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); if (!BluetoothDevice.checkBluetoothAddress(address)) { @@ -660,14 +715,18 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { } private native boolean removeBondingNative(String address); - public synchronized boolean hasBonding(String address) { + public synchronized String[] listBonds() { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + return mBondState.listBonds(); + } + + public synchronized int getBondState(String address) { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); if (!BluetoothDevice.checkBluetoothAddress(address)) { - return false; + return BluetoothError.ERROR; } - return hasBondingNative(address); + return mBondState.getBondState(address.toUpperCase()); } - private native boolean hasBondingNative(String address); public synchronized String[] listAclConnections() { mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); @@ -1016,6 +1075,8 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { } private native byte[] getRemoteServiceRecordNative(String address, int handle); + private static final int MAX_OUTSTANDING_ASYNC = 32; + // AIDL does not yet support short's public synchronized boolean getRemoteServiceChannel(String address, int uuid16, IBluetoothDeviceCallback callback) { @@ -1051,6 +1112,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { !BluetoothDevice.checkBluetoothAddress(address)) { return false; } + address = address.toUpperCase(); Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); if (data == null) { Log.w(TAG, "setPin(" + address + ") called but no native data available, " + @@ -1076,6 +1138,7 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { if (!BluetoothDevice.checkBluetoothAddress(address)) { return false; } + address = address.toUpperCase(); Integer data = mEventLoop.getPasskeyAgentRequestData().remove(address); if (data == null) { Log.w(TAG, "cancelPin(" + address + ") called but no native data available, " + @@ -1143,25 +1206,20 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { BluetoothHeadset headset = new BluetoothHeadset(mContext, null); - pw.println("\n--Bondings--"); - String[] addresses = listBondings(); - for (String address : addresses) { - String name = getRemoteName(address); - pw.println(address + " (" + name + ")"); - } + String[] addresses = listRemoteDevices(); - pw.println("\n--Current ACL Connections--"); - addresses = listAclConnections(); + pw.println("\n--Known devices--"); for (String address : addresses) { - String name = getRemoteName(address); - pw.println(address + " (" + name + ")"); + pw.printf("%s %10s (%d) %s\n", address, + toBondStateString(mBondState.getBondState(address)), + mBondState.getAttempt(address), + getRemoteName(address)); } - pw.println("\n--Known Devices--"); - addresses = listRemoteDevices(); + addresses = listAclConnections(); + pw.println("\n--ACL connected devices--"); for (String address : addresses) { - String name = getRemoteName(address); - pw.println(address + " (" + name + ")"); + pw.println(address); } // Rather not do this from here, but no-where else and I need this @@ -1189,4 +1247,8 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { } pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive); } + + private static void log(String msg) { + Log.d(TAG, msg); + } } diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java index 2d8aaccfb9bf..4f63f9835033 100644 --- a/core/java/android/server/BluetoothEventLoop.java +++ b/core/java/android/server/BluetoothEventLoop.java @@ -16,8 +16,9 @@ package android.server; -import android.bluetooth.BluetoothClass.Device; +import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothError; import android.bluetooth.BluetoothIntent; import android.bluetooth.IBluetoothDeviceCallback; import android.content.Context; @@ -41,11 +42,9 @@ class BluetoothEventLoop { private int mNativeData; private Thread mThread; private boolean mInterrupted; - private HashMap mCreateBondingCallbacks; private HashMap mPasskeyAgentRequestData; private HashMap mGetRemoteServiceChannelCallbacks; - private HashMap mDefaultPinData; - private BluetoothDeviceService mBluetoothService; + private BluetoothDeviceService mBluetoothService; private Context mContext; private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN; @@ -57,10 +56,8 @@ class BluetoothEventLoop { /* pacakge */ BluetoothEventLoop(Context context, BluetoothDeviceService bluetoothService) { mBluetoothService = bluetoothService; mContext = context; - mCreateBondingCallbacks = new HashMap(); mPasskeyAgentRequestData = new HashMap(); mGetRemoteServiceChannelCallbacks = new HashMap(); - mDefaultPinData = new HashMap(); initializeNativeDataNative(); } private native void initializeNativeDataNative(); @@ -74,9 +71,6 @@ class BluetoothEventLoop { } private native void cleanupNativeDataNative(); - /* pacakge */ HashMap getCreateBondingCallbacks() { - return mCreateBondingCallbacks; - } /* pacakge */ HashMap getRemoteServiceChannelCallbacks() { return mGetRemoteServiceChannelCallbacks; } @@ -235,33 +229,24 @@ class BluetoothEventLoop { mContext.sendBroadcast(intent, BLUETOOTH_PERM); } - private void onCreateBondingResult(String address, boolean result) { - mBluetoothService.setOutgoingBondingDevAddress(null); - IBluetoothDeviceCallback callback = mCreateBondingCallbacks.get(address); - if (callback != null) { - try { - callback.onCreateBondingResult(address, - result ? BluetoothDevice.RESULT_SUCCESS : - BluetoothDevice.RESULT_FAILURE); - } catch (RemoteException e) {} - mCreateBondingCallbacks.remove(address); - } + private void onCreateBondingResult(String address, int result) { + address = address.toUpperCase(); + if (result == BluetoothError.SUCCESS) { + mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_BONDED); + } else { + mBluetoothService.getBondState().setBondState(address, + BluetoothDevice.BOND_NOT_BONDED, result); + } } - + public void onBondingCreated(String address) { - Intent intent = new Intent(BluetoothIntent.BONDING_CREATED_ACTION); - intent.putExtra(BluetoothIntent.ADDRESS, address); - mContext.sendBroadcast(intent, BLUETOOTH_PERM); + mBluetoothService.getBondState().setBondState(address.toUpperCase(), + BluetoothDevice.BOND_BONDED); } - - public void onBondingRemoved(String address) { - Intent intent = new Intent(BluetoothIntent.BONDING_REMOVED_ACTION); - intent.putExtra(BluetoothIntent.ADDRESS, address); - mContext.sendBroadcast(intent, BLUETOOTH_PERM); - if (mDefaultPinData.containsKey(address)) { - mDefaultPinData.remove(address); - } + public void onBondingRemoved(String address) { + mBluetoothService.getBondState().setBondState(address.toUpperCase(), + BluetoothDevice.BOND_NOT_BONDED, BluetoothDevice.UNBOND_REASON_REMOVED); } public void onNameChanged(String name) { @@ -271,24 +256,24 @@ class BluetoothEventLoop { } public void onPasskeyAgentRequest(String address, int nativeData) { - mPasskeyAgentRequestData.put(address, new Integer(nativeData)); - - if (address.equals(mBluetoothService.getOutgoingBondingDevAddress())) { + address = address.toUpperCase(); + mPasskeyAgentRequestData.put(address, new Integer(nativeData)); + + if (mBluetoothService.getBondState().getBondState(address) == + BluetoothDevice.BOND_BONDING) { + // we initiated the bonding int btClass = mBluetoothService.getRemoteClass(address); - int remoteDeviceClass = Device.getDevice(btClass); - if (remoteDeviceClass == Device.AUDIO_VIDEO_WEARABLE_HEADSET || - remoteDeviceClass == Device.AUDIO_VIDEO_HANDSFREE || - remoteDeviceClass == Device.AUDIO_VIDEO_HEADPHONES || - remoteDeviceClass == Device.AUDIO_VIDEO_PORTABLE_AUDIO || - remoteDeviceClass == Device.AUDIO_VIDEO_CAR_AUDIO || - remoteDeviceClass == Device.AUDIO_VIDEO_HIFI_AUDIO) { - if (!mDefaultPinData.containsKey(address)) { - mDefaultPinData.put(address, false); - } - if (!mDefaultPinData.get(address)) { - mDefaultPinData.remove(address); - mDefaultPinData.put(address, true); + // try 0000 once if the device looks dumb + switch (BluetoothClass.Device.getDevice(btClass)) { + case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET: + case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE: + case BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES: + case BluetoothClass.Device.AUDIO_VIDEO_PORTABLE_AUDIO: + case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO: + case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO: + if (mBluetoothService.getBondState().getAttempt(address) < 1) { + mBluetoothService.getBondState().attempt(address); mBluetoothService.setPin(address, BluetoothDevice.convertPinToBytes("0000")); return; } @@ -298,18 +283,17 @@ class BluetoothEventLoop { intent.putExtra(BluetoothIntent.ADDRESS, address); mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); } - + public void onPasskeyAgentCancel(String address) { + address = address.toUpperCase(); mPasskeyAgentRequestData.remove(address); - if (mDefaultPinData.containsKey(address)) { - mDefaultPinData.remove(address); - mDefaultPinData.put(address, false); - } Intent intent = new Intent(BluetoothIntent.PAIRING_CANCEL_ACTION); intent.putExtra(BluetoothIntent.ADDRESS, address); mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM); + mBluetoothService.getBondState().setBondState(address, BluetoothDevice.BOND_NOT_BONDED, + BluetoothDevice.UNBOND_REASON_CANCELLED); } - + private void onGetRemoteServiceChannelResult(String address, int channel) { IBluetoothDeviceCallback callback = mGetRemoteServiceChannelCallbacks.get(address); if (callback != null) { diff --git a/core/java/android/server/search/SearchableInfo.java b/core/java/android/server/search/SearchableInfo.java index ac4cdb9d0cfc..c8f395e8a03c 100644 --- a/core/java/android/server/search/SearchableInfo.java +++ b/core/java/android/server/search/SearchableInfo.java @@ -704,6 +704,7 @@ public final class SearchableInfo implements Parcelable { * positioned at the location in the buffer where it was written. */ public SearchableInfo(Parcel in) { + mSearchable = in.readInt() != 0; mLabelId = in.readInt(); mSearchActivity = ComponentName.readFromParcel(in); mHintId = in.readInt(); @@ -733,6 +734,7 @@ public final class SearchableInfo implements Parcelable { } public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mSearchable ? 1 : 0); dest.writeInt(mLabelId); mSearchActivity.writeToParcel(dest, flags); dest.writeInt(mHintId); diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java index 64356d547152..405d9341181c 100644 --- a/core/java/android/text/TextUtils.java +++ b/core/java/android/text/TextUtils.java @@ -659,8 +659,8 @@ public class TextUtils { p.writeInt(0); } - p.writeInt(tas.getTextSize()); p.writeInt(tas.getTextStyle()); + p.writeInt(tas.getTextSize()); ColorStateList csl = tas.getTextColor(); if (csl == null) { @@ -799,8 +799,8 @@ public class TextUtils { p.readInt() != 0 ? p.readString() : null, - p.readInt(), - p.readInt(), + p.readInt(), // style + p.readInt(), // size p.readInt() != 0 ? ColorStateList.CREATOR.createFromParcel(p) : null, diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index a6def51784c5..6af4915f8185 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -21,6 +21,7 @@ import android.content.res.Configuration; import android.graphics.Rect; import android.os.IBinder; import android.os.LocalPowerManager; +import android.view.animation.Animation; /** * This interface supplies all UI-specific behavior of the window manager. An @@ -247,6 +248,13 @@ public interface WindowManagerPolicy { public WindowState getAppStartingWindow(); /** + * Is this window visible? It is not visible if there is no + * surface, or we are in the process of running an exit animation + * that will remove the surface. + */ + boolean isVisibleLw(); + + /** * Is this window currently visible to the user on-screen? It is * displayed either if it is visible or it is currently running an * animation before no longer being visible. Must be called with the @@ -282,7 +290,7 @@ public interface WindowManagerPolicy { * regardless of whether the client or window manager would like * it shown. Must be called with the window manager lock held. */ - public void hideLw(); + public void hideLw(boolean doAnimation); /** * Can be called to undo the effect of {@link #hideLw}, allowing a @@ -290,7 +298,7 @@ public interface WindowManagerPolicy { * also like it to be shown. Must be called with the window manager * lock held. */ - public void showLw(); + public void showLw(boolean doAnimation); } /** No transition happening. */ diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java index 27461ff6a687..bd7b0507d85b 100644 --- a/core/java/android/view/inputmethod/InputConnection.java +++ b/core/java/android/view/inputmethod/InputConnection.java @@ -177,6 +177,19 @@ public interface InputConnection { public boolean commitCompletion(CompletionInfo text); /** + * Tell the editor that you are starting a batch of editor operations. + * The editor will try to avoid sending you updates about its state + * until {@link #endBatchEdit} is called. + */ + public boolean beginBatchEdit(); + + /** + * Tell the editor that you are done with a batch edit previously + * initiated with {@link #endBatchEdit}. + */ + public boolean endBatchEdit(); + + /** * Send a key event to the process that is currently attached through * this input connection. The event will be dispatched like a normal * key event, to the currently focused; this generally is the view that diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java index a41955c04771..f65b2a1081c7 100644 --- a/core/java/android/view/inputmethod/InputConnectionWrapper.java +++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java @@ -77,6 +77,14 @@ public class InputConnectionWrapper implements InputConnection { return mBase.commitCompletion(text); } + public boolean beginBatchEdit() { + return mBase.beginBatchEdit(); + } + + public boolean endBatchEdit() { + return mBase.endBatchEdit(); + } + public boolean sendKeyEvent(KeyEvent event) { return mBase.sendKeyEvent(event); } diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index ba40782072a9..a9a95944dc4a 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -293,6 +293,14 @@ public final class InputMethodManager { return false; } + public boolean beginBatchEdit() { + return false; + } + + public boolean endBatchEdit() { + return false; + } + public boolean commitCompletion(CompletionInfo text) { return false; } @@ -401,6 +409,12 @@ public final class InputMethodManager { }; final InputConnection mDummyInputConnection = new BaseInputConnection(this) { + public boolean beginBatchEdit() { + return false; + } + public boolean endBatchEdit() { + return false; + } public boolean commitText(CharSequence text, int newCursorPosition) { return false; } diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java index c45ab29fa8c4..3f2bbe5a7908 100644 --- a/core/java/android/webkit/LoadListener.java +++ b/core/java/android/webkit/LoadListener.java @@ -167,7 +167,7 @@ class LoadListener extends Handler implements EventHandler { * should do with them. */ if (mNativeLoader != 0) { - commitHeaders(); + commitHeadersCheckRedirect(); } break; @@ -458,11 +458,6 @@ class LoadListener extends Handler implements EventHandler { if (Config.LOGV) { Log.v(LOGTAG, "LoadListener.data(): url: " + url()); } - - if (ignoreCallbacks()) { - return; - } - // Decode base64 data // Note: It's fine that we only decode base64 here and not in the other // data call because the only caller of the stream version is not @@ -484,7 +479,7 @@ class LoadListener extends Handler implements EventHandler { sendMessage = mDataBuilder.isEmpty(); mDataBuilder.append(data, 0, length); } - if (sendMessage) { + if (sendMessage && !ignoreCallbacks()) { // Send a message whenever data comes in after a write to WebCore sendMessageInternal(obtainMessage(MSG_CONTENT_DATA)); } @@ -850,7 +845,8 @@ class LoadListener extends Handler implements EventHandler { return mContentLength; } - private void commitHeaders() { + // Commit the headers if the status code is not a redirect. + private void commitHeadersCheckRedirect() { if (mCancelled) return; // do not call webcore if it is redirect. According to the code in @@ -860,6 +856,11 @@ class LoadListener extends Handler implements EventHandler { return; } + commitHeaders(); + } + + // This commits the headers without checking the response status code. + private void commitHeaders() { // Commit the headers to WebCore int nativeResponse = createNativeResponse(); // The native code deletes the native response object. @@ -1075,7 +1076,11 @@ class LoadListener extends Handler implements EventHandler { } } } else { - cancel(); + // With a null redirect, commit the original headers, the buffered + // data, and then finish the load. + commitHeaders(); + commitLoad(); + nativeFinished(); } if (Config.LOGV) { diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 9cfc6225a3d7..cab278beb375 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -288,10 +288,6 @@ public class WebView extends AbsoluteLayout // The time that the Zoom Controls are visible before fading away private static final long ZOOM_CONTROLS_TIMEOUT = ViewConfiguration.getZoomControlsTimeout(); - // Wait a short time before sending kit focus message, in case - // the user is still moving around, to avoid rebuilding the display list - // prematurely - private static final long SET_KIT_FOCUS_DELAY = 250; // The amount of content to overlap between two screens when going through // pages with the space bar, in pixels. private static final int PAGE_SCROLL_OVERLAP = 24; @@ -4725,8 +4721,7 @@ public class WebView extends AbsoluteLayout // called by JNI private void sendKitFocus() { WebViewCore.FocusData focusData = new WebViewCore.FocusData(mFocusData); - mWebViewCore.sendMessageDelayed(EventHub.SET_KIT_FOCUS, focusData, - SET_KIT_FOCUS_DELAY); + mWebViewCore.sendMessage(EventHub.SET_KIT_FOCUS, focusData); } // called by JNI diff --git a/core/java/android/widget/Button.java b/core/java/android/widget/Button.java index f2868af76ae7..5e692d4fbbe1 100644 --- a/core/java/android/widget/Button.java +++ b/core/java/android/widget/Button.java @@ -21,6 +21,7 @@ import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.KeyEvent; +import android.widget.RemoteViews.RemoteView; /** @@ -54,6 +55,7 @@ import android.view.KeyEvent; * {@link android.R.styleable#View View Attributes} *

*/ +@RemoteView public class Button extends TextView { public Button(Context context) { this(context, null); diff --git a/core/java/android/widget/ImageButton.java b/core/java/android/widget/ImageButton.java index 5c564287a3c4..4c1cbf6a2f91 100644 --- a/core/java/android/widget/ImageButton.java +++ b/core/java/android/widget/ImageButton.java @@ -21,6 +21,7 @@ import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.view.MotionEvent; +import android.widget.RemoteViews.RemoteView; import java.util.Map; @@ -36,6 +37,7 @@ import java.util.Map; * {@link android.R.styleable#View View Attributes} *

*/ +@RemoteView public class ImageButton extends ImageView { public ImageButton(Context context) { this(context, null); diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 54951b7d3206..572109574aa0 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -16,6 +16,8 @@ package android.widget; +import android.app.PendingIntent; +import android.app.PendingIntent.CanceledException; import android.content.Context; import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; @@ -31,6 +33,7 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.LayoutInflater.Filter; +import android.view.View.OnClickListener; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -371,6 +374,52 @@ public class RemoteViews implements Parcelable, Filter { public final static int TAG = 6; } + + /** + * Equivalent to calling + * {@link android.view.View#setOnClickListener(android.view.View.OnClickListener)} + * to launch the provided {@link PendingIntent}. + */ + private class SetOnClickPendingIntent extends Action { + public SetOnClickPendingIntent(int id, PendingIntent pendingIntent) { + this.viewId = id; + this.pendingIntent = pendingIntent; + } + + public SetOnClickPendingIntent(Parcel parcel) { + viewId = parcel.readInt(); + pendingIntent = PendingIntent.readPendingIntentOrNullFromParcel(parcel); + } + + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(TAG); + dest.writeInt(viewId); + pendingIntent.writeToParcel(dest, 0 /* no flags */); + } + + @Override + public void apply(View root) { + final View target = root.findViewById(viewId); + if (target != null && pendingIntent != null) { + OnClickListener listener = new OnClickListener() { + public void onClick(View v) { + try { + // TODO: Unregister this handler if PendingIntent.FLAG_ONE_SHOT? + pendingIntent.send(); + } catch (CanceledException e) { + throw new ActionException(e.toString()); + } + } + }; + target.setOnClickListener(listener); + } + } + + int viewId; + PendingIntent pendingIntent; + + public final static int TAG = 7; + } /** * Create a new RemoteViews object that will display the views contained @@ -419,6 +468,9 @@ public class RemoteViews implements Parcelable, Filter { case SetProgressBar.TAG: mActions.add(new SetProgressBar(parcel)); break; + case SetOnClickPendingIntent.TAG: + mActions.add(new SetOnClickPendingIntent(parcel)); + break; default: throw new ActionException("Tag " + tag + "not found"); } @@ -491,8 +543,6 @@ public class RemoteViews implements Parcelable, Filter { * * @param viewId The id of the view whose drawable should change * @param bitmap The new Bitmap for the drawable - * - * @hide pending API Council approval to extend the public API */ public void setImageViewBitmap(int viewId, Bitmap bitmap) { addAction(new SetImageViewBitmap(viewId, bitmap)); @@ -533,6 +583,18 @@ public class RemoteViews implements Parcelable, Filter { } /** + * Equivalent to calling + * {@link android.view.View#setOnClickListener(android.view.View.OnClickListener)} + * to launch the provided {@link PendingIntent}. + * + * @param viewId The id of the view that will trigger the {@link PendingIntent} when clicked + * @param pendingIntent The {@link PendingIntent} to send when user clicks + */ + public void setOnClickPendingIntent(int viewId, PendingIntent pendingIntent) { + addAction(new SetOnClickPendingIntent(viewId, pendingIntent)); + } + + /** * Inflates the view hierarchy represented by this object and applies * all of the actions. * diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 8baed7d71b44..aa70663ff649 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -235,6 +235,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener float[] mTmpOffset = new float[2]; ExtractedTextRequest mExtracting; final ExtractedText mTmpExtracted = new ExtractedText(); + boolean mBatchEditing; } InputMethodState mInputMethodState; @@ -3505,7 +3506,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ InputMethodManager imm = InputMethodManager.peekInstance(); - if (highlight != null && mInputMethodState != null && imm != null) { + if (highlight != null && mInputMethodState != null + && !mInputMethodState.mBatchEditing && imm != null) { if (imm.isActive(this)) { int candStart = -1; int candEnd = -1; @@ -3865,6 +3867,38 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } /** + * Called by the framework in response to a request to begin a batch + * of edit operations from the current input method, as a result of + * it calling {@link InputConnection#beginBatchEdit + * InputConnection.beginBatchEdit()}. The default implementation sets + * up the TextView's internal state to take care of this; if overriding + * you should call through to the super class. + */ + public void onBeginBatchEdit() { + if (mInputMethodState != null) { + // XXX we should be smarter here, such as not doing invalidates + // until all edits are done. + mInputMethodState.mBatchEditing = true; + } + } + + /** + * Called by the framework in response to a request to end a batch + * of edit operations from the current input method, as a result of + * it calling {@link InputConnection#endBatchEdit + * InputConnection.endBatchEdit()}. The default implementation sets + * up the TextView's internal state to take care of this; if overriding + * you should call through to the super class. + */ + public void onEndBatchEdit() { + if (mInputMethodState != null) { + mInputMethodState.mBatchEditing = false; + // Cheezy way to get us to report the current cursor location. + invalidateCursor(); + } + } + + /** * Called by the framework in response to a private command from the * current method, provided by it calling * {@link InputConnection#performPrivateCommand @@ -5271,6 +5305,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mError != null) { hideError(); } + // Don't leave us in the middle of a batch edit. + onEndBatchEdit(); } startStopMarquee(focused); @@ -5300,6 +5336,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mBlink != null) { mBlink.cancel(); } + // Don't leave us in the middle of a batch edit. + onEndBatchEdit(); } startStopMarquee(hasWindowFocus); diff --git a/core/java/com/android/internal/gadget/IGadgetService.aidl b/core/java/com/android/internal/gadget/IGadgetService.aidl index 0117d1df4239..6f9af0453144 100644 --- a/core/java/com/android/internal/gadget/IGadgetService.aidl +++ b/core/java/com/android/internal/gadget/IGadgetService.aidl @@ -25,4 +25,5 @@ interface IGadgetService { void deleteGadgetId(int gadgetId); void bindGadgetId(int gadgetId, in ComponentName provider); GadgetInfo getGadgetInfo(int gadgetId); + List getInstalledProviders(); } diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java index d6042591dad2..011e9446985a 100644 --- a/core/java/com/android/internal/view/IInputConnectionWrapper.java +++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java @@ -26,6 +26,8 @@ public class IInputConnectionWrapper extends IInputContext.Stub { private static final int DO_FINISH_COMPOSING_TEXT = 65; private static final int DO_SEND_KEY_EVENT = 70; private static final int DO_DELETE_SURROUNDING_TEXT = 80; + private static final int DO_BEGIN_BATCH_EDIT = 90; + private static final int DO_END_BATCH_EDIT = 95; private static final int DO_HIDE_STATUS_ICON = 100; private static final int DO_SHOW_STATUS_ICON = 110; private static final int DO_PERFORM_PRIVATE_COMMAND = 120; @@ -107,6 +109,14 @@ public class IInputConnectionWrapper extends IInputContext.Stub { leftLength, rightLength)); } + public void beginBatchEdit() { + dispatchMessage(obtainMessage(DO_BEGIN_BATCH_EDIT)); + } + + public void endBatchEdit() { + dispatchMessage(obtainMessage(DO_END_BATCH_EDIT)); + } + public void hideStatusIcon() { dispatchMessage(obtainMessage(DO_HIDE_STATUS_ICON)); } @@ -202,6 +212,14 @@ public class IInputConnectionWrapper extends IInputContext.Stub { mInputConnection.deleteSurroundingText(msg.arg1, msg.arg2); return; } + case DO_BEGIN_BATCH_EDIT: { + mInputConnection.beginBatchEdit(); + return; + } + case DO_END_BATCH_EDIT: { + mInputConnection.beginBatchEdit(); + return; + } case DO_HIDE_STATUS_ICON: { mInputConnection.hideStatusIcon(); return; diff --git a/core/java/com/android/internal/view/IInputContext.aidl b/core/java/com/android/internal/view/IInputContext.aidl index 55a9784b26d9..b048ce292e2b 100644 --- a/core/java/com/android/internal/view/IInputContext.aidl +++ b/core/java/com/android/internal/view/IInputContext.aidl @@ -48,6 +48,10 @@ import com.android.internal.view.IInputContextCallback; void commitCompletion(in CompletionInfo completion); + void beginBatchEdit(); + + void endBatchEdit(); + void sendKeyEvent(in KeyEvent event); void clearMetaKeyStates(int states); diff --git a/core/java/com/android/internal/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java index 1cfaf1713e1f..a9ba5f6190ff 100644 --- a/core/java/com/android/internal/view/InputConnectionWrapper.java +++ b/core/java/com/android/internal/view/InputConnectionWrapper.java @@ -259,6 +259,24 @@ public class InputConnectionWrapper implements InputConnection { } } + public boolean beginBatchEdit() { + try { + mIInputContext.beginBatchEdit(); + return true; + } catch (RemoteException e) { + return false; + } + } + + public boolean endBatchEdit() { + try { + mIInputContext.endBatchEdit(); + return true; + } catch (RemoteException e) { + return false; + } + } + public boolean sendKeyEvent(KeyEvent event) { try { mIInputContext.sendKeyEvent(event); diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java index 263220bcd094..a2673a56b949 100644 --- a/core/java/com/android/internal/widget/EditableInputConnection.java +++ b/core/java/com/android/internal/widget/EditableInputConnection.java @@ -242,6 +242,18 @@ public class EditableInputConnection extends BaseInputConnection { return true; } + public boolean beginBatchEdit() { + if (mTextView == null) return false; + mTextView.onBeginBatchEdit(); + return true; + } + + public boolean endBatchEdit() { + if (mTextView == null) return false; + mTextView.onEndBatchEdit(); + return true; + } + public boolean clearMetaKeyStates(int states) { final Editable content = getEditable(); if (content == null) return false; diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index 329a695fee52..65f44d504257 100644 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -507,6 +507,18 @@ static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject, } } +static void Bitmap_copyPixelsFromBuffer(JNIEnv* env, jobject, + const SkBitmap* bitmap, jobject jbuffer) { + SkAutoLockPixels alp(*bitmap); + void* dst = bitmap->getPixels(); + + if (NULL != dst) { + android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE); + // the java side has already checked that buffer is large enough + memcpy(dst, abp.pointer(), bitmap->getSize()); + } +} + /////////////////////////////////////////////////////////////////////////////// #include @@ -538,7 +550,9 @@ static JNINativeMethod gBitmapMethods[] = { { "nativeSetPixel", "(IIII)V", (void*)Bitmap_setPixel }, { "nativeSetPixels", "(I[IIIIIII)V", (void*)Bitmap_setPixels }, { "nativeCopyPixelsToBuffer", "(ILjava/nio/Buffer;)V", - (void*)Bitmap_copyPixelsToBuffer } + (void*)Bitmap_copyPixelsToBuffer }, + { "nativeCopyPixelsFromBuffer", "(ILjava/nio/Buffer;)V", + (void*)Bitmap_copyPixelsFromBuffer } }; #define kClassPathName "android/graphics/Bitmap" @@ -546,16 +560,7 @@ static JNINativeMethod gBitmapMethods[] = { int register_android_graphics_Bitmap(JNIEnv* env); int register_android_graphics_Bitmap(JNIEnv* env) { -#if 1 return android::AndroidRuntime::registerNativeMethods(env, kClassPathName, gBitmapMethods, SK_ARRAY_COUNT(gBitmapMethods)); -#else - short n = 0; - int limit = (char*)env - (char*)0; - for (int i = 0; i < limit; i++) { - n += i*i; - } - return n; -#endif } diff --git a/core/jni/android_server_BluetoothDeviceService.cpp b/core/jni/android_server_BluetoothDeviceService.cpp index 3ff6af1f367e..61a4a26aad0e 100644 --- a/core/jni/android_server_BluetoothDeviceService.cpp +++ b/core/jni/android_server_BluetoothDeviceService.cpp @@ -378,12 +378,12 @@ static jint getDiscoverableTimeoutNative(JNIEnv *env, jobject object) { LOGV(__FUNCTION__); native_data_t *nat = get_native_data(env, object); if (nat) { - DBusMessage *reply = + DBusMessage *reply = dbus_func_args(env, nat->conn, nat->adapter, DBUS_CLASS_NAME, "GetDiscoverableTimeout", DBUS_TYPE_INVALID); return reply ? dbus_returns_uint32(env, reply) : -1; - } + } #endif return -1; } @@ -394,7 +394,7 @@ static jboolean isConnectedNative(JNIEnv *env, jobject object, jstring address) native_data_t *nat = get_native_data(env, object); if (nat) { const char *c_address = env->GetStringUTFChars(address, NULL); - DBusMessage *reply = + DBusMessage *reply = dbus_func_args(env, nat->conn, nat->adapter, DBUS_CLASS_NAME, "IsConnected", DBUS_TYPE_STRING, &c_address, @@ -412,12 +412,12 @@ static void disconnectRemoteDeviceNative(JNIEnv *env, jobject object, jstring ad native_data_t *nat = get_native_data(env, object); if (nat) { const char *c_address = env->GetStringUTFChars(address, NULL); - // Set a timeout of 5 seconds. Specifying the default timeout is - // not long enough, as a remote-device disconnect results in - // signal RemoteDisconnectRequested being sent, followed by a + // Set a timeout of 5 seconds. Specifying the default timeout is + // not long enough, as a remote-device disconnect results in + // signal RemoteDisconnectRequested being sent, followed by a // delay of 2 seconds, after which the actual disconnect takes // place. - DBusMessage *reply = + DBusMessage *reply = dbus_func_args_timeout(env, nat->conn, 60000, nat->adapter, DBUS_CLASS_NAME, "DisconnectRemoteDevice", DBUS_TYPE_STRING, &c_address, @@ -448,7 +448,7 @@ static jboolean isDiscoverableNative(JNIEnv *env, jobject object) { LOGV(__FUNCTION__); native_data_t *nat = get_native_data(env, object); if (nat) { - DBusMessage *reply = + DBusMessage *reply = dbus_func_args(env, nat->conn, nat->adapter, DBUS_CLASS_NAME, "IsDiscoverable", DBUS_TYPE_INVALID); @@ -463,7 +463,7 @@ static jstring getModeNative(JNIEnv *env, jobject object) { LOGV(__FUNCTION__); native_data_t *nat = get_native_data(env, object); if (nat) { - DBusMessage *reply = + DBusMessage *reply = dbus_func_args(env, nat->conn, nat->adapter, DBUS_CLASS_NAME, "GetMode", DBUS_TYPE_INVALID); @@ -551,25 +551,6 @@ static void removeBondingNative(JNIEnv *env, jobject object, jstring address) { common_Bonding(env, object, -1, "RemoveBonding", address); } -static jboolean hasBondingNative(JNIEnv *env, jobject object, jstring address) { -#ifdef HAVE_BLUETOOTH - LOGV(__FUNCTION__); - native_data_t *nat = get_native_data(env, object); - if (nat) { - const char *c_address = env->GetStringUTFChars(address, NULL); - LOGV("... address = %s", c_address); - DBusMessage *reply = - dbus_func_args(env, nat->conn, nat->adapter, - DBUS_CLASS_NAME, "HasBonding", - DBUS_TYPE_STRING, &c_address, - DBUS_TYPE_INVALID); - env->ReleaseStringUTFChars(address, c_address); - return reply ? dbus_returns_boolean(env, reply) : JNI_FALSE; - } -#endif - return JNI_FALSE; -} - static jobjectArray listBondingsNative(JNIEnv *env, jobject object) { #ifdef HAVE_BLUETOOTH LOGV(__FUNCTION__); @@ -763,7 +744,7 @@ static jboolean clearRemoteAliasNative(JNIEnv *env, jobject obj, jstring address native_data_t *nat = get_native_data(env, obj); if (nat) { const char *c_address = env->GetStringUTFChars(address, NULL); - + LOGV("... address = %s", c_address); DBusMessage *reply = dbus_func_args(env, nat->conn, nat->adapter, @@ -998,6 +979,7 @@ static jboolean getRemoteServiceChannelNative(JNIEnv *env, jobject object, static jint enableNative(JNIEnv *env, jobject object) { #ifdef HAVE_BLUETOOTH + LOGV(__FUNCTION__); return bt_enable(); #endif return -1; @@ -1005,6 +987,7 @@ static jint enableNative(JNIEnv *env, jobject object) { static jint disableNative(JNIEnv *env, jobject object) { #ifdef HAVE_BLUETOOTH + LOGV(__FUNCTION__); return bt_disable(); #endif return -1; @@ -1012,6 +995,7 @@ static jint disableNative(JNIEnv *env, jobject object) { static jint isEnabledNative(JNIEnv *env, jobject object) { #ifdef HAVE_BLUETOOTH + LOGV(__FUNCTION__); return bt_is_enabled(); #endif return -1; @@ -1113,7 +1097,6 @@ static JNINativeMethod sMethods[] = { {"createBondingNative", "(Ljava/lang/String;I)Z", (void *)createBondingNative}, {"cancelBondingProcessNative", "(Ljava/lang/String;)Z", (void *)cancelBondingProcessNative}, {"listBondingsNative", "()[Ljava/lang/String;", (void *)listBondingsNative}, - {"hasBondingNative", "(Ljava/lang/String;)Z", (void *)hasBondingNative}, {"removeBondingNative", "(Ljava/lang/String;)Z", (void *)removeBondingNative}, {"getRemoteNameNative", "(Ljava/lang/String;)Ljava/lang/String;", (void *)getRemoteNameNative}, diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp index 1aef138ce463..3468265bd8bf 100644 --- a/core/jni/android_server_BluetoothEventLoop.cpp +++ b/core/jni/android_server_BluetoothEventLoop.cpp @@ -92,7 +92,7 @@ static void classInitNative(JNIEnv* env, jclass clazz) { method_onBondingCreated = env->GetMethodID(clazz, "onBondingCreated", "(Ljava/lang/String;)V"); method_onBondingRemoved = env->GetMethodID(clazz, "onBondingRemoved", "(Ljava/lang/String;)V"); - method_onCreateBondingResult = env->GetMethodID(clazz, "onCreateBondingResult", "(Ljava/lang/String;Z)V"); + method_onCreateBondingResult = env->GetMethodID(clazz, "onCreateBondingResult", "(Ljava/lang/String;I)V"); method_onPasskeyAgentRequest = env->GetMethodID(clazz, "onPasskeyAgentRequest", "(Ljava/lang/String;I)V"); method_onPasskeyAgentCancel = env->GetMethodID(clazz, "onPasskeyAgentCancel", "(Ljava/lang/String;)V"); @@ -609,6 +609,12 @@ static jboolean waitForAndDispatchEventNative(JNIEnv *env, jobject object, } #ifdef HAVE_BLUETOOTH +//TODO: Unify result codes in a header +#define BOND_RESULT_ERROR -1000 +#define BOND_RESULT_SUCCESS 0 +#define BOND_RESULT_AUTH_FAILED 1 +#define BOND_RESULT_AUTH_REJECTED 2 +#define BOND_RESULT_REMOTE_DEVICE_DOWN 3 void onCreateBondingResult(DBusMessage *msg, void *user) { LOGV(__FUNCTION__); @@ -619,11 +625,26 @@ void onCreateBondingResult(DBusMessage *msg, void *user) { LOGV("... address = %s", address); - jboolean result = JNI_TRUE; + jint result = BOND_RESULT_SUCCESS; if (dbus_set_error_from_message(&err, msg)) { - /* if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationFailed")) */ - LOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message); - result = JNI_FALSE; + if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationFailed")) { + // Pins did not match, or remote device did not respond to pin + // request in time + LOGV("... error = %s (%s)\n", err.name, err.message); + result = BOND_RESULT_AUTH_FAILED; + } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".Error.AuthenticationRejected")) { + // We rejected pairing, or the remote side rejected pairing. This + // happens if either side presses 'cancel' at the pairing dialog. + LOGV("... error = %s (%s)\n", err.name, err.message); + result = BOND_RESULT_AUTH_REJECTED; + } else if (!strcmp(err.name, BLUEZ_DBUS_BASE_IFC ".ConnectionAttemptFailed")) { + // Other device is not responding at all + LOGV("... error = %s (%s)\n", err.name, err.message); + result = BOND_RESULT_REMOTE_DEVICE_DOWN; + } else { + LOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message); + result = BOND_RESULT_ERROR; + } dbus_error_free(&err); } diff --git a/core/res/res/anim/status_bar_enter.xml b/core/res/res/anim/status_bar_enter.xml new file mode 100644 index 000000000000..2df1af4ccbcf --- /dev/null +++ b/core/res/res/anim/status_bar_enter.xml @@ -0,0 +1,24 @@ + + + + + + + diff --git a/core/res/res/anim/status_bar_exit.xml b/core/res/res/anim/status_bar_exit.xml new file mode 100644 index 000000000000..c72d014421c5 --- /dev/null +++ b/core/res/res/anim/status_bar_exit.xml @@ -0,0 +1,24 @@ + + + + + + + diff --git a/core/res/res/values-cs/arrays.xml b/core/res/res/values-cs/arrays.xml deleted file mode 100644 index f9c904be4c64..000000000000 --- a/core/res/res/values-cs/arrays.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 61a2c29af72d..76232de14e8c 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -1,4 +1,18 @@ + "B" diff --git a/core/res/res/values-de/arrays.xml b/core/res/res/values-de/arrays.xml deleted file mode 100644 index f9c904be4c64..000000000000 --- a/core/res/res/values-de/arrays.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 44671e60062a..a8115a8b5b76 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -1,4 +1,18 @@ + "B" diff --git a/core/res/res/values-es/arrays.xml b/core/res/res/values-es/arrays.xml deleted file mode 100644 index f9c904be4c64..000000000000 --- a/core/res/res/values-es/arrays.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 07a92fa3a367..2ceea2c4ffc1 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -1,4 +1,18 @@ + "B" diff --git a/core/res/res/values-fr/arrays.xml b/core/res/res/values-fr/arrays.xml deleted file mode 100644 index f9c904be4c64..000000000000 --- a/core/res/res/values-fr/arrays.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index 0f58ba136961..ef826cb07c9c 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -1,4 +1,18 @@ + "O" diff --git a/core/res/res/values-it/arrays.xml b/core/res/res/values-it/arrays.xml deleted file mode 100644 index f9c904be4c64..000000000000 --- a/core/res/res/values-it/arrays.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 8b96f89de6bb..caf63c7ba3c7 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -1,4 +1,18 @@ + "B" diff --git a/core/res/res/values-ja/arrays.xml b/core/res/res/values-ja/arrays.xml deleted file mode 100644 index f9c904be4c64..000000000000 --- a/core/res/res/values-ja/arrays.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 07358372a687..055a8b14688d 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -1,4 +1,18 @@ + "B" diff --git a/core/res/res/values-mcc204-cs/strings.xml b/core/res/res/values-mcc204-cs/strings.xml index c846c60ac6ff..7d962307a3de 100644 --- a/core/res/res/values-mcc204-cs/strings.xml +++ b/core/res/res/values-mcc204-cs/strings.xml @@ -1,4 +1,18 @@ + "nl_nl" diff --git a/core/res/res/values-mcc204-de/strings.xml b/core/res/res/values-mcc204-de/strings.xml index c846c60ac6ff..7d962307a3de 100644 --- a/core/res/res/values-mcc204-de/strings.xml +++ b/core/res/res/values-mcc204-de/strings.xml @@ -1,4 +1,18 @@ + "nl_nl" diff --git a/core/res/res/values-mcc204-es/strings.xml b/core/res/res/values-mcc204-es/strings.xml index c846c60ac6ff..7d962307a3de 100644 --- a/core/res/res/values-mcc204-es/strings.xml +++ b/core/res/res/values-mcc204-es/strings.xml @@ -1,4 +1,18 @@ + "nl_nl" diff --git a/core/res/res/values-mcc204-fr/strings.xml b/core/res/res/values-mcc204-fr/strings.xml index c846c60ac6ff..7d962307a3de 100644 --- a/core/res/res/values-mcc204-fr/strings.xml +++ b/core/res/res/values-mcc204-fr/strings.xml @@ -1,4 +1,18 @@ + "nl_nl" diff --git a/core/res/res/values-mcc204-it/strings.xml b/core/res/res/values-mcc204-it/strings.xml index c846c60ac6ff..7d962307a3de 100644 --- a/core/res/res/values-mcc204-it/strings.xml +++ b/core/res/res/values-mcc204-it/strings.xml @@ -1,4 +1,18 @@ + "nl_nl" diff --git a/core/res/res/values-mcc204-ja/strings.xml b/core/res/res/values-mcc204-ja/strings.xml index c846c60ac6ff..7d962307a3de 100644 --- a/core/res/res/values-mcc204-ja/strings.xml +++ b/core/res/res/values-mcc204-ja/strings.xml @@ -1,4 +1,18 @@ + "nl_nl" diff --git a/core/res/res/values-mcc204-nl/strings.xml b/core/res/res/values-mcc204-nl/strings.xml index c846c60ac6ff..7d962307a3de 100644 --- a/core/res/res/values-mcc204-nl/strings.xml +++ b/core/res/res/values-mcc204-nl/strings.xml @@ -1,4 +1,18 @@ + "nl_nl" diff --git a/core/res/res/values-mcc204-pl/strings.xml b/core/res/res/values-mcc204-pl/strings.xml index c846c60ac6ff..7d962307a3de 100644 --- a/core/res/res/values-mcc204-pl/strings.xml +++ b/core/res/res/values-mcc204-pl/strings.xml @@ -1,4 +1,18 @@ + "nl_nl" diff --git a/core/res/res/values-mcc204-ru/strings.xml b/core/res/res/values-mcc204-ru/strings.xml index c846c60ac6ff..7d962307a3de 100644 --- a/core/res/res/values-mcc204-ru/strings.xml +++ b/core/res/res/values-mcc204-ru/strings.xml @@ -1,4 +1,18 @@ + "nl_nl" diff --git a/core/res/res/values-mcc204-zh-rCN/strings.xml b/core/res/res/values-mcc204-zh-rCN/strings.xml index c846c60ac6ff..7d962307a3de 100644 --- a/core/res/res/values-mcc204-zh-rCN/strings.xml +++ b/core/res/res/values-mcc204-zh-rCN/strings.xml @@ -1,4 +1,18 @@ + "nl_nl" diff --git a/core/res/res/values-mcc204-zh-rTW/strings.xml b/core/res/res/values-mcc204-zh-rTW/strings.xml index c846c60ac6ff..7d962307a3de 100644 --- a/core/res/res/values-mcc204-zh-rTW/strings.xml +++ b/core/res/res/values-mcc204-zh-rTW/strings.xml @@ -1,4 +1,18 @@ + "nl_nl" diff --git a/core/res/res/values-mcc230-cs/strings.xml b/core/res/res/values-mcc230-cs/strings.xml index fd82191feaa0..d3ecdbba28ed 100644 --- a/core/res/res/values-mcc230-cs/strings.xml +++ b/core/res/res/values-mcc230-cs/strings.xml @@ -1,4 +1,18 @@ + "cs_cz" diff --git a/core/res/res/values-mcc230-de/strings.xml b/core/res/res/values-mcc230-de/strings.xml index fd82191feaa0..d3ecdbba28ed 100644 --- a/core/res/res/values-mcc230-de/strings.xml +++ b/core/res/res/values-mcc230-de/strings.xml @@ -1,4 +1,18 @@ + "cs_cz" diff --git a/core/res/res/values-mcc230-es/strings.xml b/core/res/res/values-mcc230-es/strings.xml index fd82191feaa0..d3ecdbba28ed 100644 --- a/core/res/res/values-mcc230-es/strings.xml +++ b/core/res/res/values-mcc230-es/strings.xml @@ -1,4 +1,18 @@ + "cs_cz" diff --git a/core/res/res/values-mcc230-fr/strings.xml b/core/res/res/values-mcc230-fr/strings.xml index fd82191feaa0..d3ecdbba28ed 100644 --- a/core/res/res/values-mcc230-fr/strings.xml +++ b/core/res/res/values-mcc230-fr/strings.xml @@ -1,4 +1,18 @@ + "cs_cz" diff --git a/core/res/res/values-mcc230-it/strings.xml b/core/res/res/values-mcc230-it/strings.xml index fd82191feaa0..d3ecdbba28ed 100644 --- a/core/res/res/values-mcc230-it/strings.xml +++ b/core/res/res/values-mcc230-it/strings.xml @@ -1,4 +1,18 @@ + "cs_cz" diff --git a/core/res/res/values-mcc230-ja/strings.xml b/core/res/res/values-mcc230-ja/strings.xml index fd82191feaa0..d3ecdbba28ed 100644 --- a/core/res/res/values-mcc230-ja/strings.xml +++ b/core/res/res/values-mcc230-ja/strings.xml @@ -1,4 +1,18 @@ + "cs_cz" diff --git a/core/res/res/values-mcc230-nl/strings.xml b/core/res/res/values-mcc230-nl/strings.xml index fd82191feaa0..d3ecdbba28ed 100644 --- a/core/res/res/values-mcc230-nl/strings.xml +++ b/core/res/res/values-mcc230-nl/strings.xml @@ -1,4 +1,18 @@ + "cs_cz" diff --git a/core/res/res/values-mcc230-pl/strings.xml b/core/res/res/values-mcc230-pl/strings.xml index fd82191feaa0..d3ecdbba28ed 100644 --- a/core/res/res/values-mcc230-pl/strings.xml +++ b/core/res/res/values-mcc230-pl/strings.xml @@ -1,4 +1,18 @@ + "cs_cz" diff --git a/core/res/res/values-mcc230-ru/strings.xml b/core/res/res/values-mcc230-ru/strings.xml index fd82191feaa0..d3ecdbba28ed 100644 --- a/core/res/res/values-mcc230-ru/strings.xml +++ b/core/res/res/values-mcc230-ru/strings.xml @@ -1,4 +1,18 @@ + "cs_cz" diff --git a/core/res/res/values-mcc230-zh-rCN/strings.xml b/core/res/res/values-mcc230-zh-rCN/strings.xml index fd82191feaa0..d3ecdbba28ed 100644 --- a/core/res/res/values-mcc230-zh-rCN/strings.xml +++ b/core/res/res/values-mcc230-zh-rCN/strings.xml @@ -1,4 +1,18 @@ + "cs_cz" diff --git a/core/res/res/values-mcc230-zh-rTW/strings.xml b/core/res/res/values-mcc230-zh-rTW/strings.xml index fd82191feaa0..d3ecdbba28ed 100644 --- a/core/res/res/values-mcc230-zh-rTW/strings.xml +++ b/core/res/res/values-mcc230-zh-rTW/strings.xml @@ -1,4 +1,18 @@ + "cs_cz" diff --git a/core/res/res/values-mcc232-cs/strings.xml b/core/res/res/values-mcc232-cs/strings.xml index 1376f0ccf6b5..4773838f9c47 100644 --- a/core/res/res/values-mcc232-cs/strings.xml +++ b/core/res/res/values-mcc232-cs/strings.xml @@ -1,4 +1,18 @@ + "de_at" diff --git a/core/res/res/values-mcc232-de/strings.xml b/core/res/res/values-mcc232-de/strings.xml index 1376f0ccf6b5..4773838f9c47 100644 --- a/core/res/res/values-mcc232-de/strings.xml +++ b/core/res/res/values-mcc232-de/strings.xml @@ -1,4 +1,18 @@ + "de_at" diff --git a/core/res/res/values-mcc232-es/strings.xml b/core/res/res/values-mcc232-es/strings.xml index 1376f0ccf6b5..4773838f9c47 100644 --- a/core/res/res/values-mcc232-es/strings.xml +++ b/core/res/res/values-mcc232-es/strings.xml @@ -1,4 +1,18 @@ + "de_at" diff --git a/core/res/res/values-mcc232-fr/strings.xml b/core/res/res/values-mcc232-fr/strings.xml index 1376f0ccf6b5..4773838f9c47 100644 --- a/core/res/res/values-mcc232-fr/strings.xml +++ b/core/res/res/values-mcc232-fr/strings.xml @@ -1,4 +1,18 @@ + "de_at" diff --git a/core/res/res/values-mcc232-it/strings.xml b/core/res/res/values-mcc232-it/strings.xml index 1376f0ccf6b5..4773838f9c47 100644 --- a/core/res/res/values-mcc232-it/strings.xml +++ b/core/res/res/values-mcc232-it/strings.xml @@ -1,4 +1,18 @@ + "de_at" diff --git a/core/res/res/values-mcc232-ja/strings.xml b/core/res/res/values-mcc232-ja/strings.xml index 1376f0ccf6b5..4773838f9c47 100644 --- a/core/res/res/values-mcc232-ja/strings.xml +++ b/core/res/res/values-mcc232-ja/strings.xml @@ -1,4 +1,18 @@ + "de_at" diff --git a/core/res/res/values-mcc232-nl/strings.xml b/core/res/res/values-mcc232-nl/strings.xml index 1376f0ccf6b5..4773838f9c47 100644 --- a/core/res/res/values-mcc232-nl/strings.xml +++ b/core/res/res/values-mcc232-nl/strings.xml @@ -1,4 +1,18 @@ + "de_at" diff --git a/core/res/res/values-mcc232-pl/strings.xml b/core/res/res/values-mcc232-pl/strings.xml index 1376f0ccf6b5..4773838f9c47 100644 --- a/core/res/res/values-mcc232-pl/strings.xml +++ b/core/res/res/values-mcc232-pl/strings.xml @@ -1,4 +1,18 @@ + "de_at" diff --git a/core/res/res/values-mcc232-ru/strings.xml b/core/res/res/values-mcc232-ru/strings.xml index 1376f0ccf6b5..4773838f9c47 100644 --- a/core/res/res/values-mcc232-ru/strings.xml +++ b/core/res/res/values-mcc232-ru/strings.xml @@ -1,4 +1,18 @@ + "de_at" diff --git a/core/res/res/values-mcc232-zh-rCN/strings.xml b/core/res/res/values-mcc232-zh-rCN/strings.xml index 1376f0ccf6b5..4773838f9c47 100644 --- a/core/res/res/values-mcc232-zh-rCN/strings.xml +++ b/core/res/res/values-mcc232-zh-rCN/strings.xml @@ -1,4 +1,18 @@ + "de_at" diff --git a/core/res/res/values-mcc232-zh-rTW/strings.xml b/core/res/res/values-mcc232-zh-rTW/strings.xml index 1376f0ccf6b5..4773838f9c47 100644 --- a/core/res/res/values-mcc232-zh-rTW/strings.xml +++ b/core/res/res/values-mcc232-zh-rTW/strings.xml @@ -1,4 +1,18 @@ + "de_at" diff --git a/core/res/res/values-mcc234-cs/strings.xml b/core/res/res/values-mcc234-cs/strings.xml index 44a78410acf6..2538b7329239 100644 --- a/core/res/res/values-mcc234-cs/strings.xml +++ b/core/res/res/values-mcc234-cs/strings.xml @@ -1,4 +1,18 @@ + "en_gb" diff --git a/core/res/res/values-mcc234-de/strings.xml b/core/res/res/values-mcc234-de/strings.xml index 44a78410acf6..2538b7329239 100644 --- a/core/res/res/values-mcc234-de/strings.xml +++ b/core/res/res/values-mcc234-de/strings.xml @@ -1,4 +1,18 @@ + "en_gb" diff --git a/core/res/res/values-mcc234-es/strings.xml b/core/res/res/values-mcc234-es/strings.xml index 44a78410acf6..2538b7329239 100644 --- a/core/res/res/values-mcc234-es/strings.xml +++ b/core/res/res/values-mcc234-es/strings.xml @@ -1,4 +1,18 @@ + "en_gb" diff --git a/core/res/res/values-mcc234-fr/strings.xml b/core/res/res/values-mcc234-fr/strings.xml index 44a78410acf6..2538b7329239 100644 --- a/core/res/res/values-mcc234-fr/strings.xml +++ b/core/res/res/values-mcc234-fr/strings.xml @@ -1,4 +1,18 @@ + "en_gb" diff --git a/core/res/res/values-mcc234-it/strings.xml b/core/res/res/values-mcc234-it/strings.xml index 44a78410acf6..2538b7329239 100644 --- a/core/res/res/values-mcc234-it/strings.xml +++ b/core/res/res/values-mcc234-it/strings.xml @@ -1,4 +1,18 @@ + "en_gb" diff --git a/core/res/res/values-mcc234-ja/strings.xml b/core/res/res/values-mcc234-ja/strings.xml index 44a78410acf6..2538b7329239 100644 --- a/core/res/res/values-mcc234-ja/strings.xml +++ b/core/res/res/values-mcc234-ja/strings.xml @@ -1,4 +1,18 @@ + "en_gb" diff --git a/core/res/res/values-mcc234-nl/strings.xml b/core/res/res/values-mcc234-nl/strings.xml index 44a78410acf6..2538b7329239 100644 --- a/core/res/res/values-mcc234-nl/strings.xml +++ b/core/res/res/values-mcc234-nl/strings.xml @@ -1,4 +1,18 @@ + "en_gb" diff --git a/core/res/res/values-mcc234-pl/strings.xml b/core/res/res/values-mcc234-pl/strings.xml index 44a78410acf6..2538b7329239 100644 --- a/core/res/res/values-mcc234-pl/strings.xml +++ b/core/res/res/values-mcc234-pl/strings.xml @@ -1,4 +1,18 @@ + "en_gb" diff --git a/core/res/res/values-mcc234-ru/strings.xml b/core/res/res/values-mcc234-ru/strings.xml index 44a78410acf6..2538b7329239 100644 --- a/core/res/res/values-mcc234-ru/strings.xml +++ b/core/res/res/values-mcc234-ru/strings.xml @@ -1,4 +1,18 @@ + "en_gb" diff --git a/core/res/res/values-mcc234-zh-rCN/strings.xml b/core/res/res/values-mcc234-zh-rCN/strings.xml index 44a78410acf6..2538b7329239 100644 --- a/core/res/res/values-mcc234-zh-rCN/strings.xml +++ b/core/res/res/values-mcc234-zh-rCN/strings.xml @@ -1,4 +1,18 @@ + "en_gb" diff --git a/core/res/res/values-mcc234-zh-rTW/strings.xml b/core/res/res/values-mcc234-zh-rTW/strings.xml index 44a78410acf6..2538b7329239 100644 --- a/core/res/res/values-mcc234-zh-rTW/strings.xml +++ b/core/res/res/values-mcc234-zh-rTW/strings.xml @@ -1,4 +1,18 @@ + "en_gb" diff --git a/core/res/res/values-mcc260-cs/strings.xml b/core/res/res/values-mcc260-cs/strings.xml index 2e40a50278bd..1161f9a6356f 100644 --- a/core/res/res/values-mcc260-cs/strings.xml +++ b/core/res/res/values-mcc260-cs/strings.xml @@ -1,4 +1,18 @@ + "pl_pl" diff --git a/core/res/res/values-mcc260-de/strings.xml b/core/res/res/values-mcc260-de/strings.xml index 2e40a50278bd..1161f9a6356f 100644 --- a/core/res/res/values-mcc260-de/strings.xml +++ b/core/res/res/values-mcc260-de/strings.xml @@ -1,4 +1,18 @@ + "pl_pl" diff --git a/core/res/res/values-mcc260-es/strings.xml b/core/res/res/values-mcc260-es/strings.xml index 2e40a50278bd..1161f9a6356f 100644 --- a/core/res/res/values-mcc260-es/strings.xml +++ b/core/res/res/values-mcc260-es/strings.xml @@ -1,4 +1,18 @@ + "pl_pl" diff --git a/core/res/res/values-mcc260-fr/strings.xml b/core/res/res/values-mcc260-fr/strings.xml index 2e40a50278bd..1161f9a6356f 100644 --- a/core/res/res/values-mcc260-fr/strings.xml +++ b/core/res/res/values-mcc260-fr/strings.xml @@ -1,4 +1,18 @@ + "pl_pl" diff --git a/core/res/res/values-mcc260-it/strings.xml b/core/res/res/values-mcc260-it/strings.xml index 2e40a50278bd..1161f9a6356f 100644 --- a/core/res/res/values-mcc260-it/strings.xml +++ b/core/res/res/values-mcc260-it/strings.xml @@ -1,4 +1,18 @@ + "pl_pl" diff --git a/core/res/res/values-mcc260-ja/strings.xml b/core/res/res/values-mcc260-ja/strings.xml index 2e40a50278bd..1161f9a6356f 100644 --- a/core/res/res/values-mcc260-ja/strings.xml +++ b/core/res/res/values-mcc260-ja/strings.xml @@ -1,4 +1,18 @@ + "pl_pl" diff --git a/core/res/res/values-mcc260-nl/strings.xml b/core/res/res/values-mcc260-nl/strings.xml index 2e40a50278bd..1161f9a6356f 100644 --- a/core/res/res/values-mcc260-nl/strings.xml +++ b/core/res/res/values-mcc260-nl/strings.xml @@ -1,4 +1,18 @@ + "pl_pl" diff --git a/core/res/res/values-mcc260-pl/strings.xml b/core/res/res/values-mcc260-pl/strings.xml index 2e40a50278bd..1161f9a6356f 100644 --- a/core/res/res/values-mcc260-pl/strings.xml +++ b/core/res/res/values-mcc260-pl/strings.xml @@ -1,4 +1,18 @@ + "pl_pl" diff --git a/core/res/res/values-mcc260-ru/strings.xml b/core/res/res/values-mcc260-ru/strings.xml index 2e40a50278bd..1161f9a6356f 100644 --- a/core/res/res/values-mcc260-ru/strings.xml +++ b/core/res/res/values-mcc260-ru/strings.xml @@ -1,4 +1,18 @@ + "pl_pl" diff --git a/core/res/res/values-mcc260-zh-rCN/strings.xml b/core/res/res/values-mcc260-zh-rCN/strings.xml index 2e40a50278bd..1161f9a6356f 100644 --- a/core/res/res/values-mcc260-zh-rCN/strings.xml +++ b/core/res/res/values-mcc260-zh-rCN/strings.xml @@ -1,4 +1,18 @@ + "pl_pl" diff --git a/core/res/res/values-mcc260-zh-rTW/strings.xml b/core/res/res/values-mcc260-zh-rTW/strings.xml index 2e40a50278bd..1161f9a6356f 100644 --- a/core/res/res/values-mcc260-zh-rTW/strings.xml +++ b/core/res/res/values-mcc260-zh-rTW/strings.xml @@ -1,4 +1,18 @@ + "pl_pl" diff --git a/core/res/res/values-mcc262-cs/strings.xml b/core/res/res/values-mcc262-cs/strings.xml index c4b1b7230af0..9505cf4b4226 100644 --- a/core/res/res/values-mcc262-cs/strings.xml +++ b/core/res/res/values-mcc262-cs/strings.xml @@ -1,4 +1,18 @@ + "de_de" diff --git a/core/res/res/values-mcc262-de/strings.xml b/core/res/res/values-mcc262-de/strings.xml index c4b1b7230af0..9505cf4b4226 100644 --- a/core/res/res/values-mcc262-de/strings.xml +++ b/core/res/res/values-mcc262-de/strings.xml @@ -1,4 +1,18 @@ + "de_de" diff --git a/core/res/res/values-mcc262-es/strings.xml b/core/res/res/values-mcc262-es/strings.xml index c4b1b7230af0..9505cf4b4226 100644 --- a/core/res/res/values-mcc262-es/strings.xml +++ b/core/res/res/values-mcc262-es/strings.xml @@ -1,4 +1,18 @@ + "de_de" diff --git a/core/res/res/values-mcc262-fr/strings.xml b/core/res/res/values-mcc262-fr/strings.xml index c4b1b7230af0..9505cf4b4226 100644 --- a/core/res/res/values-mcc262-fr/strings.xml +++ b/core/res/res/values-mcc262-fr/strings.xml @@ -1,4 +1,18 @@ + "de_de" diff --git a/core/res/res/values-mcc262-it/strings.xml b/core/res/res/values-mcc262-it/strings.xml index c4b1b7230af0..9505cf4b4226 100644 --- a/core/res/res/values-mcc262-it/strings.xml +++ b/core/res/res/values-mcc262-it/strings.xml @@ -1,4 +1,18 @@ + "de_de" diff --git a/core/res/res/values-mcc262-ja/strings.xml b/core/res/res/values-mcc262-ja/strings.xml index c4b1b7230af0..9505cf4b4226 100644 --- a/core/res/res/values-mcc262-ja/strings.xml +++ b/core/res/res/values-mcc262-ja/strings.xml @@ -1,4 +1,18 @@ + "de_de" diff --git a/core/res/res/values-mcc262-nl/strings.xml b/core/res/res/values-mcc262-nl/strings.xml index c4b1b7230af0..9505cf4b4226 100644 --- a/core/res/res/values-mcc262-nl/strings.xml +++ b/core/res/res/values-mcc262-nl/strings.xml @@ -1,4 +1,18 @@ + "de_de" diff --git a/core/res/res/values-mcc262-pl/strings.xml b/core/res/res/values-mcc262-pl/strings.xml index c4b1b7230af0..9505cf4b4226 100644 --- a/core/res/res/values-mcc262-pl/strings.xml +++ b/core/res/res/values-mcc262-pl/strings.xml @@ -1,4 +1,18 @@ + "de_de" diff --git a/core/res/res/values-mcc262-ru/strings.xml b/core/res/res/values-mcc262-ru/strings.xml index c4b1b7230af0..9505cf4b4226 100644 --- a/core/res/res/values-mcc262-ru/strings.xml +++ b/core/res/res/values-mcc262-ru/strings.xml @@ -1,4 +1,18 @@ + "de_de" diff --git a/core/res/res/values-mcc262-zh-rCN/strings.xml b/core/res/res/values-mcc262-zh-rCN/strings.xml index c4b1b7230af0..9505cf4b4226 100644 --- a/core/res/res/values-mcc262-zh-rCN/strings.xml +++ b/core/res/res/values-mcc262-zh-rCN/strings.xml @@ -1,4 +1,18 @@ + "de_de" diff --git a/core/res/res/values-mcc262-zh-rTW/strings.xml b/core/res/res/values-mcc262-zh-rTW/strings.xml index c4b1b7230af0..9505cf4b4226 100644 --- a/core/res/res/values-mcc262-zh-rTW/strings.xml +++ b/core/res/res/values-mcc262-zh-rTW/strings.xml @@ -1,4 +1,18 @@ + "de_de" diff --git a/core/res/res/values-nl/arrays.xml b/core/res/res/values-nl/arrays.xml deleted file mode 100644 index f9c904be4c64..000000000000 --- a/core/res/res/values-nl/arrays.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 9426f355eb9d..5c54226c4aa8 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -1,4 +1,18 @@ + "B" diff --git a/core/res/res/values-pl/arrays.xml b/core/res/res/values-pl/arrays.xml deleted file mode 100644 index f9c904be4c64..000000000000 --- a/core/res/res/values-pl/arrays.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index d76922f4fe01..c3e3a46b0c12 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -1,4 +1,18 @@ + "B" diff --git a/core/res/res/values-ru/arrays.xml b/core/res/res/values-ru/arrays.xml deleted file mode 100644 index f9c904be4c64..000000000000 --- a/core/res/res/values-ru/arrays.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index a00973fd4407..33efbf68eb5c 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -1,4 +1,18 @@ + "б" diff --git a/core/res/res/values-zh-rCN/arrays.xml b/core/res/res/values-zh-rCN/arrays.xml deleted file mode 100644 index f9c904be4c64..000000000000 --- a/core/res/res/values-zh-rCN/arrays.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 87bd4e4de496..cb1339078f82 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -1,4 +1,18 @@ + "B" diff --git a/core/res/res/values-zh-rTW/arrays.xml b/core/res/res/values-zh-rTW/arrays.xml deleted file mode 100644 index f9c904be4c64..000000000000 --- a/core/res/res/values-zh-rTW/arrays.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index fbe8c552fdfc..758bf82fa03d 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -1,4 +1,18 @@ + "位元組" diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 2562a8a9850d..5477538a6019 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2934,5 +2934,22 @@ requested keyboard mode, the key will be skipped --> + + + + + + + + + + + + + + diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index f25d8293a3ca..c757c562ed42 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -986,6 +986,8 @@ + + + + diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index 72367f898ddf..3f07e70b907a 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -31,7 +31,7 @@ @android:color/bright_foreground_dark_inverse @android:color/background_dark 0.5 - 0.5 + 0.6 @android:style/TextAppearance diff --git a/data/localization/import-from-xtb b/data/localization/import-from-xtb index 15b060a47774..f0a0b7d8180a 100755 --- a/data/localization/import-from-xtb +++ b/data/localization/import-from-xtb @@ -44,7 +44,12 @@ extract() p4 edit $out p4 add $out mkdir -p `dirname $out` - ../../../../out/host/linux-x86/bin/transconsole -m $1 $2 -p $module -i $module-$locale.xtb $i > $out + if ../../../../out/host/linux-x86/bin/transconsole -m $1 $2 -p $module -i $module-$locale.xtb $i > $out + then : + else + p4 revert $out + p4 delete $out + fi done } diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index 501c99f394cb..dc16c39f4d7e 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -184,6 +184,37 @@ public final class Bitmap implements Parcelable { } /** + * Copy the pixels from the buffer, beginning at the current position, + * overwriting the bitmap's pixels. The data in the buffer is not changed + * in any way (unlike setPixels(), which converts from unpremultipled 32bit + * to whatever the bitmap's native format is. + */ + public void copyPixelsFromBuffer(Buffer src) { + checkRecycled("copyPixelsFromBuffer called on recycled bitmap"); + + int elements = src.remaining(); + int shift; + if (src instanceof ByteBuffer) { + shift = 0; + } else if (src instanceof ShortBuffer) { + shift = 1; + } else if (src instanceof IntBuffer) { + shift = 2; + } else { + throw new RuntimeException("unsupported Buffer subclass"); + } + + long bufferBytes = (long)elements << shift; + long bitmapBytes = (long)getRowBytes() * getHeight(); + + if (bufferBytes < bitmapBytes) { + throw new RuntimeException("Buffer not large enough for pixels"); + } + + nativeCopyPixelsFromBuffer(mNativeBitmap, src); + } + + /** * Tries to make a new bitmap based on the dimensions of this bitmap, * setting the new bitmap's config to the one specified, and then copying * this bitmap's pixels into the new bitmap. If the conversion is not @@ -794,6 +825,7 @@ public final class Bitmap implements Parcelable { int y, int width, int height); private static native void nativeCopyPixelsToBuffer(int nativeBitmap, Buffer dst); + private static native void nativeCopyPixelsFromBuffer(int nb, Buffer src); private static native Bitmap nativeCreateFromParcel(Parcel p); // returns true on success diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java index d1e609088c5c..2c3f543a90e9 100644 --- a/graphics/java/android/graphics/BitmapFactory.java +++ b/graphics/java/android/graphics/BitmapFactory.java @@ -304,11 +304,6 @@ public class BitmapFactory { bm = nativeDecodeStream(is, tempStorage, outPadding, opts); } - try { - is.reset(); - } catch (IOException ex) { - // ignore - } return bm; } diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index fa5ed0a4827b..59dfbd46c758 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -340,10 +340,10 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { final int N = mLayerState.mNum; for (int i=0; ibufferSize() / output->channelCount() / sizeof(int16_t); } +#ifdef WITH_A2DP +bool AudioFlinger::streamDisablesA2dp(int streamType) +{ + return (streamType == AudioTrack::SYSTEM || + streamType == AudioTrack::RING || + streamType == AudioTrack::ALARM || + streamType == AudioTrack::NOTIFICATION); +} + +void AudioFlinger::setA2dpEnabled(bool enable) +{ + if (enable) { + LOGD("set output to A2DP\n"); + setOutput(mA2dpOutput); + } else { + LOGD("set output to hardware audio\n"); + setOutput(mHardwareOutput); + } +} +#endif // WITH_A2DP + status_t AudioFlinger::dumpClients(int fd, const Vector& args) { const size_t SIZE = 256; @@ -457,7 +478,7 @@ bool AudioFlinger::threadLoop() if (UNLIKELY(count)) { for (size_t i=0 ; i& track = tracksToRemove[i]; - mActiveTracks.remove(track); + removeActiveTrack(track); if (track->isTerminated()) { mTracks.remove(track); mAudioMixer->deleteTrackName(track->mName); @@ -653,13 +674,16 @@ status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask) LOGD("setRouting %d %d %d\n", mode, routes, mask); if (mode == AudioSystem::MODE_NORMAL && (mask & AudioSystem::ROUTE_BLUETOOTH_A2DP)) { + AutoMutex lock(&mLock); + + bool enableA2dp = false; if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) { - LOGD("set output to A2DP\n"); - setOutput(mA2dpOutput); - } else { - LOGD("set output to hardware audio\n"); - setOutput(mHardwareOutput); + if (mA2dpDisableCount > 0) + mA2dpSuppressed = true; + else + enableA2dp = true; } + setA2dpEnabled(enableA2dp); LOGD("setOutput done\n"); } #endif @@ -875,7 +899,7 @@ status_t AudioFlinger::addTrack(const sp& track) // effectively get the latency it requested. track->mFillingUpStatus = Track::FS_FILLING; track->mResetDone = false; - mActiveTracks.add(track); + addActiveTrack(track); return NO_ERROR; } return ALREADY_EXISTS; @@ -897,7 +921,7 @@ void AudioFlinger::remove_track_l(wp track, int name) t->reset(); } audioMixer()->deleteTrackName(name); - mActiveTracks.remove(track); + removeActiveTrack(track); mWaitWorkCV.broadcast(); } @@ -918,6 +942,44 @@ void AudioFlinger::destroyTrack(const sp& track) } } +void AudioFlinger::addActiveTrack(const wp& t) +{ + mActiveTracks.add(t); + +#ifdef WITH_A2DP + // disable A2DP for certain stream types + sp track = t.promote(); + if (streamDisablesA2dp(track->type())) { + if (mA2dpDisableCount++ == 0 && isA2dpEnabled()) { + setA2dpEnabled(false); + mA2dpSuppressed = true; + LOGD("mA2dpSuppressed = true\n"); + } + LOGD("mA2dpDisableCount incremented to %d\n", mA2dpDisableCount); + } +#endif +} + +void AudioFlinger::removeActiveTrack(const wp& t) +{ + mActiveTracks.remove(t); +#ifdef WITH_A2DP + // disable A2DP for certain stream types + sp track = t.promote(); + if (streamDisablesA2dp(track->type())) { + if (mA2dpDisableCount > 0) { + mA2dpDisableCount--; + if (mA2dpDisableCount == 0 && mA2dpSuppressed) { + setA2dpEnabled(true); + mA2dpSuppressed = false; + } + LOGD("mA2dpDisableCount decremented to %d\n", mA2dpDisableCount); + } else + LOGE("mA2dpDisableCount is already zero"); + } +#endif +} + // ---------------------------------------------------------------------------- AudioFlinger::Client::Client(const sp& audioFlinger, pid_t pid) diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h index 90bc72d07b5d..9ab362a39ddd 100644 --- a/libs/audioflinger/AudioFlinger.h +++ b/libs/audioflinger/AudioFlinger.h @@ -153,6 +153,15 @@ private: void doSetOutput(AudioStreamOut* output); size_t getOutputFrameCount(AudioStreamOut* output); +#ifdef WITH_A2DP + static bool streamDisablesA2dp(int streamType); + inline bool isA2dpEnabled() const { + return (mRequestedOutput == mA2dpOutput || + (mOutput && mOutput == mA2dpOutput)); + } + void setA2dpEnabled(bool enable); +#endif + // Internal dump utilites. status_t dumpPermissionDenial(int fd, const Vector& args); status_t dumpClients(int fd, const Vector& args); @@ -371,6 +380,8 @@ private: void removeTrack(wp track, int name); void remove_track_l(wp track, int name); void destroyTrack(const sp& track); + void addActiveTrack(const wp& track); + void removeActiveTrack(const wp& track); AudioMixer* audioMixer() { return mAudioMixer; @@ -481,6 +492,8 @@ private: int mNumDelayedWrites; bool mStandby; bool mInWrite; + int mA2dpDisableCount; + bool mA2dpSuppressed; }; // ---------------------------------------------------------------------------- diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java index 3d4d4a275b07..c6f13c943127 100644 --- a/location/java/com/android/internal/location/GpsLocationProvider.java +++ b/location/java/com/android/internal/location/GpsLocationProvider.java @@ -155,6 +155,7 @@ public class GpsLocationProvider extends LocationProviderImpl { private ArrayList mListeners = new ArrayList(); private GpsEventThread mEventThread; private GpsNetworkThread mNetworkThread; + private Object mNetworkThreadLock = new Object(); // how often to request NTP time, in milliseconds // current setting 4 hours @@ -301,8 +302,9 @@ public class GpsLocationProvider extends LocationProviderImpl { * when the provider is enabled. */ @Override - public void enable() { + public synchronized void enable() { if (Config.LOGD) Log.d(TAG, "enable"); + if (mEnabled) return; mEnabled = native_init(); if (mEnabled) { @@ -330,8 +332,10 @@ public class GpsLocationProvider extends LocationProviderImpl { * down while the provider is disabled. */ @Override - public void disable() { + public synchronized void disable() { if (Config.LOGD) Log.d(TAG, "disable"); + if (!mEnabled) return; + mEnabled = false; stopNavigating(); native_disable(); @@ -346,6 +350,11 @@ public class GpsLocationProvider extends LocationProviderImpl { mEventThread = null; } + if (mNetworkThread != null) { + mNetworkThread.setDone(); + mNetworkThread = null; + } + native_cleanup(); } @@ -745,12 +754,21 @@ public class GpsLocationProvider extends LocationProviderImpl { private long mNextNtpTime = 0; private long mNextXtraTime = 0; private boolean mXtraDownloadRequested = false; + private boolean mDone = false; public GpsNetworkThread() { super("GpsNetworkThread"); } public void run() { + synchronized (mNetworkThreadLock) { + if (!mDone) { + runLocked(); + } + } + } + + public void runLocked() { if (Config.LOGD) Log.d(TAG, "NetworkThread starting"); SntpClient client = new SntpClient(); @@ -761,7 +779,7 @@ public class GpsLocationProvider extends LocationProviderImpl { } // thread exits after disable() is called - while (mEnabled) { + while (!mDone) { long waitTime = getWaitTime(); do { synchronized (this) { @@ -784,11 +802,11 @@ public class GpsLocationProvider extends LocationProviderImpl { } } waitTime = getWaitTime(); - } while (mEnabled && ((!mXtraDownloadRequested && waitTime > 0) + } while (!mDone && ((!mXtraDownloadRequested && waitTime > 0) || !mNetworkAvailable)); if (Config.LOGD) Log.d(TAG, "NetworkThread out of wake loop"); - if (mEnabled) { + if (!mDone) { if (mNtpServer != null && mNextNtpTime <= System.currentTimeMillis()) { if (Config.LOGD) { @@ -840,6 +858,12 @@ public class GpsLocationProvider extends LocationProviderImpl { notify(); } + synchronized void setDone() { + if (Config.LOGD) Log.d(TAG, "stopping NetworkThread"); + mDone = true; + notify(); + } + private long getWaitTime() { long now = System.currentTimeMillis(); long waitTime = Long.MAX_VALUE; diff --git a/services/java/com/android/server/DeviceMemoryMonitor.java b/services/java/com/android/server/DeviceMemoryMonitor.java deleted file mode 100644 index 3669e1f4c2a3..000000000000 --- a/services/java/com/android/server/DeviceMemoryMonitor.java +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (C) 2007 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 com.android.server; - -import com.android.server.am.ActivityManagerService; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.pm.IPackageDataObserver; -import android.content.pm.IPackageManager; -import android.os.Binder; -import android.os.Handler; -import android.os.Message; -import android.os.Process; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.StatFs; -import android.os.SystemClock; -import android.os.SystemProperties; -import android.provider.Settings.Gservices; -import android.util.Config; -import android.util.EventLog; -import android.util.Log; -import android.provider.Settings; - -/** - * This class implements a service to monitor the amount of disk storage space - * on the device. If the free storage on device is less than a tunable threshold value - * (default is 10%. this value is a gservices parameter) a low memory notification is - * displayed to alert the user. If the user clicks on the low memory notification the - * Application Manager application gets launched to let the user free storage space. - * Event log events: - * A low memory event with the free storage on device in bytes is logged to the event log - * when the device goes low on storage space. - * The amount of free storage on the device is periodically logged to the event log. The log - * interval is a gservices parameter with a default value of 12 hours - * When the free storage differential goes below a threshold(again a gservices parameter with - * a default value of 2MB), the free memory is logged to the event log - */ -class DeviceMemoryMonitorService extends Binder { - private static final String TAG = "DeviceMemoryMonitor"; - private static final boolean DEBUG = false; - private static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV; - private static final int DEVICE_MEMORY_WHAT = 1; - private static final int MONITOR_INTERVAL = 1; //in minutes - private static final int LOW_MEMORY_NOTIFICATION_ID = 1; - private static final int DEFAULT_THRESHOLD_PERCENTAGE = 10; - private static final int DEFAULT_FREE_STORAGE_LOG_INTERVAL_IN_MINUTES = 12*60; //in minutes - private static final int EVENT_LOG_STORAGE_BELOW_THRESHOLD = 2744; - private static final int EVENT_LOG_LOW_STORAGE_NOTIFICATION = 2745; - private static final int EVENT_LOG_FREE_STORAGE_LEFT = 2746; - private static final long DEFAULT_DISK_FREE_CHANGE_REPORTING_THRESHOLD = 2 * 1024 * 1024; // 2MB - private long mFreeMem; - private long mLastReportedFreeMem; - private long mLastReportedFreeMemTime; - private boolean mLowMemFlag=false; - private Context mContext; - private ContentResolver mContentResolver; - int mBlkSize; - long mTotalMemory; - StatFs mFileStats; - private static final String DATA_PATH="/data"; - long mThreadStartTime = -1; - boolean mClearSucceeded = false; - boolean mClearingCache; - private Intent mStorageLowIntent; - private Intent mStorageOkIntent; - /** - * Handler that checks the amount of disk space on the device and sends a - * notification if the device runs low on disk space - */ - Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - //dont handle an invalid message - if (msg.what != DEVICE_MEMORY_WHAT) { - Log.e(TAG, "Will not process invalid message"); - return; - } - checkMemory(); - } - }; - - class CachePackageDataObserver extends IPackageDataObserver.Stub { - public void onRemoveCompleted(String packageName, boolean succeeded) { - mClearSucceeded = succeeded; - mClearingCache = false; - if(localLOGV) Log.i(TAG, " Clear succeeded:"+mClearSucceeded - +", mClearingCache:"+mClearingCache); - } - } - - private final void restatDataDir() { - mFileStats.restat(DATA_PATH); - mFreeMem = mFileStats.getAvailableBlocks()*mBlkSize; - // Allow freemem to be overridden by debug.freemem for testing - String debugFreeMem = SystemProperties.get("debug.freemem"); - if (!"".equals(debugFreeMem)) { - mFreeMem = Long.parseLong(debugFreeMem); - } - // Read the log interval from Gservices - long freeMemLogInterval = Gservices.getLong(mContentResolver, - Gservices.SYS_FREE_STORAGE_LOG_INTERVAL, - DEFAULT_FREE_STORAGE_LOG_INTERVAL_IN_MINUTES)*60*1000; - //log the amount of free memory in event log - long currTime = SystemClock.elapsedRealtime(); - if((mLastReportedFreeMemTime == 0) || - (currTime-mLastReportedFreeMemTime) >= freeMemLogInterval) { - mLastReportedFreeMemTime = currTime; - EventLog.writeEvent(EVENT_LOG_FREE_STORAGE_LEFT, mFreeMem); - } - // Read the reporting threshold from Gservices - long threshold = Gservices.getLong(mContentResolver, - Gservices.DISK_FREE_CHANGE_REPORTING_THRESHOLD, - DEFAULT_DISK_FREE_CHANGE_REPORTING_THRESHOLD); - // If mFree changed significantly log the new value - long delta = mFreeMem - mLastReportedFreeMem; - if (delta > threshold || delta < -threshold) { - mLastReportedFreeMem = mFreeMem; - EventLog.writeEvent(EVENT_LOG_STORAGE_BELOW_THRESHOLD, mFreeMem); - } - } - - private final void clearCache() { - CachePackageDataObserver observer = new CachePackageDataObserver(); - mClearingCache = true; - try { - IPackageManager.Stub.asInterface(ServiceManager.getService("package")). - freeApplicationCache(getMemThreshold(), observer); - } catch (RemoteException e) { - Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e); - mClearingCache = false; - mClearSucceeded = false; - } - } - - private final void checkMemory() { - //if the thread that was started to clear cache is still running do nothing till its - //finished clearing cache. Ideally this flag could be modified by clearCache - // and should be accessed via a lock but even if it does this test will fail now and - //hopefully the next time this flag will be set to the correct value. - if(mClearingCache) { - if(localLOGV) Log.i(TAG, "Thread already running just skip"); - //make sure the thread is not hung for too long - long diffTime = System.currentTimeMillis() - mThreadStartTime; - if(diffTime > (10*60*1000)) { - Log.w(TAG, "Thread that clears cache file seems to run for ever"); - } - } else { - restatDataDir(); - if (localLOGV) Log.v(TAG, "freeMemory="+mFreeMem); - //post intent to NotificationManager to display icon if necessary - long memThreshold = getMemThreshold(); - if (mFreeMem < memThreshold) { - if (!mLowMemFlag) { - //see if clearing cache helps - mThreadStartTime = System.currentTimeMillis(); - clearCache(); - Log.i(TAG, "Running low on memory. Sending notification"); - sendNotification(); - mLowMemFlag = true; - } else { - if (localLOGV) Log.v(TAG, "Running low on memory " + - "notification already sent. do nothing"); - } - } else { - if (mLowMemFlag) { - Log.i(TAG, "Memory available. Cancelling notification"); - cancelNotification(); - mLowMemFlag = false; - } - } - } - if(localLOGV) Log.i(TAG, "Posting Message again"); - //keep posting messages to itself periodically - mHandler.sendMessageDelayed(mHandler.obtainMessage(DEVICE_MEMORY_WHAT), - MONITOR_INTERVAL*60*1000); - } - - /* - * just query settings to retrieve the memory threshold. - * Preferred this over using a ContentObserver since Settings.Gservices caches the value - * any way - */ - private long getMemThreshold() { - int value = Settings.Gservices.getInt( - mContentResolver, - Settings.Gservices.SYS_STORAGE_THRESHOLD_PERCENTAGE, - DEFAULT_THRESHOLD_PERCENTAGE); - if(localLOGV) Log.v(TAG, "Threshold Percentage="+value); - //evaluate threshold value - return mTotalMemory*value; - } - - /** - * Constructor to run service. initializes the disk space threshold value - * and posts an empty message to kickstart the process. - */ - public DeviceMemoryMonitorService(Context context) { - mLastReportedFreeMemTime = 0; - mContext = context; - mContentResolver = mContext.getContentResolver(); - //create StatFs object - mFileStats = new StatFs(DATA_PATH); - //initialize block size - mBlkSize = mFileStats.getBlockSize(); - //initialize total storage on device - mTotalMemory = (mFileStats.getBlockCount()*mBlkSize)/100; - mStorageLowIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_LOW); - mStorageOkIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_OK); - checkMemory(); - } - - - /** - * This method sends a notification to NotificationManager to display - * an error dialog indicating low disk space and launch the Installer - * application - */ - private final void sendNotification() { - if(localLOGV) Log.i(TAG, "Sending low memory notification"); - //log the event to event log with the amount of free storage(in bytes) left on the device - EventLog.writeEvent(EVENT_LOG_LOW_STORAGE_NOTIFICATION, mFreeMem); - // Pack up the values and broadcast them to everyone - Intent lowMemIntent = new Intent(Intent.ACTION_MANAGE_PACKAGE_STORAGE); - lowMemIntent.putExtra("memory", mFreeMem); - lowMemIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - NotificationManager mNotificationMgr = - (NotificationManager)mContext.getSystemService( - Context.NOTIFICATION_SERVICE); - CharSequence title = mContext.getText( - com.android.internal.R.string.low_internal_storage_view_title); - CharSequence details = mContext.getText( - com.android.internal.R.string.low_internal_storage_view_text); - PendingIntent intent = PendingIntent.getActivity(mContext, 0, lowMemIntent, 0); - Notification notification = new Notification(); - notification.icon = com.android.internal.R.drawable.stat_notify_disk_full; - notification.tickerText = title; - notification.flags |= Notification.FLAG_NO_CLEAR; - notification.setLatestEventInfo(mContext, title, details, intent); - mNotificationMgr.notify(LOW_MEMORY_NOTIFICATION_ID, notification); - mContext.sendStickyBroadcast(mStorageLowIntent); - } - - /** - * Cancels low storage notification and sends OK intent. - */ - private final void cancelNotification() { - if(localLOGV) Log.i(TAG, "Canceling low memory notification"); - NotificationManager mNotificationMgr = - (NotificationManager)mContext.getSystemService( - Context.NOTIFICATION_SERVICE); - //cancel notification since memory has been freed - mNotificationMgr.cancel(LOW_MEMORY_NOTIFICATION_ID); - - mContext.removeStickyBroadcast(mStorageLowIntent); - mContext.sendBroadcast(mStorageOkIntent); - } - - public void updateMemory() { - ActivityManagerService ams = (ActivityManagerService)ServiceManager.getService("activity"); - int callingUid = getCallingUid(); - if(callingUid != Process.SYSTEM_UID) { - return; - } - //remove queued messages - mHandler.removeMessages(DEVICE_MEMORY_WHAT); - //force an early check - checkMemory(); - } -} diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java index 04b190037445..44f70f0d8017 100644 --- a/services/java/com/android/server/DeviceStorageMonitorService.java +++ b/services/java/com/android/server/DeviceStorageMonitorService.java @@ -149,7 +149,7 @@ class DeviceStorageMonitorService extends Binder { mClearingCache = true; try { IPackageManager.Stub.asInterface(ServiceManager.getService("package")). - freeApplicationCache(getMemThreshold(), observer); + freeStorageAndNotify(getMemThreshold(), observer); } catch (RemoteException e) { Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e); mClearingCache = false; diff --git a/services/java/com/android/server/GadgetService.java b/services/java/com/android/server/GadgetService.java index 4e4925361cc2..4be9ed557e6e 100644 --- a/services/java/com/android/server/GadgetService.java +++ b/services/java/com/android/server/GadgetService.java @@ -19,30 +19,264 @@ package com.android.server; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.PackageItemInfo; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; import android.gadget.GadgetManager; import android.gadget.GadgetInfo; +import android.os.Binder; +import android.util.AttributeSet; +import android.util.Log; +import android.util.Xml; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; import com.android.internal.gadget.IGadgetService; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + class GadgetService extends IGadgetService.Stub { private static final String TAG = "GadgetService"; + static class GadgetId { + int gadgetId; + String hostPackage; + GadgetInfo info; + } + Context mContext; + PackageManager mPackageManager; + ArrayList mInstalledProviders; + int mNextGadgetId = 1; + ArrayList mGadgetIds = new ArrayList(); GadgetService(Context context) { mContext = context; + mPackageManager = context.getPackageManager(); + mInstalledProviders = getGadgetList(); + } + + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mContext.checkCallingPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + + synchronized (mGadgetIds) { + int N = mInstalledProviders.size(); + pw.println("Providers: (size=" + N + ")"); + for (int i=0; i getInstalledProviders() { + synchronized (mGadgetIds) { + return new ArrayList(mInstalledProviders); + } + } + + boolean canAccessGadgetId(GadgetId id, String callingPackage) { + if (id.hostPackage.equals(callingPackage)) { + return true; + } + if (id.info != null && id.info.provider.getPackageName().equals(callingPackage)) { + return true; + } + // TODO: Check for the pick permission + //if (has permission) { + // return true; + //} + //return false; + return true; + } + + private GadgetId lookupGadgetIdLocked(int gadgetId) { + String callingPackage = getCallingPackage(); + final int N = mGadgetIds.size(); + for (int i=0; i getGadgetList() { + PackageManager pm = mPackageManager; + + // TODO: We have these as different actions. I wonder if it makes more sense to + // have like a GADGET_ACTION, and then subcommands. It's kind of arbitrary that + // we look for GADGET_UPDATE_ACTION and not any of the other gadget actions. + Intent intent = new Intent(GadgetManager.GADGET_UPDATE_ACTION); + List broadcastReceivers = pm.queryBroadcastReceivers(intent, + PackageManager.GET_META_DATA); + + ArrayList result = new ArrayList(); + + final int N = broadcastReceivers.size(); + for (int i=0; i= 0)); } catch (RemoteException e) { - Log.i(TAG, "Observer no longer exists."); + Log.w(TAG, "RemoveException when invoking call back"); } - } //end if observer - } //end run + } + } }); } + public void freeStorage(final long freeStorageSize, final PendingIntent opFinishedIntent) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CLEAR_APP_CACHE, null); + // Queue up an async operation since clearing cache may take a little while. + mHandler.post(new Runnable() { + public void run() { + mHandler.removeCallbacks(this); + int retCode = -1; + if (mInstaller != null) { + retCode = mInstaller.freeCache(freeStorageSize); + if (retCode < 0) { + Log.w(TAG, "Couldn't clear application caches"); + } + } + if(opFinishedIntent != null) { + try { + // Callback via pending intent + opFinishedIntent.send((retCode >= 0) ? 1 : 0); + } catch (CanceledException e1) { + Log.i(TAG, "Failed to send pending intent"); + } + } + } + }); + } + public ActivityInfo getActivityInfo(ComponentName component, int flags) { synchronized (mPackages) { PackageParser.Activity a = mActivities.mActivities.get(component); diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 881add11c51f..7ed0aecdbc03 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -165,6 +165,10 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo * value to another, when no window animation is driving it. */ static final int DEFAULT_DIM_DURATION = 200; + + /** Adjustment to time to perform a dim, to make it more dramatic. + */ + static final int DIM_DURATION_MULTIPLIER = 6; static final int UPDATE_FOCUS_NORMAL = 0; static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1; @@ -1129,7 +1133,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo if (win.mSurface != null && !mDisplayFrozen) { // If we are not currently running the exit animation, we // need to see about starting one. - if (win.isVisible()) { + if (win.isVisibleLw()) { int transit = WindowManagerPolicy.TRANSIT_EXIT; if (win.getAttrs().type == TYPE_APPLICATION_STARTING) { transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; @@ -1339,7 +1343,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo win.mViewVisibility = viewVisibility; if (viewVisibility == View.VISIBLE && (win.mAppToken == null || !win.mAppToken.clientHidden)) { - displayed = !win.isVisible(); + displayed = !win.isVisibleLw(); if (win.mExiting) { win.mExiting = false; win.mAnimation = null; @@ -1389,7 +1393,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo if (win.getAttrs().type == TYPE_APPLICATION_STARTING) { transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE; } - if (win.isVisible() && + if (win.isVisibleLw() && applyAnimationLocked(win, transit, false)) { win.mExiting = true; mKeyWaiter.finishedKey(session, client, true, @@ -2215,6 +2219,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo if (swin != null && (swin.mDrawPending || swin.mCommitDrawPending)) { swin.mPolicyVisibility = false; + swin.mPolicyVisibilityAfterAnim = false; } } @@ -2901,7 +2906,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo final int N = mWindows.size(); for (int i=0; i mUserLeaving=" + mUserLeaving); + // If the onlyIfNeeded flag is set, then we can do this if the activity // being launched is the same as the one making the call... or, as // a special case, if we do not know the caller then we count the @@ -3360,7 +3387,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (mPausingActivity == null) { if (DEBUG_PAUSE) Log.v(TAG, "Finish needs to pause: " + r); - startPausingLocked(); + if (DEBUG_USER_LEAVING) Log.v(TAG, "finish() => pause with userLeaving=false"); + startPausingLocked(false); } } else if (r.state != ActivityState.PAUSING) { @@ -6875,7 +6903,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen // run and release the wake lock when all done. if (mPausingActivity == null) { if (DEBUG_PAUSE) Log.v(TAG, "Sleep needs to pause..."); - startPausingLocked(); + if (DEBUG_USER_LEAVING) Log.v(TAG, "Sleep => pause with userLeaving=false"); + startPausingLocked(false); } } } diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java index 2d2faebe9806..3b6e354b6b48 100644 --- a/services/java/com/android/server/status/StatusBarService.java +++ b/services/java/com/android/server/status/StatusBarService.java @@ -331,6 +331,7 @@ public class StatusBarService extends IStatusBar.Stub mPixelFormat); lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL; lp.setTitle("StatusBar"); + lp.windowAnimations = R.style.Animation_StatusBar; WindowManagerImpl.getDefault().addView(mStatusBarView, lp); } diff --git a/telephony/java/com/android/internal/telephony/gsm/stk/StkService.java b/telephony/java/com/android/internal/telephony/gsm/stk/StkService.java index a90e7ea3beb8..c0c4ceb5c795 100644 --- a/telephony/java/com/android/internal/telephony/gsm/stk/StkService.java +++ b/telephony/java/com/android/internal/telephony/gsm/stk/StkService.java @@ -528,7 +528,16 @@ public class StkService extends Handler implements AppInterface { } private void handleCmdResponse(StkResponseMessage resMsg) { - // make sure the response details match the last valid command. + // Make sure the response details match the last valid command. An invalid + // response is a one that doesn't have a corresponding proactive command + // and sending it can "confuse" the baseband/ril. + // One reason for out of order responses can be UI glitches. For example, + // if the application launch an activity, and that activity is stored + // by the framework inside the history stack. That activity will be + // available for relaunch using the latest application dialog + // (long press on the home button). Relaunching that activity can send + // the same command's result again to the StkService and can cause it to + // get out of sync with the SIM. if (!validateResponse(resMsg)) { return; } @@ -578,9 +587,11 @@ public class StkService extends Handler implements AppInterface { break; case SET_UP_CALL: mCmdIf.handleCallSetupRequestFromSim(resMsg.usersConfirm, null); - if (!resMsg.usersConfirm) { - resMsg.resCode = ResultCode.USER_NOT_ACCEPT; - } + // No need to send terminal response for SET UP CALL. The user's + // confirmation result is send back using a dedicated ril message + // invoked by the CommandInterface call above. + mCurrntCmd = null; + return; } break; case NO_RESPONSE_FROM_USER: diff --git a/test-runner/android/test/mock/MockPackageManager.java b/test-runner/android/test/mock/MockPackageManager.java index 34ebd78544a3..f131bf26545b 100644 --- a/test-runner/android/test/mock/MockPackageManager.java +++ b/test-runner/android/test/mock/MockPackageManager.java @@ -16,6 +16,7 @@ package android.test.mock; +import android.app.PendingIntent; import android.content.ComponentName; import android.content.Intent; import android.content.IntentFilter; @@ -304,10 +305,19 @@ public class MockPackageManager extends PackageManager { * @hide - to match hiding in superclass */ @Override - public void freeApplicationCache( + public void freeStorageAndNotify( long idealStorageSize, IPackageDataObserver observer) { throw new UnsupportedOperationException(); } + + /** + * @hide - to match hiding in superclass + */ + @Override + public void freeStorage( + long idealStorageSize, PendingIntent onFinishedIntent) { + throw new UnsupportedOperationException(); + } /** * @hide - to match hiding in superclass diff --git a/tests/AndroidTests/src/com/android/unit_tests/AppCacheTest.java b/tests/AndroidTests/src/com/android/unit_tests/AppCacheTest.java index 914d98bcfd53..6a9ac86a854a 100755 --- a/tests/AndroidTests/src/com/android/unit_tests/AppCacheTest.java +++ b/tests/AndroidTests/src/com/android/unit_tests/AppCacheTest.java @@ -21,7 +21,12 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; + +import android.app.PendingIntent; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageStatsObserver; @@ -33,12 +38,13 @@ import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.SmallTest; import android.test.suitebuilder.annotation.Suppress; import android.util.Log; +import android.os.Handler; import android.os.RemoteException; import android.os.ServiceManager; import android.os.StatFs; public class AppCacheTest extends AndroidTestCase { - private static final boolean localLOGV = false; + private static final boolean localLOGV = true; public static final String TAG="AppCacheTest"; public final long MAX_WAIT_TIME=60*1000; public final long WAIT_TIME_INCR=10*1000; @@ -471,12 +477,11 @@ public class AppCacheTest extends AndroidTestCase { boolean invokePMFreeApplicationCache(long idealStorageSize) throws Exception { try { - String packageName = mContext.getPackageName(); PackageDataObserver observer = new PackageDataObserver(); //wait on observer synchronized(observer) { - getPm().freeApplicationCache(idealStorageSize, observer); + getPm().freeStorageAndNotify(idealStorageSize, observer); long waitTime = 0; while(!observer.isDone() || (waitTime > MAX_WAIT_TIME)) { observer.wait(WAIT_TIME_INCR); @@ -495,6 +500,31 @@ public class AppCacheTest extends AndroidTestCase { return false; } } + + boolean invokePMFreeStorage(long idealStorageSize, FreeStorageReceiver r, + PendingIntent pi) throws Exception { + try { + // Spin lock waiting for call back + synchronized(r) { + getPm().freeStorage(idealStorageSize, pi); + long waitTime = 0; + while(!r.isDone() && (waitTime < MAX_WAIT_TIME)) { + r.wait(WAIT_TIME_INCR); + waitTime += WAIT_TIME_INCR; + } + if(!r.isDone()) { + throw new Exception("timed out waiting for call back from PendingIntent"); + } + } + return r.getResultCode() == 1; + } catch (RemoteException e) { + Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e); + return false; + } catch (InterruptedException e) { + Log.w(TAG, "InterruptedException :"+e); + return false; + } + } @LargeTest public void testDeleteAppCacheFiles() throws Exception { @@ -563,6 +593,52 @@ public class AppCacheTest extends AndroidTestCase { ", cache="+stats.cacheSize); } + class FreeStorageReceiver extends BroadcastReceiver { + public static final String ACTION_FREE = "com.android.unit_tests.testcallback"; + private boolean doneFlag = false; + + public boolean isDone() { + return doneFlag; + } + + @Override + public void onReceive(Context context, Intent intent) { + if(intent.getAction().equalsIgnoreCase(ACTION_FREE)) { + if (localLOGV) Log.i(TAG, "Got notification: clear cache succeeded "+getResultCode()); + synchronized (this) { + doneFlag = true; + notifyAll(); + } + } + } + } + + @SmallTest + public void testFreeStorage() throws Exception { + StatFs st = new StatFs("/data"); + long blks1 = getFreeStorageBlks(st); + if(localLOGV) Log.i(TAG, "Available free blocks="+blks1); + long availableMem = getFreeStorageSize(st); + File cacheDir = mContext.getCacheDir(); + assertNotNull(cacheDir); + createTestFiles1(cacheDir, "testtmpdir", 5); + long blks2 = getFreeStorageBlks(st); + if(localLOGV) Log.i(TAG, "Available blocks after writing test files in application cache="+blks2); + // Create receiver and register it + FreeStorageReceiver receiver = new FreeStorageReceiver(); + mContext.registerReceiver(receiver, new IntentFilter(FreeStorageReceiver.ACTION_FREE)); + PendingIntent pi = PendingIntent.getBroadcast(mContext, + 0, new Intent(FreeStorageReceiver.ACTION_FREE), 0); + // Invoke PackageManager api + invokePMFreeStorage(availableMem, receiver, pi); + long blks3 = getFreeStorageBlks(st); + if(localLOGV) Log.i(TAG, "Available blocks after freeing cache"+blks3); + assertEquals(receiver.getResultCode(), 1); + mContext.unregisterReceiver(receiver); + // Verify result + verifyTestFiles1(cacheDir, "testtmpdir", 5); + } + /* utility method used to create observer and check async call back from PackageManager. * ClearApplicationUserData */ diff --git a/tests/AndroidTests/src/com/android/unit_tests/BluetoothTest.java b/tests/AndroidTests/src/com/android/unit_tests/BluetoothTest.java index 48a02c4a728b..21fb94b82200 100644 --- a/tests/AndroidTests/src/com/android/unit_tests/BluetoothTest.java +++ b/tests/AndroidTests/src/com/android/unit_tests/BluetoothTest.java @@ -234,30 +234,18 @@ public class BluetoothTest extends AndroidTestCase { } Log.i(TAG, "onEnableResult(" + result + ")"); } - public void onCreateBondingResult(String device, int res) { - String result = "unknown"; - switch (res) { - case BluetoothDevice.RESULT_SUCCESS: - result = "success"; - break; - case BluetoothDevice.RESULT_FAILURE: - result = "FAILURE"; - break; - } - Log.i(TAG, "onEnableResult(" + device + ", " + result + ")"); - } public void onGetRemoteServiceChannelResult(String device, int channel) {} }; @SmallTest - public void testCreateBondingWithCallback() throws Exception { + public void testCreateBond() throws Exception { BluetoothDevice device = (BluetoothDevice)getContext().getSystemService(Context.BLUETOOTH_SERVICE); if (device == null) { Log.i(TAG, "Device not Bluetooth capable, skipping test"); return; } - if (!device.createBonding("01:23:45:67:89:AB", mCallback)) { + if (!device.createBond("01:23:45:67:89:AB")) { Log.e(TAG, "createBonding() failed"); } } @@ -286,7 +274,7 @@ public class BluetoothTest extends AndroidTestCase { Log.i(TAG, "Device not Bluetooth capable, skipping test"); return; } - String[] addresses = device.listBondings(); + String[] addresses = device.listBonds(); if (addresses == null) { Log.i(TAG, "Bluetooth disabled"); return; @@ -363,8 +351,7 @@ public class BluetoothTest extends AndroidTestCase { filter.addAction(BluetoothIntent.REMOTE_NAME_FAILED_ACTION); filter.addAction(BluetoothIntent.REMOTE_ALIAS_CHANGED_ACTION); filter.addAction(BluetoothIntent.REMOTE_ALIAS_CLEARED_ACTION); - filter.addAction(BluetoothIntent.BONDING_CREATED_ACTION); - filter.addAction(BluetoothIntent.BONDING_REMOVED_ACTION); + filter.addAction(BluetoothIntent.BOND_STATE_CHANGED_ACTION); filter.addAction(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION); getContext().registerReceiver( (BroadcastReceiver)new BluetoothIntentReceiver(), filter); diff --git a/tests/FrameworkTest/res/layout/remote_view_test_good.xml b/tests/FrameworkTest/res/layout/remote_view_test_good.xml index 92ff21c6f35b..54f4db92cbf0 100644 --- a/tests/FrameworkTest/res/layout/remote_view_test_good.xml +++ b/tests/FrameworkTest/res/layout/remote_view_test_good.xml @@ -47,4 +47,13 @@ + + + +