From 22f7dfd23490a3de2f21ff96949ba47003aac8f8 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Tue, 20 Jan 2009 14:03:58 -0800 Subject: [PATCH] auto import from //branches/cupcake/...@127101 --- Android.mk | 7 +- api/current.xml | 280 +++++++++++++++--- camera/libcameraservice/CameraService.cpp | 56 +++- core/java/android/app/SearchDialog.java | 9 + .../java/android/bluetooth/BluetoothA2dp.java | 66 +++++ .../android/bluetooth/BluetoothHeadset.java | 109 +++++-- .../android/bluetooth/IBluetoothA2dp.aidl | 2 + .../android/bluetooth/IBluetoothHeadset.aidl | 18 +- core/java/android/content/Context.java | 9 + core/java/android/gadget/GadgetHost.java | 72 +++++ core/java/android/gadget/GadgetHostView.java | 102 +++++++ .../GadgetInfo.aidl} | 28 +- core/java/android/gadget/GadgetInfo.java | 126 ++++++++ core/java/android/gadget/GadgetManager.java | 170 +++++++++++ core/java/android/gadget/package.html | 4 + core/java/android/hardware/Camera.java | 27 +- .../InputMethodService.java | 198 ++++++++++--- core/java/android/provider/Settings.java | 38 ++- .../java/android/provider/UserDictionary.java | 127 ++++++++ .../android/server/BluetoothA2dpService.java | 52 +++- core/java/android/speech/srec/Recognizer.java | 40 +++ core/java/android/speech/srec/WaveHeader.java | 7 + core/java/android/view/ViewRoot.java | 30 +- .../view/inputmethod/InputMethodManager.java | 5 +- core/java/android/webkit/CallbackProxy.java | 134 ++++++++- core/java/android/webkit/TextDialog.java | 49 ++- core/java/android/webkit/WebView.java | 13 +- .../android/widget/AutoCompleteTextView.java | 2 +- core/java/android/widget/MediaController.java | 6 + core/java/android/widget/VideoView.java | 7 +- .../internal/gadget/IGadgetService.aidl | 28 ++ .../com/android/internal/gadget/package.html | 3 + .../android/internal/os/HandlerCaller.java | 2 +- .../internal/view/menu/IconMenuItemView.java | 4 +- .../internal/view/menu/ListMenuItemView.java | 8 +- .../internal/view/menu/MenuBuilder.java | 13 +- .../android/internal/widget/NumberPicker.java | 1 + core/jni/android_hardware_Camera.cpp | 40 ++- core/res/AndroidManifest.xml | 18 ++ .../res/drawable/btn_check_off_longpress.png | Bin 1633 -> 0 bytes .../res/drawable/btn_check_on_longpress.png | Bin 1661 -> 0 bytes core/res/res/drawable/emo_im_angel.png | Bin 0 -> 3592 bytes core/res/res/drawable/emo_im_cool.png | Bin 0 -> 3466 bytes core/res/res/drawable/emo_im_crying.png | Bin 0 -> 3558 bytes core/res/res/drawable/emo_im_embarrassed.png | Bin 0 -> 3619 bytes .../res/res/drawable/emo_im_foot_in_mouth.png | Bin 0 -> 3603 bytes core/res/res/drawable/emo_im_happy.png | Bin 0 -> 3591 bytes core/res/res/drawable/emo_im_kissing.png | Bin 0 -> 3492 bytes core/res/res/drawable/emo_im_laughing.png | Bin 0 -> 3624 bytes .../res/drawable/emo_im_lips_are_sealed.png | Bin 0 -> 3670 bytes core/res/res/drawable/emo_im_money_mouth.png | Bin 0 -> 3649 bytes core/res/res/drawable/emo_im_sad.png | Bin 0 -> 3572 bytes core/res/res/drawable/emo_im_surprised.png | Bin 0 -> 3490 bytes .../drawable/emo_im_tongue_sticking_out.png | Bin 0 -> 3653 bytes core/res/res/drawable/emo_im_undecided.png | Bin 0 -> 3552 bytes core/res/res/drawable/emo_im_winking.png | Bin 0 -> 3568 bytes core/res/res/drawable/emo_im_wtf.png | Bin 0 -> 3591 bytes core/res/res/drawable/emo_im_yelling.png | Bin 0 -> 3575 bytes .../res/res/drawable/ic_menu_account_list.png | Bin 0 -> 2394 bytes core/res/res/drawable/ic_menu_allfriends.png | Bin 0 -> 2257 bytes core/res/res/drawable/ic_menu_archive.png | Bin 0 -> 1354 bytes core/res/res/drawable/ic_menu_attachment.png | Bin 0 -> 2247 bytes core/res/res/drawable/ic_menu_back.png | Bin 0 -> 1237 bytes core/res/res/drawable/ic_menu_block.png | Bin 0 -> 2336 bytes .../res/res/drawable/ic_menu_blocked_user.png | Bin 0 -> 2408 bytes core/res/res/drawable/ic_menu_cc.png | Bin 0 -> 2046 bytes .../res/drawable/ic_menu_chat_dashboard.png | Bin 0 -> 1865 bytes .../res/drawable/ic_menu_clear_playlist.png | Bin 0 -> 2281 bytes core/res/res/drawable/ic_menu_compose.png | Bin 0 -> 2014 bytes core/res/res/drawable/ic_menu_emoticons.png | Bin 0 -> 2620 bytes .../res/drawable/ic_menu_end_conversation.png | Bin 0 -> 1932 bytes core/res/res/drawable/ic_menu_forward.png | Bin 0 -> 1228 bytes core/res/res/drawable/ic_menu_friendslist.png | Bin 0 -> 1561 bytes core/res/res/drawable/ic_menu_goto.png | Bin 0 -> 1636 bytes core/res/res/drawable/ic_menu_home.png | Bin 0 -> 2048 bytes core/res/res/drawable/ic_menu_invite.png | Bin 0 -> 2349 bytes core/res/res/drawable/ic_menu_mark.png | Bin 0 -> 2519 bytes core/res/res/drawable/ic_menu_play_clip.png | Bin 0 -> 1471 bytes core/res/res/drawable/ic_menu_star.png | Bin 0 -> 1608 bytes .../drawable/ic_menu_start_conversation.png | Bin 0 -> 1715 bytes core/res/res/drawable/ic_menu_stop.png | Bin 0 -> 1930 bytes core/res/res/drawable/ic_power.png | Bin 925 -> 0 bytes core/res/res/layout/js_prompt.xml | 38 +++ core/res/res/layout/zoom_controls.xml | 10 +- core/res/res/layout/zoom_magnify.xml | 7 +- core/res/res/values-cs/strings.xml | 14 + core/res/res/values-de/strings.xml | 86 +++--- core/res/res/values-es/strings.xml | 14 + core/res/res/values-fr/strings.xml | 14 + core/res/res/values-it/strings.xml | 14 + core/res/res/values-ja/strings.xml | 14 + core/res/res/values-nl/strings.xml | 14 + core/res/res/values-pl/strings.xml | 14 + core/res/res/values-ru/strings.xml | 14 + core/res/res/values-zh-rCN/strings.xml | 14 + core/res/res/values-zh-rTW/strings.xml | 14 + core/res/res/values/attrs.xml | 6 +- core/res/res/values/public.xml | 26 +- core/res/res/values/strings.xml | 20 ++ core/res/res/values/styles.xml | 7 + .../screen_background_blue-land.png | Bin 11681 -> 0 bytes .../screen_background_green-land.png | Bin 9861 -> 0 bytes .../screen_background_white-land.png | Bin 8332 -> 0 bytes include/media/AudioRecord.h | 2 +- include/media/AudioTrack.h | 2 +- include/media/ToneGenerator.h | 2 +- include/private/media/AudioTrackShared.h | 9 +- include/ui/Overlay.h | 6 +- include/utils/Parcel.h | 13 + libs/audioflinger/A2dpAudioInterface.cpp | 2 +- libs/surfaceflinger/LayerBuffer.h | 2 +- libs/ui/Camera.cpp | 55 ++-- libs/ui/Overlay.cpp | 27 +- libs/utils/Parcel.cpp | 63 +++- media/libmedia/AudioRecord.cpp | 46 +-- media/libmedia/AudioTrack.cpp | 82 +++-- .../com/android/server/GadgetService.java | 64 ++++ .../java/com/android/server/SystemServer.java | 9 +- .../android/server/WifiWatchdogService.java | 74 ++++- .../widget/AutoCompleteTextViewPopup.java | 31 ++ tests/GadgetHost/Android.mk | 11 + tests/GadgetHost/AndroidManifest.xml | 22 ++ tests/GadgetHost/res/layout/gadget_host.xml | 50 ++++ tests/GadgetHost/res/layout/test_gadget.xml | 22 ++ tests/GadgetHost/res/values/strings.xml | 22 ++ .../gadgethost/GadgetContainerView.java | 32 ++ .../gadgethost/GadgetHostActivity.java | 133 +++++++++ .../gadgethost/GadgetPickActivity.java | 70 +++++ .../gadgethost/TestGadgetProvider.java | 32 ++ tools/aapt/ResourceTable.cpp | 5 +- 130 files changed, 2728 insertions(+), 410 deletions(-) create mode 100644 core/java/android/gadget/GadgetHost.java create mode 100644 core/java/android/gadget/GadgetHostView.java rename core/java/android/{bluetooth/IBluetoothHeadsetCallback.aidl => gadget/GadgetInfo.aidl} (55%) create mode 100644 core/java/android/gadget/GadgetInfo.java create mode 100644 core/java/android/gadget/GadgetManager.java create mode 100644 core/java/android/gadget/package.html create mode 100644 core/java/android/provider/UserDictionary.java create mode 100644 core/java/com/android/internal/gadget/IGadgetService.aidl create mode 100644 core/java/com/android/internal/gadget/package.html delete mode 100644 core/res/res/drawable/btn_check_off_longpress.png delete mode 100644 core/res/res/drawable/btn_check_on_longpress.png create mode 100644 core/res/res/drawable/emo_im_angel.png create mode 100644 core/res/res/drawable/emo_im_cool.png create mode 100644 core/res/res/drawable/emo_im_crying.png create mode 100644 core/res/res/drawable/emo_im_embarrassed.png create mode 100644 core/res/res/drawable/emo_im_foot_in_mouth.png create mode 100644 core/res/res/drawable/emo_im_happy.png create mode 100644 core/res/res/drawable/emo_im_kissing.png create mode 100644 core/res/res/drawable/emo_im_laughing.png create mode 100644 core/res/res/drawable/emo_im_lips_are_sealed.png create mode 100644 core/res/res/drawable/emo_im_money_mouth.png create mode 100644 core/res/res/drawable/emo_im_sad.png create mode 100644 core/res/res/drawable/emo_im_surprised.png create mode 100644 core/res/res/drawable/emo_im_tongue_sticking_out.png create mode 100644 core/res/res/drawable/emo_im_undecided.png create mode 100644 core/res/res/drawable/emo_im_winking.png create mode 100644 core/res/res/drawable/emo_im_wtf.png create mode 100644 core/res/res/drawable/emo_im_yelling.png create mode 100644 core/res/res/drawable/ic_menu_account_list.png create mode 100755 core/res/res/drawable/ic_menu_allfriends.png create mode 100644 core/res/res/drawable/ic_menu_archive.png create mode 100644 core/res/res/drawable/ic_menu_attachment.png create mode 100644 core/res/res/drawable/ic_menu_back.png create mode 100644 core/res/res/drawable/ic_menu_block.png create mode 100644 core/res/res/drawable/ic_menu_blocked_user.png create mode 100644 core/res/res/drawable/ic_menu_cc.png create mode 100644 core/res/res/drawable/ic_menu_chat_dashboard.png create mode 100644 core/res/res/drawable/ic_menu_clear_playlist.png create mode 100644 core/res/res/drawable/ic_menu_compose.png create mode 100644 core/res/res/drawable/ic_menu_emoticons.png create mode 100644 core/res/res/drawable/ic_menu_end_conversation.png create mode 100644 core/res/res/drawable/ic_menu_forward.png create mode 100644 core/res/res/drawable/ic_menu_friendslist.png create mode 100644 core/res/res/drawable/ic_menu_goto.png create mode 100644 core/res/res/drawable/ic_menu_home.png create mode 100644 core/res/res/drawable/ic_menu_invite.png create mode 100644 core/res/res/drawable/ic_menu_mark.png create mode 100644 core/res/res/drawable/ic_menu_play_clip.png create mode 100755 core/res/res/drawable/ic_menu_star.png create mode 100644 core/res/res/drawable/ic_menu_start_conversation.png create mode 100644 core/res/res/drawable/ic_menu_stop.png delete mode 100755 core/res/res/drawable/ic_power.png create mode 100644 core/res/res/layout/js_prompt.xml delete mode 100644 core/res/waitingroom/screen_background_blue-land.png delete mode 100644 core/res/waitingroom/screen_background_green-land.png delete mode 100644 core/res/waitingroom/screen_background_white-land.png create mode 100644 services/java/com/android/server/GadgetService.java create mode 100644 tests/GadgetHost/Android.mk create mode 100644 tests/GadgetHost/AndroidManifest.xml create mode 100644 tests/GadgetHost/res/layout/gadget_host.xml create mode 100644 tests/GadgetHost/res/layout/test_gadget.xml create mode 100644 tests/GadgetHost/res/values/strings.xml create mode 100644 tests/GadgetHost/src/com/android/gadgethost/GadgetContainerView.java create mode 100644 tests/GadgetHost/src/com/android/gadgethost/GadgetHostActivity.java create mode 100644 tests/GadgetHost/src/com/android/gadgethost/GadgetPickActivity.java create mode 100644 tests/GadgetHost/src/com/android/gadgethost/TestGadgetProvider.java diff --git a/Android.mk b/Android.mk index 18051aaa8a86a..d67a21e46e897 100644 --- a/Android.mk +++ b/Android.mk @@ -71,7 +71,6 @@ LOCAL_SRC_FILES += \ core/java/android/bluetooth/IBluetoothDevice.aidl \ core/java/android/bluetooth/IBluetoothDeviceCallback.aidl \ core/java/android/bluetooth/IBluetoothHeadset.aidl \ - core/java/android/bluetooth/IBluetoothHeadsetCallback.aidl \ core/java/android/content/ISyncAdapter.aidl \ core/java/android/content/ISyncContext.aidl \ core/java/android/content/pm/IPackageDataObserver.aidl \ @@ -98,6 +97,7 @@ LOCAL_SRC_FILES += \ core/java/android/view/IWindowManager.aidl \ core/java/android/view/IWindowSession.aidl \ core/java/com/android/internal/app/IBatteryStats.aidl \ + core/java/com/android/internal/gadget/IGadgetService.aidl \ core/java/com/android/internal/view/IInputContext.aidl \ core/java/com/android/internal/view/IInputContextCallback.aidl \ core/java/com/android/internal/view/IInputMethod.aidl \ @@ -165,6 +165,7 @@ aidl_files := \ frameworks/base/core/java/android/content/Intent.aidl \ frameworks/base/core/java/android/content/SyncStats.aidl \ frameworks/base/core/java/android/content/res/Configuration.aidl \ + frameworks/base/core/java/android/gadget/GadgetInfo.aidl \ frameworks/base/core/java/android/net/Uri.aidl \ frameworks/base/core/java/android/os/Bundle.aidl \ frameworks/base/core/java/android/os/ParcelFileDescriptor.aidl \ @@ -421,4 +422,8 @@ include $(BUILD_JAVA_LIBRARY) # Include subdirectory makefiles # ============================================================ +# If we're building with ONE_SHOT_MAKEFILE (mm, mmm), then what the framework +# team really wants is to build the stuff defined by this makefile. +ifeq (,$(ONE_SHOT_MAKEFILE)) include $(call first-makefiles-under,$(LOCAL_PATH)) +endif diff --git a/api/current.xml b/api/current.xml index f6fa67d385343..e183217d003c7 100644 --- a/api/current.xml +++ b/api/current.xml @@ -8563,22 +8563,198 @@ visibility="public" > - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + & cameraService, status_t CameraService::Client::checkPid() { - // zero means the interface is not locked down - if (mClientPid == 0) return NO_ERROR; - return (int) mClientPid == IPCThreadState::self()->getCallingPid() ? NO_ERROR : -EBUSY; + if (mClientPid == IPCThreadState::self()->getCallingPid()) return NO_ERROR; + LOGW("Attempt to use locked camera from different process"); + return -EBUSY; } status_t CameraService::Client::lock() { - // lock camera to this client - status_t result = checkPid(); - if (result == NO_ERROR) mClientPid = IPCThreadState::self()->getCallingPid(); - return result; + // lock camera to this client if the the camera is unlocked + if (mClientPid == 0) { + mClientPid = IPCThreadState::self()->getCallingPid(); + return NO_ERROR; + } + // returns NO_ERROR if the client already owns the camera, -EBUSY otherwise + return checkPid(); } status_t CameraService::Client::unlock() { // allow anyone to use camera + LOGV("unlock"); status_t result = checkPid(); if (result == NO_ERROR) mClientPid = 0; return result; @@ -189,12 +193,29 @@ status_t CameraService::Client::unlock() status_t CameraService::Client::connect(const sp& client) { - // remove old client - LOGV("connect new client to existing camera"); - Mutex::Autolock _l(mLock); - mCameraClient = client; - mClientPid = IPCThreadState::self()->getCallingPid(); - mFrameCallbackFlag = FRAME_CALLBACK_FLAG_NOOP; + // connect a new process to the camera + LOGV("connect"); + + // hold a reference to the old client or we will deadlock if the client is + // in the same process and we hold the lock when we remove the reference + sp oldClient; + { + Mutex::Autolock _l(mLock); + if (mClientPid != 0) { + LOGW("Tried to connect to locked camera"); + return -EBUSY; + } + oldClient = mCameraClient; + + // did the client actually change? + if (client->asBinder() == mCameraClient->asBinder()) return NO_ERROR; + + LOGV("connect new process to existing camera client"); + mCameraClient = client; + mClientPid = IPCThreadState::self()->getCallingPid(); + mFrameCallbackFlag = FRAME_CALLBACK_FLAG_NOOP; + } + return NO_ERROR; } @@ -210,7 +231,7 @@ static void *unregister_surface(void *arg) CameraService::Client::~Client() { - // spin down hardware + // tear down client LOGD("Client E destructor"); if (mSurface != 0) { #if HAVE_ANDROID_OS @@ -227,6 +248,8 @@ CameraService::Client::~Client() #endif } + // make sure we tear down the hardware + mClientPid = IPCThreadState::self()->getCallingPid(); disconnect(); LOGD("Client X destructor"); } @@ -235,7 +258,12 @@ void CameraService::Client::disconnect() { LOGD("Client E disconnect"); Mutex::Autolock lock(mLock); + if (mClientPid == 0) { + LOGV("camera is unlocked, don't tear down hardware"); + return; + } if (checkPid() != NO_ERROR) return; + mCameraService->removeClient(mCameraClient); if (mHardware != 0) { // Before destroying mHardware, we must make sure it's in the diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index 495156e280e27..5af08f77298a1 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -1128,6 +1128,15 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS super(context, attrs, defStyle); } + /** + * We never allow ACTV to automatically replace the text, since we use "jamSuggestionQuery" + * to do that. There's no point in letting ACTV do this here, because in the search UI, + * as soon as we click a suggestion, we're going to start shutting things down. + */ + @Override + public void replaceText(CharSequence text) { + } + /** * We always return true, so that the effective threshold is "zero". This allows us * to provide "null" suggestions such as "just show me some recent entries". diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java index 022a87cd443ce..b0b0154abc906 100644 --- a/core/java/android/bluetooth/BluetoothA2dp.java +++ b/core/java/android/bluetooth/BluetoothA2dp.java @@ -72,6 +72,12 @@ public class BluetoothA2dp { /** Playing implies connected */ public static final int STATE_PLAYING = 4; + /** Default priority for a2dp devices that should allow incoming + * connections */ + public static final int PRIORITY_AUTO = 100; + /** Default priority for a2dp devices that should not allow incoming + * connections */ + public static final int PRIORITY_OFF = 0; private final IBluetoothA2dp mService; private final Context mContext; @@ -158,6 +164,66 @@ public class BluetoothA2dp { } } + /** + * Set priority of a2dp sink. + * Priority is a non-negative integer. By default paired sinks will have + * a priority of PRIORITY_AUTO, and unpaired headset PRIORITY_NONE (0). + * Sinks with priority greater than zero will accept incoming connections + * (if no sink is currently connected). + * Priority for unpaired sink must be PRIORITY_NONE. + * @param address Paired sink + * @param priority Integer priority, for example PRIORITY_AUTO or + * PRIORITY_NONE + * @return Result code, negative indicates an error + */ + public int setSinkPriority(String address, int priority) { + try { + return mService.setSinkPriority(address, priority); + } catch (RemoteException e) { + Log.w(TAG, "", e); + return BluetoothError.ERROR_IPC; + } + } + + /** + * Get priority of a2dp sink. + * @param address Sink + * @return non-negative priority, or negative error code on error. + */ + public int getSinkPriority(String address) { + try { + return mService.getSinkPriority(address); + } catch (RemoteException e) { + Log.w(TAG, "", e); + return BluetoothError.ERROR_IPC; + } + } + + /** + * Check class bits for possible A2DP Sink support. + * This is a simple heuristic that tries to guess if a device with the + * given class bits might be a A2DP Sink. It is not accurate for all + * devices. It tries to err on the side of false positives. + * @return True if this device might be a A2DP sink + */ + public static boolean doesClassMatchSink(int btClass) { + if (BluetoothClass.Service.hasService(btClass, BluetoothClass.Service.RENDER)) { + return true; + } + // By the A2DP spec, sinks must indicate the RENDER service. + // However we found some that do not (Chordette). So lets also + // match on some other class bits. + switch (BluetoothClass.Device.getDevice(btClass)) { + case BluetoothClass.Device.AUDIO_VIDEO_HIFI_AUDIO: + case BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES: + case BluetoothClass.Device.AUDIO_VIDEO_LOUDSPEAKER: + case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO: + return true; + default: + return false; + } + } + /** Helper for converting a state to a string. * For debug use only - strings are not internationalized. * @hide diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index 905173e34083e..c3152719bbb61 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -57,7 +57,6 @@ public class BluetoothHeadset { private IBluetoothHeadset mService; private final Context mContext; private final ServiceListener mServiceListener; - private ConnectHeadsetCallback mConnectHeadsetCallback; /** There was an error trying to obtain the state */ public static final int STATE_ERROR = -1; @@ -73,6 +72,11 @@ public class BluetoothHeadset { /** Connection cancelled before completetion. */ public static final int RESULT_CANCELLED = 2; + /** Default priority for headsets that should be auto-connected */ + public static final int PRIORITY_AUTO = 100; + /** Default priority for headsets that should not be auto-connected */ + public static final int PRIORITY_OFF = 0; + /** * An interface for notifying BluetoothHeadset IPC clients when they have * been connected to the BluetoothHeadset service. @@ -96,14 +100,6 @@ public class BluetoothHeadset { public void onServiceDisconnected(); } - /** - * Interface for connectHeadset() callback. - * This callback can occur in the Binder thread. - */ - public interface ConnectHeadsetCallback { - public void onConnectHeadsetResult(String address, int resultCode); - } - /** * Create a BluetoothHeadset proxy object. */ @@ -175,24 +171,18 @@ public class BluetoothHeadset { * Request to initiate a connection to a headset. * This call does not block. Fails if a headset is already connecting * or connected. - * Will connect to the last connected headset if address is null. - * onConnectHeadsetResult() of your ConnectHeadsetCallback will be called - * on completition. - * @param address The Bluetooth Address to connect to, or null to connect - * to the last connected headset. - * @param callback Callback on result. Not called if false is returned. Can - * be null. - * to the last connected headset. + * Initiates auto-connection if address is null. Tries to connect to all + * devices with priority greater than PRIORITY_AUTO in descending order. + * @param address The Bluetooth Address to connect to, or null to + * auto-connect to the last connected headset. * @return False if there was a problem initiating the connection - * procedure, and your callback will not be used. True if - * the connection procedure was initiated, in which case - * your callback is guarenteed to be called. + * procedure, and no further HEADSET_STATE_CHANGED intents + * will be expected. */ - public boolean connectHeadset(String address, ConnectHeadsetCallback callback) { + public boolean connectHeadset(String address) { if (mService != null) { try { - if (mService.connectHeadset(address, mHeadsetCallback)) { - mConnectHeadsetCallback = callback; + if (mService.connectHeadset(address)) { return true; } } catch (RemoteException e) {Log.e(TAG, e.toString());} @@ -273,6 +263,71 @@ public class BluetoothHeadset { return false; } + /** + * Set priority of headset. + * Priority is a non-negative integer. By default paired headsets will have + * a priority of PRIORITY_AUTO, and unpaired headset PRIORITY_NONE (0). + * Headsets with priority greater than zero will be auto-connected, and + * incoming connections will be accepted (if no other headset is + * connected). + * Auto-connection occurs at the following events: boot, incoming phone + * call, outgoing phone call. + * Headsets with priority equal to zero, or that are unpaired, are not + * auto-connected. + * Incoming connections are ignored regardless of priority if there is + * already a headset connected. + * @param address Paired headset + * @param priority Integer priority, for example PRIORITY_AUTO or + * PRIORITY_NONE + * @return True if successful, false if there was some error. + */ + public boolean setPriority(String address, int priority) { + if (mService != null) { + try { + return mService.setPriority(address, priority); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return false; + } + + /** + * Get priority of headset. + * @param address Headset + * @return non-negative priority, or negative error code on error. + */ + public int getPriority(String address) { + if (mService != null) { + try { + return mService.getPriority(address); + } catch (RemoteException e) {Log.e(TAG, e.toString());} + } else { + Log.w(TAG, "Proxy not attached to service"); + if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); + } + return -1; + } + + /** + * Check class bits for possible HSP or HFP support. + * This is a simple heuristic that tries to guess if a device with the + * given class bits might support HSP or HFP. It is not accurate for all + * devices. It tries to err on the side of false positives. + * @return True if this device might support HSP or HFP. + */ + public static boolean doesClassMatch(int btClass) { + switch (BluetoothClass.Device.getDevice(btClass)) { + case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE: + case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET: + case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO: + return true; + default: + return false; + } + } + private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected"); @@ -289,12 +344,4 @@ public class BluetoothHeadset { } } }; - - private IBluetoothHeadsetCallback mHeadsetCallback = new IBluetoothHeadsetCallback.Stub() { - public void onConnectHeadsetResult(String address, int resultCode) { - if (mConnectHeadsetCallback != null) { - mConnectHeadsetCallback.onConnectHeadsetResult(address, resultCode); - } - } - }; } diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl index 7e0226d2fd9a6..55ff27f97ec03 100644 --- a/core/java/android/bluetooth/IBluetoothA2dp.aidl +++ b/core/java/android/bluetooth/IBluetoothA2dp.aidl @@ -26,4 +26,6 @@ interface IBluetoothA2dp { int disconnectSink(in String address); List listConnectedSinks(); int getSinkState(in String address); + int setSinkPriority(in String address, int priority); + int getSinkPriority(in String address); } diff --git a/core/java/android/bluetooth/IBluetoothHeadset.aidl b/core/java/android/bluetooth/IBluetoothHeadset.aidl index 564861ff4c774..582d4e340ee17 100644 --- a/core/java/android/bluetooth/IBluetoothHeadset.aidl +++ b/core/java/android/bluetooth/IBluetoothHeadset.aidl @@ -16,8 +16,6 @@ package android.bluetooth; -import android.bluetooth.IBluetoothHeadsetCallback; - /** * System private API for Bluetooth Headset service * @@ -25,22 +23,12 @@ import android.bluetooth.IBluetoothHeadsetCallback; */ interface IBluetoothHeadset { int getState(); - String getHeadsetAddress(); - - // Request that the given headset be connected - // Assumes the given headset is already bonded - // Will disconnect any currently connected headset - // returns false if cannot start a connection (for example, there is - // already a pending connect). callback will always be called iff this - // returns true - boolean connectHeadset(in String address, in IBluetoothHeadsetCallback callback); - + boolean connectHeadset(in String address); void disconnectHeadset(); - boolean isConnected(in String address); - boolean startVoiceRecognition(); - boolean stopVoiceRecognition(); + boolean setPriority(in String address, int priority); + int getPriority(in String address); } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 6da00dfb30f69..3908aa1bf80fc 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -1248,6 +1248,15 @@ public abstract class Context { */ public static final String INPUT_METHOD_SERVICE = "input_method"; + /** + * Use with {@link #getSystemService} to retrieve a + * {@blink android.gadget.GadgetManager} for accessing wallpapers. + * + * @hide + * @see #getSystemService + */ + public static final String GADGET_SERVICE = "gadget"; + /** * Determine whether the given permission is allowed for a particular * process and user ID running in the system. diff --git a/core/java/android/gadget/GadgetHost.java b/core/java/android/gadget/GadgetHost.java new file mode 100644 index 0000000000000..418f2aa17998b --- /dev/null +++ b/core/java/android/gadget/GadgetHost.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gadget; + +import android.content.Context; +import android.widget.RemoteViews; + +/** + * GadgetHost provides the interaction with the Gadget Service for apps, + * like the home screen, that want to embed gadgets in their UI. + */ +public class GadgetHost { + public GadgetHost(Context context, int hostId) { + } + + /** + * Start receiving onGadgetChanged calls for your gadgets. Call this when your activity + * becomes visible, i.e. from onStart() in your Activity. + */ + public void startListening() { + } + + /** + * Stop receiving onGadgetChanged calls for your gadgets. Call this when your activity is + * no longer visible, i.e. from onStop() in your Activity. + */ + public void stopListening() { + } + + /** + * Stop listening to changes for this gadget. + */ + public void gadgetRemoved(int gadgetId) { + } + + /** + * Remove all records about gadget instances from the gadget manager. Call this when + * initializing your database, as it might be because of a data wipe. + */ + public void clearGadgets() { + } + + public final GadgetHostView createView(Context context, int gadgetId, GadgetInfo gadget) { + GadgetHostView view = onCreateView(context, gadgetId, gadget); + view.setGadget(gadgetId, gadget); + view.updateGadget(null); + return view; + } + + /** + * Called to create the GadgetHostView. Override to return a custom subclass if you + * need it. {@more} + */ + protected GadgetHostView onCreateView(Context context, int gadgetId, GadgetInfo gadget) { + return new GadgetHostView(context); + } +} + diff --git a/core/java/android/gadget/GadgetHostView.java b/core/java/android/gadget/GadgetHostView.java new file mode 100644 index 0000000000000..e2bef8c12e40b --- /dev/null +++ b/core/java/android/gadget/GadgetHostView.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gadget; + +import android.content.Context; +import android.content.pm.PackageManager; +import android.gadget.GadgetInfo; +import android.util.AttributeSet; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.RemoteViews; +import android.widget.TextView; + +public class GadgetHostView extends FrameLayout { + static final String TAG = "GadgetHostView"; + + // When we're inflating the initialLayout for a gadget, we only allow + // views that are allowed in RemoteViews. + static final LayoutInflater.Filter sInflaterFilter = new LayoutInflater.Filter() { + public boolean onLoadClass(Class clazz) { + return clazz.isAnnotationPresent(RemoteViews.RemoteView.class); + } + }; + + int mGadgetId; + GadgetInfo mInfo; + View mContentView; + + public GadgetHostView(Context context) { + super(context); + } + + public void setGadget(int gadgetId, GadgetInfo info) { + if (mInfo != null) { + // TODO: remove the old view, or whatever + } + mGadgetId = gadgetId; + mInfo = info; + } + + public void updateGadget(RemoteViews remoteViews) { + Context context = getContext(); + + View contentView = null; + Exception exception = null; + try { + if (remoteViews == null) { + // there is no remoteViews (yet), so use the initial layout + Context theirContext = context.createPackageContext(mInfo.provider.getPackageName(), + 0); + LayoutInflater inflater = (LayoutInflater)theirContext.getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + inflater = inflater.cloneInContext(theirContext); + inflater.setFilter(sInflaterFilter); + contentView = inflater.inflate(mInfo.initialLayout, this, false); + } else { + // use the RemoteViews + contentView = remoteViews.apply(mContext, this); + } + } + catch (PackageManager.NameNotFoundException e) { + exception = e; + } + catch (RuntimeException e) { + exception = e; + } + if (contentView == null) { + Log.w(TAG, "Error inflating gadget " + mInfo, exception); + // TODO: Should we throw an exception here for the host activity to catch? + // Maybe we should show a generic error widget. + TextView tv = new TextView(context); + tv.setText("Error inflating gadget"); + contentView = tv; + } + + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.WRAP_CONTENT, + FrameLayout.LayoutParams.WRAP_CONTENT); + + mContentView = contentView; + this.addView(contentView, lp); + + // TODO: do an animation (maybe even one provided by the gadget). + } +} + diff --git a/core/java/android/bluetooth/IBluetoothHeadsetCallback.aidl b/core/java/android/gadget/GadgetInfo.aidl similarity index 55% rename from core/java/android/bluetooth/IBluetoothHeadsetCallback.aidl rename to core/java/android/gadget/GadgetInfo.aidl index 03e884b341ca8..72315454b6dd8 100644 --- a/core/java/android/bluetooth/IBluetoothHeadsetCallback.aidl +++ b/core/java/android/gadget/GadgetInfo.aidl @@ -1,25 +1,19 @@ /* - * Copyright (C) 2008, The Android Open Source Project + * 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 + * 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 + * 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 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and * limitations under the License. */ -package android.bluetooth; +package android.gadget; -/** - * {@hide} - */ -oneway interface IBluetoothHeadsetCallback -{ - void onConnectHeadsetResult(in String address, int resultCode); -} +parcelable GadgetInfo; diff --git a/core/java/android/gadget/GadgetInfo.java b/core/java/android/gadget/GadgetInfo.java new file mode 100644 index 0000000000000..1a7a9a0ef0443 --- /dev/null +++ b/core/java/android/gadget/GadgetInfo.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gadget; + +import android.os.Parcel; +import android.os.Parcelable; +import android.content.ComponentName; + +/** + * Describes the meta data for an installed gadget. + */ +public class GadgetInfo implements Parcelable { + /** + * Identity of this gadget component. This component should be a {@link + * android.content.BroadcastReceiver}, and it will be sent the Gadget intents + * {@link android.gadget as described in the gadget package documentation}. + */ + public ComponentName provider; + + /** + * Minimum width of the gadget, in dp. + */ + public int minWidth; + + /** + * Minimum height of the gadget, in dp. + */ + public int minHeight; + + /** + * How often, in milliseconds, that this gadget wants to be updated. + * The gadget manager may place a limit on how often a gadget is updated. + */ + public int updatePeriodMillis; + + /** + * The resource id of the initial layout for this gadget. This should be + * displayed until the RemoteViews for the gadget is available. + */ + public int initialLayout; + + /** + * The activity to launch that will configure the gadget. + */ + public ComponentName configure; + + public GadgetInfo() { + } + + /** + * Unflatten the GadgetInfo from a parcel. + */ + public GadgetInfo(Parcel in) { + if (0 != in.readInt()) { + this.provider = new ComponentName(in); + } + this.minWidth = in.readInt(); + this.minHeight = in.readInt(); + this.updatePeriodMillis = in.readInt(); + this.initialLayout = in.readInt(); + if (0 != in.readInt()) { + this.configure = new ComponentName(in); + } + } + + + public void writeToParcel(android.os.Parcel out, int flags) { + if (this.provider != null) { + out.writeInt(1); + this.provider.writeToParcel(out, flags); + } else { + out.writeInt(0); + } + out.writeInt(this.minWidth); + out.writeInt(this.minHeight); + out.writeInt(this.updatePeriodMillis); + out.writeInt(this.initialLayout); + if (this.configure != null) { + out.writeInt(1); + this.configure.writeToParcel(out, flags); + } else { + out.writeInt(0); + } + } + + public int describeContents() { + return 0; + } + + /** + * Parcelable.Creator that instantiates GadgetInfo objects + */ + public static final Parcelable.Creator CREATOR + = new Parcelable.Creator() + { + public GadgetInfo createFromParcel(Parcel parcel) + { + return new GadgetInfo(parcel); + } + + public GadgetInfo[] newArray(int size) + { + return new GadgetInfo[size]; + } + }; + + public String toString() { + return "GadgetInfo(provider=" + this.provider + ")"; + } +} + + diff --git a/core/java/android/gadget/GadgetManager.java b/core/java/android/gadget/GadgetManager.java new file mode 100644 index 0000000000000..49c706e83add4 --- /dev/null +++ b/core/java/android/gadget/GadgetManager.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.gadget; + +import android.content.ComponentName; +import android.content.Context; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; +import android.widget.RemoteViews; + +import com.android.internal.gadget.IGadgetService; + +import java.lang.ref.WeakReference; +import java.util.List; +import java.util.WeakHashMap; + +public class GadgetManager { + static final String TAG = "GadgetManager"; + + /** + * Send this when you want to pick a gadget to display. + * + *

+ * The system will respond with an onActivityResult call with the following extras in + * the intent: + *

    + *
  • gadgetId
  • + *
  • gadgetId
  • + *
  • gadgetId
  • + *
+ * TODO: Add constants for these. + * TODO: Where does this go? + */ + public static final String GADGET_PICK_ACTION = "android.gadget.action.PICK_GADGET"; + + public static final String EXTRA_GADGET_ID = "gadgetId"; + + /** + * Sent when it is time to update your gadget. + */ + public static final String GADGET_UPDATE_ACTION = "android.gadget.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"; + + /** + * 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"; + + static WeakHashMap> sManagerCache = new WeakHashMap(); + static IGadgetService sService; + + Context mContext; + + public static GadgetManager getInstance(Context context) { + synchronized (sManagerCache) { + if (sService == null) { + IBinder b = ServiceManager.getService(Context.GADGET_SERVICE); + sService = IGadgetService.Stub.asInterface(b); + } + + WeakReference ref = sManagerCache.get(context); + GadgetManager result = null; + if (ref != null) { + result = ref.get(); + } + if (result == null) { + result = new GadgetManager(context); + sManagerCache.put(context, new WeakReference(result)); + } + return result; + } + } + + private GadgetManager(Context context) { + mContext = context; + } + + /** + * Call this with the new RemoteViews for your gadget whenever you need to. + * + *

+ * This method will only work when called from the uid that owns the gadget provider. + * + * @param gadgetId The gadget instance for which to set the RemoteViews. + * @param views The RemoteViews object to show. + */ + public void updateGadget(int gadgetId, RemoteViews views) { + } + + /** + * Return a list of the gadgets that are currently installed. + */ + public List getAvailableGadgets() { + return null; + } + + /** + * Get the available info about the gadget. If the gadgetId has not been bound yet, + * this method will return null. + * + * TODO: throws GadgetNotFoundException ??? if not valid + */ + public GadgetInfo getGadgetInfo(int gadgetId) { + try { + return sService.getGadgetInfo(gadgetId); + } + catch (RemoteException e) { + throw new RuntimeException("system server dead?", e); + } + } + + /** + * Get a gadgetId for a host in the calling process. + * + * @return a gadgetId + */ + public int allocateGadgetId(String hostPackage) { + try { + return sService.allocateGadgetId(hostPackage); + } + catch (RemoteException e) { + throw new RuntimeException("system server dead?", e); + } + } + + /** + * Delete the gadgetId. Same as removeGadget on GadgetHost. + */ + public void deleteGadgetId(int gadgetId) { + try { + sService.deleteGadgetId(gadgetId); + } + catch (RemoteException e) { + throw new RuntimeException("system server dead?", e); + } + } + + /** + * Set the component for a given gadgetId. You need the GADGET_LIST permission. + */ + public void bindGadgetId(int gadgetId, ComponentName provider) { + try { + sService.bindGadgetId(gadgetId, provider); + } + catch (RemoteException e) { + throw new RuntimeException("system server dead?", e); + } + } +} + diff --git a/core/java/android/gadget/package.html b/core/java/android/gadget/package.html new file mode 100644 index 0000000000000..280ccfb4512d4 --- /dev/null +++ b/core/java/android/gadget/package.html @@ -0,0 +1,4 @@ + +@hide + + diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java index e2d7097af3b75..c09567c7f0a6d 100644 --- a/core/java/android/hardware/Camera.java +++ b/core/java/android/hardware/Camera.java @@ -55,6 +55,7 @@ public class Camera { private PreviewCallback mPreviewCallback; private AutoFocusCallback mAutoFocusCallback; private ErrorCallback mErrorCallback; + private boolean mOneShot; /** * Returns a new Camera object. @@ -198,9 +199,25 @@ public class Camera { */ public final void setPreviewCallback(PreviewCallback cb) { mPreviewCallback = cb; - setHasPreviewCallback(cb != null); + mOneShot = false; + setHasPreviewCallback(cb != null, false); } - private native final void setHasPreviewCallback(boolean installed); + + /** + * Installs a callback to retrieve a single preview frame, after which the + * callback is cleared. + * + * @param cb A callback object that receives a copy of the preview frame. + */ + public final void setOneShotPreviewCallback(PreviewCallback cb) { + if (cb != null) { + mPreviewCallback = cb; + mOneShot = true; + setHasPreviewCallback(true, true); + } + } + + private native final void setHasPreviewCallback(boolean installed, boolean oneshot); private class EventHandler extends Handler { @@ -230,8 +247,12 @@ public class Camera { return; case PREVIEW_CALLBACK: - if (mPreviewCallback != null) + if (mPreviewCallback != null) { mPreviewCallback.onPreviewFrame((byte[])msg.obj, mCamera); + if (mOneShot) { + mPreviewCallback = null; + } + } return; case AUTOFOCUS_CALLBACK: diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index 21bb38ec78e35..1a7547df6da0c 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -33,6 +33,8 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; +import android.view.Window; +import android.view.WindowManager; import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; @@ -197,6 +199,7 @@ public class InputMethodService extends AbstractInputMethodService { EditorInfo mInputEditorInfo; boolean mShowInputRequested; + boolean mLastShowInputRequested; boolean mShowCandidatesRequested; boolean mFullscreenApplied; @@ -257,6 +260,8 @@ public class InputMethodService extends AbstractInputMethodService { public void bindInput(InputBinding binding) { mInputBinding = binding; mInputConnection = binding.getConnection(); + if (DEBUG) Log.v(TAG, "bindInput(): binding=" + binding + + " ic=" + mInputConnection); onBindInput(); } @@ -264,17 +269,22 @@ public class InputMethodService extends AbstractInputMethodService { * Clear the current input binding. */ public void unbindInput() { + if (DEBUG) Log.v(TAG, "unbindInput(): binding=" + mInputBinding + + " ic=" + mInputConnection); + onUnbindInput(); mInputStarted = false; mInputBinding = null; mInputConnection = null; } public void startInput(EditorInfo attribute) { + if (DEBUG) Log.v(TAG, "startInput(): editor=" + attribute); doStartInput(attribute, false); } public void restartInput(EditorInfo attribute) { - doStartInput(attribute, false); + if (DEBUG) Log.v(TAG, "restartInput(): editor=" + attribute); + doStartInput(attribute, true); } /** @@ -305,6 +315,7 @@ public class InputMethodService extends AbstractInputMethodService { if (!isEnabled()) { return; } + if (DEBUG) Log.v(TAG, "finishInput() in " + this); onFinishInput(); mInputStarted = false; } @@ -455,7 +466,7 @@ public class InputMethodService extends AbstractInputMethodService { mIsInputViewShown = false; mExtractFrame.setVisibility(View.GONE); - mCandidatesFrame.setVisibility(View.GONE); + mCandidatesFrame.setVisibility(View.INVISIBLE); mInputFrame.setVisibility(View.GONE); } @@ -468,6 +479,29 @@ public class InputMethodService extends AbstractInputMethodService { } } + /** + * Take care of handling configuration changes. Subclasses of + * InputMethodService generally don't need to deal directly with + * this on their own; the standard implementation here takes care of + * regenerating the input method UI as a result of the configuration + * change, so you can rely on your {@link #onCreateInputView} and + * other methods being called as appropriate due to a configuration change. + */ + @Override public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + + boolean visible = mWindowVisible; + boolean showingInput = mShowInputRequested; + boolean showingCandidates = mShowCandidatesRequested; + initViews(); + if (visible) { + if (showingCandidates) { + setCandidatesViewShown(true); + } + showWindow(showingInput); + } + } + /** * Implement to return our standard {@link InputMethodImpl}. Subclasses * can override to provide their own customized version. @@ -492,6 +526,27 @@ public class InputMethodService extends AbstractInputMethodService { return mWindow; } + /** + * Return the maximum width, in pixels, available the input method. + * Input methods are positioned at the bottom of the screen and, unless + * running in fullscreen, will generally want to be as short as possible + * so should compute their height based on their contents. However, they + * can stretch as much as needed horizontally. The function returns to + * you the maximum amount of space available horizontally, which you can + * use if needed for UI placement. + * + *

In many cases this is not needed, you can just rely on the normal + * view layout mechanisms to position your views within the full horizontal + * space given to the input method. + * + *

Note that this value can change dynamically, in particular when the + * screen orientation changes. + */ + public int getMaxWidth() { + WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); + return wm.getDefaultDisplay().getWidth(); + } + /** * Return the currently active InputBinding for the input method, or * null if there is none. @@ -525,12 +580,19 @@ public class InputMethodService extends AbstractInputMethodService { * is currently running in fullscreen mode. */ public void updateFullscreenMode() { - boolean isFullscreen = onEvaluateFullscreenMode(); + boolean isFullscreen = mShowInputRequested && onEvaluateFullscreenMode(); + boolean changed = mLastShowInputRequested != mShowInputRequested; if (mIsFullscreen != isFullscreen || !mFullscreenApplied) { + changed = true; mIsFullscreen = isFullscreen; mFullscreenApplied = true; - mWindow.getWindow().setBackgroundDrawable( - onCreateBackgroundDrawable()); + Drawable bg = onCreateBackgroundDrawable(); + if (bg == null) { + // We need to give the window a real drawable, so that it + // correctly sets its mode. + bg = getResources().getDrawable(android.R.color.transparent); + } + mWindow.getWindow().setBackgroundDrawable(bg); mExtractFrame.setVisibility(isFullscreen ? View.VISIBLE : View.GONE); if (isFullscreen) { if (mExtractView == null) { @@ -540,11 +602,39 @@ public class InputMethodService extends AbstractInputMethodService { } } startExtractingText(); - mWindow.getWindow().setLayout(FILL_PARENT, FILL_PARENT); - } else { - mWindow.getWindow().setLayout(WRAP_CONTENT, WRAP_CONTENT); } } + + if (changed) { + onConfigureWindow(mWindow.getWindow(), isFullscreen, + !mShowInputRequested); + mLastShowInputRequested = mShowInputRequested; + } + } + + /** + * Update the given window's parameters for the given mode. This is called + * when the window is first displayed and each time the fullscreen or + * candidates only mode changes. + * + *

The default implementation makes the layout for the window + * FILL_PARENT x FILL_PARENT when in fullscreen mode, and + * FILL_PARENT x WRAP_CONTENT when in non-fullscreen mode. + * + * @param win The input method's window. + * @param isFullscreen If true, the window is running in fullscreen mode + * and intended to cover the entire application display. + * @param isCandidatesOnly If true, the window is only showing the + * candidates view and none of the rest of its UI. This is mutually + * exclusive with fullscreen mode. + */ + public void onConfigureWindow(Window win, boolean isFullscreen, + boolean isCandidatesOnly) { + if (isFullscreen) { + mWindow.getWindow().setLayout(FILL_PARENT, FILL_PARENT); + } else { + mWindow.getWindow().setLayout(FILL_PARENT, WRAP_CONTENT); + } } /** @@ -607,7 +697,7 @@ public class InputMethodService extends AbstractInputMethodService { * is currently shown. */ public void updateInputViewShown() { - boolean isShown = onEvaluateInputViewShown(); + boolean isShown = mShowInputRequested && onEvaluateInputViewShown(); if (mIsInputViewShown != isShown && mWindowVisible) { mIsInputViewShown = isShown; mInputFrame.setVisibility(isShown ? View.VISIBLE : View.GONE); @@ -650,18 +740,18 @@ public class InputMethodService extends AbstractInputMethodService { public void setCandidatesViewShown(boolean shown) { if (mShowCandidatesRequested != shown) { mCandidatesFrame.setVisibility(shown ? View.VISIBLE : View.INVISIBLE); - if (!mShowInputRequested) { - // If we are being asked to show the candidates view while the app - // has not asked for the input view to be shown, then we need - // to update whether the window is shown. - if (shown) { - showWindow(false); - } else { - hideWindow(); - } - } mShowCandidatesRequested = shown; } + if (!mShowInputRequested && mWindowVisible != shown) { + // If we are being asked to show the candidates view while the app + // has not asked for the input view to be shown, then we need + // to update whether the window is shown. + if (shown) { + showWindow(false); + } else { + hideWindow(); + } + } } public void setStatusIcon(int iconResId) { @@ -729,7 +819,7 @@ public class InputMethodService extends AbstractInputMethodService { * Called by the framework to create a Drawable for the background of * the input method window. May return null for no background. The default * implementation returns a non-null standard background only when in - * fullscreen mode. + * fullscreen mode. This is called each time the fullscreen mode changes. */ public Drawable onCreateBackgroundDrawable() { if (isFullscreenMode()) { @@ -789,22 +879,6 @@ public class InputMethodService extends AbstractInputMethodService { public void onStartInputView(EditorInfo info, boolean restarting) { } - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - - boolean visible = mWindowVisible; - boolean showingInput = mShowInputRequested; - boolean showingCandidates = mShowCandidatesRequested; - initViews(); - if (visible) { - if (showingCandidates) { - setCandidatesViewShown(true); - } - showWindow(showingInput); - } - } - /** * The system has decided that it may be time to show your input method. * This is called due to a corresponding call to your @@ -837,17 +911,17 @@ public class InputMethodService extends AbstractInputMethodService { boolean wasVisible = mWindowVisible; mWindowVisible = true; if (!mShowInputRequested) { - doShowInput = true; - mShowInputRequested = true; + if (showInput) { + doShowInput = true; + mShowInputRequested = true; + } } else { showInput = true; } - if (doShowInput) { - if (DEBUG) Log.v(TAG, "showWindow: updating UI"); - updateFullscreenMode(); - updateInputViewShown(); - } + if (DEBUG) Log.v(TAG, "showWindow: updating UI"); + updateFullscreenMode(); + updateInputViewShown(); if (!mWindowAdded || !mWindowCreated) { mWindowAdded = true; @@ -885,13 +959,44 @@ public class InputMethodService extends AbstractInputMethodService { } } + /** + * Called when a new client has bound to the input method. This + * may be followed by a series of {@link #onStartInput(EditorInfo, boolean)} + * and {@link #onFinishInput()} calls as the user navigates through its + * UI. Upon this call you know that {@link #getCurrentInputBinding} + * and {@link #getCurrentInputConnection} return valid objects. + */ public void onBindInput() { } + /** + * Called when the previous bound client is no longer associated + * with the input method. After returning {@link #getCurrentInputBinding} + * and {@link #getCurrentInputConnection} will no longer return + * valid objects. + */ + public void onUnbindInput() { + } + + /** + * Called to inform the input method that text input has started in an + * editor. You should use this callback to initialize the state of your + * input to match the state of the editor given to it. + * + * @param attribute The attributes of the editor that input is starting + * in. + * @param restarting Set to true if input is restarting in the same + * editor such as because the application has changed the text in + * the editor. Otherwise will be false, indicating this is a new + * session with the editor. + */ public void onStartInput(EditorInfo attribute, boolean restarting) { } void doStartInput(EditorInfo attribute, boolean restarting) { + if (mInputStarted && !restarting) { + onFinishInput(); + } mInputStarted = true; mInputEditorInfo = attribute; onStartInput(attribute, restarting); @@ -903,6 +1008,13 @@ public class InputMethodService extends AbstractInputMethodService { } } + /** + * Called to inform the input method that text input has finished in + * the last editor. At this point there may be a call to + * {@link #onStartInput(EditorInfo, boolean)} to perform input in a + * new editor, or the input method may be left idle. This method is + * not called when input restarts in the same editor. + */ public void onFinishInput() { } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 7b64405177624..a18f37c3ca1cf 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -1740,12 +1740,12 @@ public final class Settings { */ public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/secure"); - + /** * Whether ADB is enabled. */ public static final String ADB_ENABLED = "adb_enabled"; - + /** * Setting to allow mock locations and location provider status to be injected into the * LocationManager service for testing purposes during application development. These @@ -1753,7 +1753,7 @@ public final class Settings { * by network, gps, or other location providers. */ public static final String ALLOW_MOCK_LOCATION = "mock_location"; - + /** * The Android ID (a unique 64-bit value) as a hex string. * Identical to that obtained by calling @@ -1761,24 +1761,40 @@ public final class Settings { * so you can get it without binding to a service. */ public static final String ANDROID_ID = "android_id"; - + /** * Whether bluetooth is enabled/disabled * 0=disabled. 1=enabled. */ public static final String BLUETOOTH_ON = "bluetooth_on"; - + + /** + * Get the key that retrieves a bluetooth headset's priority. + * @hide + */ + public static final String getBluetoothHeadsetPriorityKey(String address) { + return ("bluetooth_headset_priority_" + address.toUpperCase()); + } + + /** + * Get the key that retrieves a bluetooth a2dp sink's priority. + * @hide + */ + public static final String getBluetoothA2dpSinkPriorityKey(String address) { + return ("bluetooth_a2dp_sink_priority_" + address.toUpperCase()); + } + /** * Whether or not data roaming is enabled. (0 = false, 1 = true) */ public static final String DATA_ROAMING = "data_roaming"; - + /** * Setting to record the input method used by default, holding the ID * of the desired method. */ public static final String DEFAULT_INPUT_METHOD = "default_input_method"; - + /** * Whether the device has been provisioned (0 = false, 1 = true) */ @@ -1953,7 +1969,13 @@ public final class Settings { * Whether the Wi-Fi watchdog is enabled. */ public static final String WIFI_WATCHDOG_ON = "wifi_watchdog_on"; - + + /** + * A comma-separated list of SSIDs for which the Wi-Fi watchdog should be enabled. + * @hide pending API council + */ + public static final String WIFI_WATCHDOG_WATCH_LIST = "wifi_watchdog_watch_list"; + /** * The number of pings to test if an access point is a good connection. */ diff --git a/core/java/android/provider/UserDictionary.java b/core/java/android/provider/UserDictionary.java new file mode 100644 index 0000000000000..58e5731f4cc76 --- /dev/null +++ b/core/java/android/provider/UserDictionary.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.provider; + +import java.util.Locale; + +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.net.Uri; +import android.text.TextUtils; + +/** + * + * @hide Pending API council approval + */ +public class UserDictionary { + public static final String AUTHORITY = "user_dictionary"; + + /** + * The content:// style URL for this provider + */ + public static final Uri CONTENT_URI = + Uri.parse("content://" + AUTHORITY); + + /** + * Contains the user defined words. + * @hide Pending API council approval + */ + public static class Words implements BaseColumns { + /** + * The content:// style URL for this table + */ + public static final Uri CONTENT_URI = + Uri.parse("content://" + AUTHORITY + "/words"); + + /** + * The MIME type of {@link #CONTENT_URI} providing a directory of words. + */ + public static final String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.google.userword"; + + /** + * The MIME type of a {@link #CONTENT_URI} sub-directory of a single word. + */ + public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.google.userword"; + + public static final String _ID = BaseColumns._ID; + + /** + * The word column. + *

TYPE: TEXT

+ */ + public static final String WORD = "word"; + + /** + * The frequency column. A value between 1 and 255. + *

TYPE: INTEGER

+ */ + public static final String FREQUENCY = "frequency"; + + /** + * The locale that this word belongs to. Null if it pertains to all + * locales. Locale is a 5 letter string such as
en_US
. + *

TYPE: TEXT

+ */ + public static final String LOCALE = "locale"; + + /** + * The uid of the application that inserted the word. + *

TYPE: INTEGER

+ */ + public static final String APP_ID = "appid"; + + public static final int LOCALE_TYPE_ALL = 0; + + public static final int LOCALE_TYPE_CURRENT = 1; + + /** + * Sort by descending order of frequency. + */ + public static final String DEFAULT_SORT_ORDER = FREQUENCY + " DESC"; + + + public static void addWord(Context context, String word, + int frequency, int localeType) { + final ContentResolver resolver = context.getContentResolver(); + + if (TextUtils.isEmpty(word) || localeType < 0 || localeType > 1) { + return; + } + + if (frequency < 0) frequency = 0; + if (frequency > 255) frequency = 255; + + String locale = null; + + // TODO: Verify if this is the best way to get the current locale + if (localeType == LOCALE_TYPE_CURRENT) { + locale = Locale.getDefault().toString(); + } + ContentValues values = new ContentValues(4); + + values.put(WORD, word); + values.put(FREQUENCY, frequency); + values.put(LOCALE, locale); + values.put(APP_ID, 0); // TODO: Get App UID + + Uri result = resolver.insert(CONTENT_URI, values); + // It's ok if the insert doesn't succeed because the word + // already exists. + } + } +} diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java index 90ef8f68a987b..be784ff3e2fcb 100644 --- a/core/java/android/server/BluetoothA2dpService.java +++ b/core/java/android/server/BluetoothA2dpService.java @@ -35,6 +35,7 @@ import android.content.IntentFilter; import android.content.pm.PackageManager; import android.media.AudioManager; import android.os.Binder; +import android.provider.Settings; import android.util.Log; import java.io.FileDescriptor; @@ -83,6 +84,8 @@ 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); mContext.registerReceiver(mReceiver, mIntentFilter); if (device.isEnabled()) { @@ -103,10 +106,15 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); + String address = intent.getStringExtra(BluetoothIntent.ADDRESS); if (action.equals(BluetoothIntent.ENABLED_ACTION)) { 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); } } }; @@ -145,7 +153,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { if (path == null) { return BluetoothError.ERROR; } - + SinkState sink = mAudioDevices.get(path); int state = BluetoothA2dp.STATE_DISCONNECTED; if (sink != null) { @@ -159,8 +167,8 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { case BluetoothA2dp.STATE_CONNECTING: return BluetoothError.SUCCESS; } - - // State is DISCONNECTED + + // State is DISCONNECTED if (!connectSinkNative(path)) { return BluetoothError.ERROR; } @@ -189,7 +197,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { return BluetoothError.SUCCESS; } - // State is CONNECTING or CONNECTED or PLAYING + // State is CONNECTING or CONNECTED or PLAYING if (!disconnectSinkNative(path)) { return BluetoothError.ERROR; } else { @@ -229,16 +237,37 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { return BluetoothA2dp.STATE_DISCONNECTED; } - public synchronized void onHeadsetCreated(String path) { + public synchronized int getSinkPriority(String address) { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); + if (!BluetoothDevice.checkBluetoothAddress(address)) { + return BluetoothError.ERROR; + } + return Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.getBluetoothA2dpSinkPriorityKey(address), + BluetoothA2dp.PRIORITY_OFF); + } + + public synchronized int setSinkPriority(String address, int priority) { + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, + "Need BLUETOOTH_ADMIN permission"); + if (!BluetoothDevice.checkBluetoothAddress(address)) { + return BluetoothError.ERROR; + } + return Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.getBluetoothA2dpSinkPriorityKey(address), priority) ? + BluetoothError.SUCCESS : BluetoothError.ERROR; + } + + private synchronized void onHeadsetCreated(String path) { updateState(path, BluetoothA2dp.STATE_DISCONNECTED); } - public synchronized void onHeadsetRemoved(String path) { + private synchronized void onHeadsetRemoved(String path) { if (mAudioDevices == null) return; mAudioDevices.remove(path); } - public synchronized void onSinkConnected(String path) { + private synchronized void onSinkConnected(String path) { if (mAudioDevices == null) return; // bluez 3.36 quietly disconnects the previous sink when a new sink // is connected, so we need to mark all previously connected sinks as @@ -258,16 +287,16 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { updateState(path, BluetoothA2dp.STATE_CONNECTED); } - public synchronized void onSinkDisconnected(String path) { + private synchronized void onSinkDisconnected(String path) { mAudioManager.setBluetoothA2dpOn(false); updateState(path, BluetoothA2dp.STATE_DISCONNECTED); } - public synchronized void onSinkPlaying(String path) { + private synchronized void onSinkPlaying(String path) { updateState(path, BluetoothA2dp.STATE_PLAYING); } - public synchronized void onSinkStopped(String path) { + private synchronized void onSinkStopped(String path) { updateState(path, BluetoothA2dp.STATE_CONNECTED); } @@ -307,7 +336,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { if (state != prevState) { if (DBG) log("state " + address + " (" + path + ") " + prevState + "->" + state); - + Intent intent = new Intent(BluetoothA2dp.SINK_STATE_CHANGED_ACTION); intent.putExtra(BluetoothIntent.ADDRESS, address); intent.putExtra(BluetoothA2dp.SINK_PREVIOUS_STATE, prevState); @@ -339,5 +368,4 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { private synchronized native boolean connectSinkNative(String path); private synchronized native boolean disconnectSinkNative(String path); private synchronized native boolean isSinkConnectedNative(String path); - } diff --git a/core/java/android/speech/srec/Recognizer.java b/core/java/android/speech/srec/Recognizer.java index 749c9235cd38a..a03a36a26e13f 100644 --- a/core/java/android/speech/srec/Recognizer.java +++ b/core/java/android/speech/srec/Recognizer.java @@ -367,6 +367,35 @@ public final class Recognizer { SR_RecognizerStop(mRecognizer); SR_RecognizerDeactivateRule(mRecognizer, mActiveGrammar.mGrammar, "trash"); } + + /** + * Reset the acoustic state vectorto it's default value. + * + * @hide + */ + public void resetAcousticState() { + SR_AcousticStateReset(mRecognizer); + } + + /** + * Set the acoustic state vector. + * @param state String containing the acoustic state vector. + * + * @hide + */ + public void setAcousticState(String state) { + SR_AcousticStateSet(mRecognizer, state); + } + + /** + * Get the acoustic state vector. + * @return String containing the acoustic state vector. + * + * @hide + */ + public String getAcousticState() { + return SR_AcousticStateGet(mRecognizer); + } /** * Clean up resources. @@ -572,6 +601,9 @@ public final class Recognizer { return "EVENT_" + event; } + // + // SR_Recognizer methods + // private static native void SR_RecognizerStart(int recognizer); private static native void SR_RecognizerStop(int recognizer); private static native int SR_RecognizerCreate(); @@ -615,6 +647,14 @@ public final class Recognizer { private static native boolean SR_RecognizerIsSignalTooFewSamples(int recognizer); private static native boolean SR_RecognizerIsSignalTooManySamples(int recognizer); // private static native void SR_Recognizer_Change_Sample_Rate (size_t new_sample_rate); + + + // + // SR_AcousticState native methods + // + private static native void SR_AcousticStateReset(int recognizer); + private static native void SR_AcousticStateSet(int recognizer, String state); + private static native String SR_AcousticStateGet(int recognizer); // diff --git a/core/java/android/speech/srec/WaveHeader.java b/core/java/android/speech/srec/WaveHeader.java index 0aa3cc22aa4d5..a99496de4ac7e 100644 --- a/core/java/android/speech/srec/WaveHeader.java +++ b/core/java/android/speech/srec/WaveHeader.java @@ -263,5 +263,12 @@ public class WaveHeader { out.write(val >> 0); out.write(val >> 8); } + + @Override + public String toString() { + return String.format( + "WaveHeader format=%d numChannels=%d sampleRate=%d bitsPerSample=%d numBytes=%d", + mFormat, mNumChannels, mSampleRate, mBitsPerSample, mNumBytes); + } } diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index 9d7a124cb01ab..9e0289a4bedbb 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -117,6 +117,7 @@ public final class ViewRoot extends Handler implements ViewParent, View mView; View mFocusedView; + View mRealFocusedView; // this is not set to null in touch mode int mViewVisibility; boolean mAppVisible = true; @@ -971,9 +972,19 @@ public final class ViewRoot extends Handler implements ViewParent, if (mFirst) { // handle first focus request - if (mView != null && !mView.hasFocus()) { - mView.requestFocus(View.FOCUS_FORWARD); - mFocusedView = mView.findFocus(); + if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: mView.hasFocus()=" + + mView.hasFocus()); + if (mView != null) { + if (!mView.hasFocus()) { + mView.requestFocus(View.FOCUS_FORWARD); + mFocusedView = mRealFocusedView = mView.findFocus(); + if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: requested focused view=" + + mFocusedView); + } else { + mRealFocusedView = mView.findFocus(); + if (DEBUG_INPUT_RESIZE) Log.v(TAG, "First: existing focused view=" + + mRealFocusedView); + } } } @@ -1214,13 +1225,16 @@ public final class ViewRoot extends Handler implements ViewParent, // requestChildRectangleOnScreen() call (in which case 'rectangle' // is non-null and we just want to scroll to whatever that // rectangle is). - View focus = mFocusedView; + View focus = mRealFocusedView; if (focus != mLastScrolledFocus) { // If the focus has changed, then ignore any requests to scroll // to a rectangle; first we want to make sure the entire focus // view is visible. rectangle = null; } + if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Eval scroll: focus=" + focus + + " rectangle=" + rectangle + " ci=" + ci + + " vi=" + vi); if (focus == mLastScrolledFocus && !mScrollMayChange && rectangle == null) { // Optimization: if the focus hasn't changed since last @@ -1234,6 +1248,7 @@ public final class ViewRoot extends Handler implements ViewParent, // a pan so it can be seen. mLastScrolledFocus = focus; mScrollMayChange = false; + if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Need to scroll?"); // Try to find the rectangle from the focus view. if (focus.getGlobalVisibleRect(mVisRect, null)) { if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Root w=" @@ -1307,7 +1322,9 @@ public final class ViewRoot extends Handler implements ViewParent, mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(mFocusedView, focused); scheduleTraversals(); } - mFocusedView = focused; + mFocusedView = mRealFocusedView = focused; + if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Request child focus: focus now " + + mFocusedView); } public void clearChildFocus(View child) { @@ -1315,7 +1332,8 @@ public final class ViewRoot extends Handler implements ViewParent, View oldFocus = mFocusedView; - mFocusedView = null; + if (DEBUG_INPUT_RESIZE) Log.v(TAG, "Clearing child focus"); + mFocusedView = mRealFocusedView = null; if (mView != null && !mView.hasFocus()) { // If a view gets the focus, the listener will be invoked from requestChildFocus() if (!mView.requestFocus(View.FOCUS_FORWARD)) { diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index a676234435a7a..ba40782072a9d 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -800,7 +800,7 @@ public final class InputMethodManager { try { if (DEBUG) Log.v(TAG, "START INPUT: " + view + " ic=" - + ic + " tba=" + tba); + + ic + " tba=" + tba + " initial=" + initial); InputBindResult res = mService.startInput(mClient, tba, initial, mCurMethod == null); if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res); @@ -848,6 +848,9 @@ public final class InputMethodManager { synchronized (mH) { if (DEBUG) Log.v(TAG, "focusIn: " + view); // Okay we have a new view that is being served. + if (mServedView != view) { + mCurrentTextBoxAttribute = null; + } mServedView = view; mCompletions = null; mServedConnecting = true; diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java index cae94c9366bb8..4f8e5e4fbcbeb 100644 --- a/core/java/android/webkit/CallbackProxy.java +++ b/core/java/android/webkit/CallbackProxy.java @@ -16,8 +16,10 @@ package android.webkit; +import android.app.AlertDialog; import android.content.ActivityNotFoundException; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; @@ -30,7 +32,14 @@ import android.os.SystemClock; import android.util.Config; import android.util.Log; import android.view.KeyEvent; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; +import com.android.internal.R; +import java.net.MalformedURLException; +import java.net.URL; import java.util.HashMap; /** @@ -376,12 +385,24 @@ class CallbackProxy extends Handler { case JS_ALERT: if (mWebChromeClient != null) { - JsResult res = (JsResult) msg.obj; + final JsResult res = (JsResult) msg.obj; String message = msg.getData().getString("message"); String url = msg.getData().getString("url"); if (!mWebChromeClient.onJsAlert(mWebView, url, message, - res)) { - res.handleDefault(); + res)) { + new AlertDialog.Builder(mContext) + .setTitle(getJsDialogTitle(url)) + .setMessage(message) + .setPositiveButton(R.string.ok, + new AlertDialog.OnClickListener() { + public void onClick( + DialogInterface dialog, + int which) { + res.confirm(); + } + }) + .setCancelable(false) + .show(); } res.setReady(); } @@ -389,12 +410,29 @@ class CallbackProxy extends Handler { case JS_CONFIRM: if (mWebChromeClient != null) { - JsResult res = (JsResult) msg.obj; + final JsResult res = (JsResult) msg.obj; String message = msg.getData().getString("message"); String url = msg.getData().getString("url"); if (!mWebChromeClient.onJsConfirm(mWebView, url, message, - res)) { - res.handleDefault(); + res)) { + new AlertDialog.Builder(mContext) + .setTitle(getJsDialogTitle(url)) + .setMessage(message) + .setPositiveButton(R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick( + DialogInterface dialog, + int which) { + res.confirm(); + }}) + .setNegativeButton(R.string.cancel, + new DialogInterface.OnClickListener() { + public void onClick( + DialogInterface dialog, + int which) { + res.cancel(); + }}) + .show(); } // Tell the JsResult that it is ready for client // interaction. @@ -404,13 +442,49 @@ class CallbackProxy extends Handler { case JS_PROMPT: if (mWebChromeClient != null) { - JsPromptResult res = (JsPromptResult) msg.obj; + final JsPromptResult res = (JsPromptResult) msg.obj; String message = msg.getData().getString("message"); String defaultVal = msg.getData().getString("default"); String url = msg.getData().getString("url"); if (!mWebChromeClient.onJsPrompt(mWebView, url, message, defaultVal, res)) { - res.handleDefault(); + final LayoutInflater factory = LayoutInflater + .from(mContext); + final View view = factory.inflate(R.layout.js_prompt, + null); + final EditText v = (EditText) view + .findViewById(R.id.value); + v.setText(defaultVal); + ((TextView) view.findViewById(R.id.message)) + .setText(message); + new AlertDialog.Builder(mContext) + .setTitle(getJsDialogTitle(url)) + .setView(view) + .setPositiveButton(R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick( + DialogInterface dialog, + int whichButton) { + res.confirm(v.getText() + .toString()); + } + }) + .setNegativeButton(R.string.cancel, + new DialogInterface.OnClickListener() { + public void onClick( + DialogInterface dialog, + int whichButton) { + res.cancel(); + } + }) + .setOnCancelListener( + new DialogInterface.OnCancelListener() { + public void onCancel( + DialogInterface dialog) { + res.cancel(); + } + }) + .show(); } // Tell the JsResult that it is ready for client // interaction. @@ -420,12 +494,32 @@ class CallbackProxy extends Handler { case JS_UNLOAD: if (mWebChromeClient != null) { - JsResult res = (JsResult) msg.obj; + final JsResult res = (JsResult) msg.obj; String message = msg.getData().getString("message"); String url = msg.getData().getString("url"); if (!mWebChromeClient.onJsBeforeUnload(mWebView, url, - message, res)) { - res.handleDefault(); + message, res)) { + final String m = mContext.getString( + R.string.js_dialog_before_unload, message); + new AlertDialog.Builder(mContext) + .setMessage(m) + .setPositiveButton(R.string.ok, + new DialogInterface.OnClickListener() { + public void onClick( + DialogInterface dialog, + int which) { + res.confirm(); + } + }) + .setNegativeButton(R.string.cancel, + new DialogInterface.OnClickListener() { + public void onClick( + DialogInterface dialog, + int which) { + res.cancel(); + } + }) + .show(); } res.setReady(); } @@ -468,6 +562,24 @@ class CallbackProxy extends Handler { sendMessage(obtainMessage(SWITCH_OUT_HISTORY)); } + private String getJsDialogTitle(String url) { + String title = url; + if (URLUtil.isDataUrl(url)) { + // For data: urls, we just display 'JavaScript' similar to Safari. + title = mContext.getString(R.string.js_dialog_title_default); + } else { + try { + URL aUrl = new URL(url); + // For example: "The page at 'http://www.mit.edu' says:" + title = mContext.getString(R.string.js_dialog_title, + aUrl.getProtocol() + "://" + aUrl.getHost()); + } catch (MalformedURLException ex) { + // do nothing. just use the url as the title + } + } + return title; + } + //-------------------------------------------------------------------------- // WebViewClient functions. // NOTE: shouldOverrideKeyEvent is never called from the WebCore thread so diff --git a/core/java/android/webkit/TextDialog.java b/core/java/android/webkit/TextDialog.java index 30b519a3e9770..b7b40b17059a5 100644 --- a/core/java/android/webkit/TextDialog.java +++ b/core/java/android/webkit/TextDialog.java @@ -38,13 +38,20 @@ import android.text.method.MovementMethod; import android.text.method.PasswordTransformationMethod; import android.text.method.TextKeyListener; import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; import android.view.View.MeasureSpec; import android.view.ViewConfiguration; import android.widget.AbsoluteLayout.LayoutParams; +import android.widget.ArrayAdapter; import android.widget.AutoCompleteTextView; +import android.widget.TextView; + +import java.util.ArrayList; /** * TextDialog is a specialized version of EditText used by WebView @@ -281,7 +288,7 @@ import android.widget.AutoCompleteTextView; } return false; } - + /** * Determine whether this TextDialog currently represents the node * represented by ptr. @@ -406,6 +413,9 @@ import android.widget.AutoCompleteTextView; * focus to the host. */ /* package */ void remove() { + // hide the soft keyboard when the edit text is out of focus + InputMethodManager.getInstance(mContext).hideSoftInputFromWindow( + getWindowToken(), 0); mHandler.removeMessages(LONGPRESS); mWebView.removeView(this); mWebView.requestFocus(); @@ -427,6 +437,43 @@ import android.widget.AutoCompleteTextView; mWebView.passToJavaScript(getText().toString(), event); } + public void setAdapterCustom(AutoCompleteAdapter adapter) { + adapter.setTextView(this); + super.setAdapter(adapter); + } + + /** + * This is a special version of ArrayAdapter which changes its text size + * to match the text size of its host TextView. + */ + public static class AutoCompleteAdapter extends ArrayAdapter { + private TextView mTextView; + + public AutoCompleteAdapter(Context context, ArrayList entries) { + super(context, com.android.internal.R.layout + .search_dropdown_item_1line, entries); + } + + /** + * {@inheritDoc} + */ + public View getView(int position, View convertView, ViewGroup parent) { + TextView tv = + (TextView) super.getView(position, convertView, parent); + if (tv != null && mTextView != null) { + tv.setTextSize(mTextView.getTextSize()); + } + return tv; + } + + /** + * Set the TextView so we can match its text size. + */ + private void setTextView(TextView tv) { + mTextView = tv; + } + } + /** * Determine whether to use the system-wide password disguising method, * or to use none. diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index f00238d79eb44..9cfc6225a3d75 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -57,6 +57,7 @@ import android.view.ViewGroup; import android.view.ViewParent; import android.view.ViewTreeObserver; import android.view.inputmethod.InputMethodManager; +import android.webkit.TextDialog.AutoCompleteAdapter; import android.webkit.WebViewCore.EventHub; import android.widget.AbsoluteLayout; import android.widget.AdapterView; @@ -2819,10 +2820,8 @@ public class WebView extends AbsoluteLayout public void run() { ArrayList pastEntries = mDatabase.getFormData(mUrl, mName); if (pastEntries.size() > 0) { - ArrayAdapter adapter = new ArrayAdapter( - mContext, com.android.internal.R.layout - .search_dropdown_item_1line, - pastEntries); + AutoCompleteAdapter adapter = new + AutoCompleteAdapter(mContext, pastEntries); ((HashMap) mUpdateMessage.obj).put("adapter", adapter); mUpdateMessage.sendToTarget(); } @@ -4458,9 +4457,9 @@ public class WebView extends AbsoluteLayout case UPDATE_TEXT_ENTRY_ADAPTER: HashMap data = (HashMap) msg.obj; if (mTextEntry.isSameTextField(msg.arg1)) { - ArrayAdapter adapter = - (ArrayAdapter) data.get("adapter"); - mTextEntry.setAdapter(adapter); + AutoCompleteAdapter adapter = + (AutoCompleteAdapter) data.get("adapter"); + mTextEntry.setAdapterCustom(adapter); } break; case UPDATE_CLIPBOARD: diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java index 024b663d83083..7d52901755787 100644 --- a/core/java/android/widget/AutoCompleteTextView.java +++ b/core/java/android/widget/AutoCompleteTextView.java @@ -413,7 +413,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe // when the selection is at the bottom, we block the // event to avoid going to the next focusable widget Adapter adapter = mDropDownList.getAdapter(); - if (curIndex == adapter.getCount() - 1) { + if (adapter != null && curIndex == adapter.getCount() - 1) { return true; } } diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java index 6c0c164e2e595..f2cec92e708e4 100644 --- a/core/java/android/widget/MediaController.java +++ b/core/java/android/widget/MediaController.java @@ -393,6 +393,12 @@ public class MediaController extends FrameLayout { doPauseResume(); show(sDefaultTimeout); return true; + } else if (keyCode == KeyEvent.KEYCODE_STOP) { + if (mPlayer.isPlaying()) { + mPlayer.pause(); + updatePausePlay(); + } + return true; } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP) { // don't show the controls for volume adjustment diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java index df4015670bd6d..1227afd9c186c 100644 --- a/core/java/android/widget/VideoView.java +++ b/core/java/android/widget/VideoView.java @@ -447,7 +447,8 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { keyCode != KeyEvent.KEYCODE_ENDCALL && mMediaPlayer != null && mMediaController != null) { - if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK) { + if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK || + keyCode == KeyEvent.KEYCODE_PLAYPAUSE) { if (mMediaPlayer.isPlaying()) { pause(); mMediaController.show(); @@ -456,6 +457,10 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { mMediaController.hide(); } return true; + } else if (keyCode == KeyEvent.KEYCODE_STOP + && mMediaPlayer.isPlaying()) { + pause(); + mMediaController.show(); } else { toggleMediaControlsVisiblity(); } diff --git a/core/java/com/android/internal/gadget/IGadgetService.aidl b/core/java/com/android/internal/gadget/IGadgetService.aidl new file mode 100644 index 0000000000000..0117d1df42390 --- /dev/null +++ b/core/java/com/android/internal/gadget/IGadgetService.aidl @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2008 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.internal.gadget; + +import android.content.ComponentName; +import android.gadget.GadgetInfo; + +/** {@hide} */ +interface IGadgetService { + int allocateGadgetId(String hostPackage); + void deleteGadgetId(int gadgetId); + void bindGadgetId(int gadgetId, in ComponentName provider); + GadgetInfo getGadgetInfo(int gadgetId); +} diff --git a/core/java/com/android/internal/gadget/package.html b/core/java/com/android/internal/gadget/package.html new file mode 100644 index 0000000000000..db6f78bbf6283 --- /dev/null +++ b/core/java/com/android/internal/gadget/package.html @@ -0,0 +1,3 @@ + +{@hide} + \ No newline at end of file diff --git a/core/java/com/android/internal/os/HandlerCaller.java b/core/java/com/android/internal/os/HandlerCaller.java index a7081e323f173..1ec74a1b9d38b 100644 --- a/core/java/com/android/internal/os/HandlerCaller.java +++ b/core/java/com/android/internal/os/HandlerCaller.java @@ -116,7 +116,7 @@ public class HandlerCaller { } public Message obtainMessageI(int what, int arg1) { - return mH.obtainMessage(what, arg1); + return mH.obtainMessage(what, arg1, 0); } public Message obtainMessageIO(int what, int arg1, Object arg2) { diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java index 3b11a649e3113..558a4c30bca11 100644 --- a/core/java/com/android/internal/view/menu/IconMenuItemView.java +++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java @@ -143,7 +143,7 @@ public final class IconMenuItemView extends TextView implements MenuView.ItemVie void setCaptionMode(boolean shortcut) { - mShortcutCaptionMode = shortcut; + mShortcutCaptionMode = shortcut && (mItemData.shouldShowShortcut()); /* * If there is no item model, don't do any of the below (for example, @@ -155,7 +155,7 @@ public final class IconMenuItemView extends TextView implements MenuView.ItemVie CharSequence text = mItemData.getTitleForItemView(this); - if (shortcut) { + if (mShortcutCaptionMode) { if (mShortcutCaption == null) { mShortcutCaption = mItemData.getShortcutLabel(); diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java index e5d57ad782c52..32513cd5d2ded 100644 --- a/core/java/com/android/internal/view/menu/ListMenuItemView.java +++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java @@ -171,9 +171,13 @@ public class ListMenuItemView extends LinearLayout implements MenuView.ItemView } public void setShortcut(boolean showShortcut, char shortcutKey) { - mShortcutView.setText(mItemData.getShortcutLabel()); + final int newVisibility = (showShortcut && mItemData.shouldShowShortcut()) + ? VISIBLE : GONE; + + if (newVisibility == VISIBLE) { + mShortcutView.setText(mItemData.getShortcutLabel()); + } - final int newVisibility = showShortcut ? VISIBLE : GONE; if (mShortcutView.getVisibility() != newVisibility) { mShortcutView.setVisibility(newVisibility); } diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java index 298760265141e..cbc4e9f950a6a 100644 --- a/core/java/com/android/internal/view/menu/MenuBuilder.java +++ b/core/java/com/android/internal/view/menu/MenuBuilder.java @@ -22,6 +22,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -279,7 +280,8 @@ public class MenuBuilder implements Menu { mVisibleItems = new ArrayList(); mIsVisibleItemsStale = true; - mShortcutsVisible = true; + mShortcutsVisible = + (mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS); } public void setCallback(Callback callback) { @@ -687,7 +689,8 @@ public class MenuBuilder implements Menu { } /** - * Sets whether the shortcuts should be visible on menus. + * Sets whether the shortcuts should be visible on menus. Devices without hardware + * key input will never make shortcuts visible even if this method is passed 'true'. * * @param shortcutsVisible Whether shortcuts should be visible (if true and a * menu item does not have a shortcut defined, that item will @@ -696,9 +699,11 @@ public class MenuBuilder implements Menu { public void setShortcutsVisible(boolean shortcutsVisible) { if (mShortcutsVisible == shortcutsVisible) return; - mShortcutsVisible = shortcutsVisible; + mShortcutsVisible = + (mResources.getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS) + && shortcutsVisible; - refreshShortcuts(shortcutsVisible, isQwertyMode()); + refreshShortcuts(mShortcutsVisible, isQwertyMode()); } /** diff --git a/core/java/com/android/internal/widget/NumberPicker.java b/core/java/com/android/internal/widget/NumberPicker.java index 5590f1a2c4e36..20ea6a6d28793 100644 --- a/core/java/com/android/internal/widget/NumberPicker.java +++ b/core/java/com/android/internal/widget/NumberPicker.java @@ -131,6 +131,7 @@ public class NumberPicker extends LinearLayout implements OnClickListener, mText = (TextView) findViewById(R.id.timepicker_input); mText.setOnFocusChangeListener(this); mText.setFilters(new InputFilter[] { mInputFilter }); + mText.setRawInputType(InputType.TYPE_CLASS_NUMBER); mSlideUpOutAnimation = new TranslateAnimation( Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp index e1ef459271901..a81f2520bcd44 100644 --- a/core/jni/android_hardware_Camera.cpp +++ b/core/jni/android_hardware_Camera.cpp @@ -70,6 +70,10 @@ sp get_native_camera(JNIEnv *env, jobject thiz) static void err_callback(status_t err, void *cookie) { JNIEnv *env = AndroidRuntime::getJNIEnv(); + if (env == NULL) { + LOGE("err_callback on dead VM"); + return; + } callback_cookie *c = (callback_cookie *)cookie; int error; @@ -176,6 +180,10 @@ static void android_hardware_Camera_setPreviewDisplay(JNIEnv *env, jobject thiz, static void preview_callback(const sp& mem, void *cookie) { JNIEnv *env = AndroidRuntime::getJNIEnv(); + if (env == NULL) { + LOGE("preview_callback on dead VM"); + return; + } callback_cookie *c = (callback_cookie *)cookie; int arg1 = 0, arg2 = 0; jobject obj = NULL; @@ -234,7 +242,7 @@ static bool android_hardware_Camera_previewEnabled(JNIEnv *env, jobject thiz) return c->previewEnabled(); } -static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject thiz, jboolean installed) +static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject thiz, jboolean installed, jboolean oneshot) { sp c = get_native_camera(env, thiz); if (c == 0) @@ -245,14 +253,22 @@ static void android_hardware_Camera_setHasPreviewCallback(JNIEnv *env, jobject t // each preview frame for nothing. callback_cookie *cookie = (callback_cookie *)env->GetIntField(thiz, fields.listener_context); - c->setFrameCallback(installed ? preview_callback : NULL, - cookie, - installed ? FRAME_CALLBACK_FLAG_CAMERA: FRAME_CALLBACK_FLAG_NOOP); + int callback_flag; + if (installed) { + callback_flag = oneshot ? FRAME_CALLBACK_FLAG_BARCODE_SCANNER : FRAME_CALLBACK_FLAG_CAMERA; + } else { + callback_flag = FRAME_CALLBACK_FLAG_NOOP; + } + c->setFrameCallback(installed ? preview_callback : NULL, cookie, callback_flag); } static void autofocus_callback_impl(bool success, void *cookie) { JNIEnv *env = AndroidRuntime::getJNIEnv(); + if (env == NULL) { + LOGE("autofocus_callback on dead VM"); + return; + } callback_cookie *c = (callback_cookie *)cookie; env->CallStaticVoidMethod(c->camera_class, fields.post_event, c->camera_ref, kAutoFocusCallback, @@ -276,6 +292,10 @@ static void android_hardware_Camera_autoFocus(JNIEnv *env, jobject thiz) static void jpeg_callback(const sp& mem, void *cookie) { JNIEnv *env = AndroidRuntime::getJNIEnv(); + if (env == NULL) { + LOGE("jpeg`_callback on dead VM"); + return; + } callback_cookie *c = (callback_cookie *)cookie; int arg1 = 0, arg2 = 0; jobject obj = NULL; @@ -319,6 +339,10 @@ static void jpeg_callback(const sp& mem, void *cookie) static void shutter_callback_impl(void *cookie) { JNIEnv *env = AndroidRuntime::getJNIEnv(); + if (env == NULL) { + LOGE("shutter_callback on dead VM"); + return; + } callback_cookie *c = (callback_cookie *)cookie; env->CallStaticVoidMethod(c->camera_class, fields.post_event, c->camera_ref, kShutterCallback, 0, 0, NULL); @@ -328,6 +352,10 @@ static void raw_callback(const sp& mem __attribute__((unused)), void *cookie) { JNIEnv *env = AndroidRuntime::getJNIEnv(); + if (env == NULL) { + LOGE("raw_callback on dead VM"); + return; + } callback_cookie *c = (callback_cookie *)cookie; env->CallStaticVoidMethod(c->camera_class, fields.post_event, c->camera_ref, kRawCallback, 0, 0, NULL); @@ -404,7 +432,7 @@ static jint android_hardware_Camera_unlock(JNIEnv *env, jobject thiz) sp c = get_native_camera(env, thiz); if (c == 0) return INVALID_OPERATION; - return (jint) c->lock(); + return (jint) c->unlock(); } //------------------------------------------------- @@ -429,7 +457,7 @@ static JNINativeMethod camMethods[] = { "()Z", (void *)android_hardware_Camera_previewEnabled }, { "setHasPreviewCallback", - "(Z)V", + "(ZZ)V", (void *)android_hardware_Camera_setHasPreviewCallback }, { "native_autoFocus", "()V", diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 29c1f527b426d..ded909f0c3ca6 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -156,6 +156,24 @@ android:label="@string/permlab_writeCalendar" android:description="@string/permdesc_writeCalendar" /> + + + + + + diff --git a/core/res/res/drawable/btn_check_off_longpress.png b/core/res/res/drawable/btn_check_off_longpress.png deleted file mode 100644 index c81e119960ca7fa5fe5a69b9f81f9312eaa5df7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1633 zcmV-n2A=teP)9EZ)p^046^&VLd17wo3^63q}=lg>-9C%#=d`P!j_v&&<-p&4AV$2^Q& zm)k%5bn&}qj-U7t4X0u2bv>e#@Yobi&t6^s;O&{|;RW(I`A~ZgCXFeyv3dLI!qV&S zpy6w(%MJy1?DrB*A)>fTe5{5_5?;pL^k50o4+0@zC<%5_j){$;H>+ zgE6j>m{ZK%Qv5i^CdTx<=a#_ZN+^$d1IFZ13R6kUDduhmrhA?R9y{=ukHsP#ye6MI z>#4;U9$FPOTot`N7zY@)rN=xe{=JdD?QlACcAH8ioAQ$xI=DOvhart(DT5i>f@x8Y zg<#!z$h*f&;o$)4=QG=sNN9kH({9lqqdY_D#BS7MT01Z`^cd%kAC*m^?$3w6UD~0c z0Y;M(ad0RUk8yZw0Hc)PF)JKTZ4U;IaS7*x)x_`pFR<0~JJKOj`4lP4rb^jG`Wm84 zW{@0f3%{9Y?*@#URMQ!cK-@prx$}2q*ZgFXVwyvyWl^P)p!vl^lW^IoTetqbr-K)H01K-5qzt#b6f=!$=^@}V#yuKjXz4sWGaBNf@*~~jNjZzTDwxaDr@|k z9JlD&W(*#)NY|OX*L0G>A~!0$jlLC=lOCU^;gLL`&O&R2`mKsJZd&)w-RLpZzeEW< ztKyp?H(O!TC{Bu49@q7&&qfnj$wK;b_z3NrKLVlu4Q>4+e`8ULjPK9Ix>-uaZw@Dn z44|qiJeNTDYvl5vU&I^$m(3)^evCu~>{Qle&^iQd~+w2ghSUih; zPq1PMVP&MW?C2wuOl6Qn*JQMb1WFCpN@>)MTLtT&F&13F>X(UCO_er2>Of0r)K;D} zA@;Gcd2-Cl*kX;kzAV&g!_wF0Vx9L&CYyNVfuZ#wwxxn`05#SC<;G?q_G^LI^)8Dd zRU-Ivb^s$56Hl8yl-KzU!eIIqsk)A8VO^Fo4Ha^S#{nT}p`KVrup3wYG)oI}@f4H& z+*--grUY}HonWF^=klAe>QfR!b7 z!184)Fw_wA3hc%APrmfnQ^)4g4=v>qdkGeL%d)ul$){&`-Z=5uuW0!k_7PYLt-!)p zP{(0MVau?Y9=?Y926hUzB3?z+u`~gb!3N90vaoay!9>;guPBlm-;c5W>-0WYAFL17 f2kXu8p8x{@aZ=>|2m##U00000NkvXXu0mjfY_cfT diff --git a/core/res/res/drawable/btn_check_on_longpress.png b/core/res/res/drawable/btn_check_on_longpress.png deleted file mode 100644 index 367760b9f1acf178aeafc31798bee40b10214ec5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1661 zcmV-@27>vCP)xWk%hY zT0IdarUcy<9*pTK_?&$1jN+$OIib=$(MSvsPeMQ$C=3`AOUX?IpOep>4a{vAQR0c2 z9+Ozi@q&@&S8hFJ7{j2aifXNjJ3E+8V0uh=%n;%q9_jzvuVM3nL%0y`!xFy_TUIP2 zhfx}(r8H;A3g&Wp%mT~LL&hCmvRas+R_xu6pyxU;4frY4gH`A6N1#S=dd!s#Otn0w z>v0*CX`$}Uhns&mj9?`}%`o?xVuFnq(Lav&C=xFR=CdkKj{u z%e2iGi}+S0=3q(P6vU$^$XOZ`mJgV&!Pc4XfVg|G^~^Q< zt5B}Y6O4OHOGc(OarjmY-*)sOFv){}-;>o-8@}vBt9nU7@$3{P>jQTB9>*+SIiiCd zG=7AlQl-&#ku`FGx%isvDPTb7xqhr`>qJk{ZMp&8nKKt_8t+T%wT)k$M62tHgyJ>I zEeW=TEk$#~bb>ktJ$}OsUX`$PzGdbUl^P_R4YsZ$h@OBZH;t?0k?y~!9$0{u`9&$6 zUp#mkdtALX)Sz6#=3DjHy!0W&v{NMbi;i7MCE@E<@aOVaTtuX}nqc8_iqIHp`WWu6>j(>G_Z$9>&~(s)*-svtB0?>4O@v0p}P@Z^vbN9xrX3`NbuW9I(I zBhpH+FPBcjYyCYk+&wnj#xs8)JP<%IbQyb#Z`e?AsVVQ}V(h42i82yVPb7JWE$WCrwt#mummOGn(JQdYHR_o zfaABjMC92Zj%#v!%kuFUW4Hs5sp8sDU4qxW(}af5Z^CIZUvaVTs(S)sN*Q7UL9@S_ z?3;46JjGbP9%E*G>HMdp{IxAJy?8~NDKmP+Oriw3ZTxa7WhzNmK@n{>fZbO}BW2tq zSPqXdvqOrTtpT~I!d{v)7LSsaa82s!g=iC=oHq|~?KEw%k(76trB$SkY0t%S@0CnE z(j5ne%?JI|s>6$o<99AIEY{In^djND%kR!^r+?lP(t zxM6@lR1HENQ@a z>>w0)kzX=O(d_AS2kwr_K?u5wH=k5wPKF{|PVvEcL3z=Ftkd00000NkvXX Hu0mjf@c0^V diff --git a/core/res/res/drawable/emo_im_angel.png b/core/res/res/drawable/emo_im_angel.png new file mode 100644 index 0000000000000000000000000000000000000000..c34dfa69b4b1becdc3e8c107d54b276b110d9a8f GIT binary patch literal 3592 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 literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/emo_im_crying.png b/core/res/res/drawable/emo_im_crying.png new file mode 100644 index 0000000000000000000000000000000000000000..1cafdb32613c890dbb4f7317ff98cf3711514550 GIT binary patch literal 3558 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 literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/emo_im_embarrassed.png b/core/res/res/drawable/emo_im_embarrassed.png new file mode 100644 index 0000000000000000000000000000000000000000..e4db9634f83afd35404fc577ab0764a7005ea229 GIT binary patch literal 3619 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 ZYXJRYNqc9=?u7sV002ovPDHLkV1jnTzBvE@ literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/emo_im_happy.png b/core/res/res/drawable/emo_im_happy.png new file mode 100644 index 0000000000000000000000000000000000000000..b86602ae7e996b160558e88cce1cb8a6b87f4e06 GIT binary patch literal 3591 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 SPZf;-00004Gf) literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/emo_im_laughing.png b/core/res/res/drawable/emo_im_laughing.png new file mode 100644 index 0000000000000000000000000000000000000000..980bf28118b738ddfda089b920161265847a1942 GIT binary patch literal 3624 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 literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/emo_im_money_mouth.png b/core/res/res/drawable/emo_im_money_mouth.png new file mode 100644 index 0000000000000000000000000000000000000000..08c53fd690d00bdbde5c7c8f89826449bb8ff199 GIT binary patch literal 3649 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 TH1iCn00000NkvXXu0mjfH-h7( literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/emo_im_sad.png b/core/res/res/drawable/emo_im_sad.png new file mode 100644 index 0000000000000000000000000000000000000000..31c08d06d522bb87bf8f6e3592cae9c4be49452d GIT binary patch literal 3572 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 Q@&Et;07*qoM6N<$f>?!)(*OVf literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/emo_im_tongue_sticking_out.png b/core/res/res/drawable/emo_im_tongue_sticking_out.png new file mode 100644 index 0000000000000000000000000000000000000000..6f0f47b0e1a6115619c8b16f8ca1997d286e8a58 GIT binary patch literal 3653 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 N002ovPDHLkV1j&|w`l+X literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/emo_im_yelling.png b/core/res/res/drawable/emo_im_yelling.png new file mode 100644 index 0000000000000000000000000000000000000000..c3c8612bd102058c07ff7b3a2ae425c74bd03aaf GIT binary patch literal 3575 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 literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/ic_menu_account_list.png b/core/res/res/drawable/ic_menu_account_list.png new file mode 100644 index 0000000000000000000000000000000000000000..f0945b254fa246c3ad552a3fa2ea02c53be187f9 GIT binary patch literal 2394 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 M07*qoM6N<$f|SyB%m4rY literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/ic_menu_allfriends.png b/core/res/res/drawable/ic_menu_allfriends.png new file mode 100755 index 0000000000000000000000000000000000000000..a5bd331f252f6e4f2b4132acf88c38f03376a6e1 GIT binary patch literal 2257 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 M07*qoM6N<$g28)?i~s-t literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/ic_menu_attachment.png b/core/res/res/drawable/ic_menu_attachment.png new file mode 100644 index 0000000000000000000000000000000000000000..89d626f6cd6844fa176a844b47d0c73b169d9473 GIT binary patch literal 2247 zcmV;&2srnNP)_VMx)H#3KLCX3JoaU`eH85mb7~jXYCjcHYDj@tlgliSJi907isJlUEMXQm5yeS zH!`~eL-KAj8zhA`QNdXRZm2R^A~6Eiuv48|CEEA*d!9Q>uB`fxT)JU}LuW}ReZIfv z`}^};n#$#}_+NfBZ3x&9upwYw1vKHfOC5B62ghyoT>i2PAmB|nG#t7T@hOgvam?c= zeVGM#@S*g(>8}pII{e3CskmJa>hFx48u>n6{|}B&Dn2XJs;qcr)EI6;Sg zaWmdG#@`xmz3{gSKg8cGz%2S~CgV7z)f8niL%MsBi0kz>Bz=sul(4B6N zwfDaA>MK9X-^_Pfh9%4vlRcmXHBp!=h-@}XMw&i+=Cu82km_^jv2HjYyb zze~awZWcNXTfVM^G+qIEAjyS0=Zehx8R5DviRg-cE1La05o;AtS#6x-FUy2w&ja2x zIKqD93xz_bZ3EoUgdO7NS);|6aA({dNbpE;Zjp!{UWpHsol3PttVKXgcx#)*(e>eX zEx>c+CAcs{rm!8mC$=N@k9degW|3aoxWy%eoeQDB4AWbxmh$Ic*L-N5;m-4yi_1lQqyV z+W;PRU_c}#+h**ov3UN&e5W0@J!qkabgD}I9glR3R@D7lPOEc$XKd$>a6V0WVQ3Ic zb`#njymq(h8EY0$4L>9!Pfdy{3fTrfJ`IrG;bL8a6&sCBJQ*Wf=xm-@*b8IE8M57cZ zZ+R^%P#+$?C(l##&WxUkBLNxSv`twmE8qu?4V-XGZUmMQY`c)L7vI&4<11)zKfau~ zoX|AQANBA(lgegyR=WaK@JEM^rVtk&o}~gl|~@z~2l%I5cpZv(15}s`H=)+mZ(3n%0iHZR zRc#wS58ENJwfhxeAAd^>i2 z?7^#PL_Tc#;0$5d{T-bh6DXC(i*9w~3EsKS=^Z~?0k4KSdLPG%;Fl8Md4CJM`4m?X zbXck=0JwqZb))qcGEf4>vqrcev_l`u7T_BMQ-3n{;Eb>9d-H!e7%*vfjVcdl-tIUCwOmVWOtrz z`+A#%PfOcyE;P&Wg5f(?2VYkJHXaXo%|z{*Ce=twKN3JrT*B*Hsblhv$}Mz4r0{Zr znjFM0MBam^_nPHk$F^Amd_4j5I!Bi+0x+Z1ct`DwsI50)MjwQqpa66PDoLTY#tXOYl|*&CD_z0$(qQNyJvN2JcskMS%ppQgK_5R^k>a(%-Y! zvJYc;JAeW0J4);gY$;zqcm5ogS=|7%q51%3e89he?@BfTzFr?_V&CH*-SSYAVR_NP z6CynR0gjh&{#(`jw)DN&w-063_dJzS-spt13BaFf6#VB;qd^&KH|W-Sw_LFr0d?Gs z@!%Vow1N*A{_KOlC%T^KdJ3N@Gzz|+0Dtzzc9HMdsD0@@i*rRaz0IgJ_VCH!gSmWe zKUFWk5~;{5_?e|P=ZzG=H(9CcQkf(R(Om+}>yID(_0d1mXzd9YcyVB7_QUKqi*v>8 z`I~vJNEMT)?B0Oy{z2tl-SBI8-a{6m8%|+J`Esw6g_n>hCvtn(Oc#JM|HKc=Z^;nSBO;GcB6L`B;hIZBQE@1&IoXsW0% znp%;~73H#AQATg8Qd)VeJNR-p^?{0V8K`j^=FTD^UkLQZf3t1~*bwl4B;daS3;=ze VC&PXuL$m+@002ovPDHLkV1lBfm~{0TE9YSf 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 a00RK$Hxe$Tvwq_M0000oiv^<=e_-KK`a2 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 DKY@Yn literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/ic_menu_clear_playlist.png b/core/res/res/drawable/ic_menu_clear_playlist.png new file mode 100644 index 0000000000000000000000000000000000000000..750db627439064dd4290233b9181fe61e5804dac GIT binary patch literal 2281 zcmV}UR&R$y9z59N98aD} z)@U`_9J($^($qzF__}K9bZTytMSIGT1EfF&grX4P!qKoDn`x59Bt@e2{EA~F6fY3p)#*gI+A-5J(iX!EDU~t4sW{7K5r2vJ;Si^Z&1{ke+@r4(o zoyR*{aD1)jniXFWf3kj6{eMZp#tn_H0GSq*p^$yo`fBT=fKpQ!s3aKW);G_Y_sEjG zm_w<+Y#Pav$-8jMxIVy*zaG{dNnxg<{36pg8~)L{%CfiA^<+qTWr8nv>Vh0IZE6h{x}R3QzlK(1Bo zj2(ov1`2$|?F5y6_blRoSB=AfKe+jM)?AfH%RUpQG4@sWrm=y}y$xt|SaZfkqG>qrOu>Ck-oaxx+k|jvo#@g3j@h1Cd)J>tHn#)S4+l zh4_91)Z-p92#oLrEl%O5Ru?hw&R`7+Wdexo(+|*^;b{14Zhe^z zx0?R(j|*dx8(V(FvkX2{ONlDWG9_g$;fR9r5?Q#H?dI4=h?+=GI4C#z<)ZbJ_EYzJiS z7x(yJMANj*d>A48x{_T1DA2QY^VUV8wp31XV{2eE4~!K;IbGL#dB00mfFQI#;})XE z^^Mz--N{zK&w2^;6Wj=)*cn8$^ zU9eAb@nCFatQF^baX!$xt95bmRB|(iUcr^XPWO6x+pF^X0O$7&>l!`$?D*RRpUdfe%2zBSL|paw{+%7b5QjI*xSws{OO} z_lO>trpb(6gYciOUx08&0EZdi{q;y#!ukLyih`GKCj(MXY+39<_T$hNJ z`NxhQ`x}yZDF_y`O`F53Yf}m{-sF=aih3Yi8~!~iZ_0z=We=apbY$+YGJ%7K5B|nF zXRU(em*PC=+0!(j#34Xy8z8tt2=4CAT@m3Yvp4E?Q|^vjmFMRrpQn3ralU`NM*OEx z;4+>xN^6)KvGqQ5r3Ig=0@J?}Pb)C3!2j9je*z2uNMY`UCs%3(00000NkvXXu0mjf DfyGA8 literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/ic_menu_compose.png b/core/res/res/drawable/ic_menu_compose.png new file mode 100644 index 0000000000000000000000000000000000000000..1b4733e422d93357b61f4bfb24a4cb202b58155a GIT binary patch literal 2014 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 e2MYX4fB^vBkhNRp|nw| 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 literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/ic_menu_play_clip.png b/core/res/res/drawable/ic_menu_play_clip.png new file mode 100644 index 0000000000000000000000000000000000000000..466994744c9d60fdcc1697daa63b37879fda80ae GIT binary patch literal 1471 zcmV;w1wi_VP)&$0kCR)F$66bXvR#8^;FR{mw@m1j`^dR)5q z%e@1sA5vcyiiM8}RU+lpUUmG!`3v8}=?at*6SA?JLi`9o&&#JjKRsDkEez_aP9#Ml zg(n44EEchC788lY$jMJn{tC~nvKFy+3#)np5T6$^zhz#Vx-s>;EXzdGGzyd`h@`k$ zB)MFUn5!mHyVc1PADx(py&YSEcb-C7WARbhO99Aw*VK1YgV|hmTGw}g z-Fi>K#-rheEsrIS1w)| zg125q99gHZFDxOx1UQ~HX$M1Uglwu=D`9UH8;B82)_NX1d@wrv8DKTJrxAJZs-I88_y4>=54It?kiAUWP@T;Sos#pz;@{H$4)EIH=TE|x9XN@YXDYV%YQF#h1GL@>`w%{X~fZ zR`+eJW@cyJWFqP!J8<04U)OOua`<-oc6w}l>|HkaMZ#?XK9GIX+Z}ta zAy%5Ak@!FygS;zqKQqpa-rH`1U++_vx#ODPtyA;Id~detnqVL6x=xm#Ecb+l5VGoa zn*m#3Q}?^WHSEQl|5Fsjd92d30GI!rrV!267WY3Qjf+KYh1VQHTaF1~*Hy!Dy|DsQ z^mA-Iu^x^9i)_hn7_~Etm7)@XRo|px7}sHZc*K^cAqcQ)=QrM|1s{w-YG-7|Ngwn) zX&9le8gCd`xcv{ewyuPWkS73Zf-s2J5f@lv!vMAjgW0vjdx^VTQo#2zG?0K&nXSO; zP4ss1I(Qrn2VC;1tWG44CcSByK#72cVxXao1t{RMqD8e?BW6qh=YM%J7=cqU4I$)R z6Z17odR31F$@V%JkDSAl;cD!yn3wa0b4b1gIFqtcCm361Mt4dsR{V7wKk*ue%c82P z*OEt)4RIdMRKiKAl-U4Zt{zhn<*EqUE!qK^hiUV~v7^VPnc)p_-n0N`D!~V{ixTrX zJr-y`PB{l$W{-b({2LaaPdURwO*z&RfL_`F<117I>X$@6Nj zy2LnNYh|v~kAQWf*Z322peO?7>(xa*CbT4lF50m_hXDOL@lIl^ByY>|qkfXRG&?PbXFRCwC#Sx;yjRT!WBXJ^`s&X5FV z)(v#PCTt|=78=@m>BWN!xfDFa3Poen2qHr3snR6XoFw>%97=1wB|)VT39g4iEr?O1 zI6ZZXJ**&Ra)``m*32ZC&H8;aZ#FNRNxQR|jS1{*KHlWb?9A`?{d?c{Hc~E^nf-i3 zngp5zngl{85CMr2!E=1UI+5~zAP@t20)z#LgV-Pz$SO!_uM>z6@K0WR`{HG7QF}{l z6DKA#TZDP2qe4-WTcvBgAD6PJTH# zB(fr}q!mVJ5%}CpZV2be^~hc&;A;P#`n0iV^b3N(uq?~S9WtXA^?sahgcYKpYkz8T z5YBk9U33T#BK*ynn}dz8LNsLGPonlEL2|%z@WBJgSVar1kPO=jVLb@7%7O2nceF2q z_TwyL!Usv96>uJ6;XK|)?%y*6q9k>;RJ0G^J%~sG54qiq1-y^kAN{`xM5smU(AfK9 zufoW4?cB!lMF}f7r1H3Gx2J`-7q&G6E~O7N|N{ z_=vp71Y#sppqUTexPBvJ6b(@;XvYo9 zkO525w9QTc!y_nA6=zrk(uU_nh*$c^+_ZL`OvM{woYN^M@fD@c@O74Ynz)gh-&K=|2CNlI$&wC)Z zJ;$I%vbLL(WLtL5l@7%vMef1pnM-Exqk`R!0Q#DJwCCt0F!PvT3$8Y7*3q&R-_Yik z!w!}~D#1?N5Z{B=b>7Fi78RcnFHtd2QxHcZxHJ=ZEO34cMr*V2*sTEekL$cN|ivLx3GzSfp75)y+@*TYI^E*eNi8V6?&s^t8;`E7r~F7 ze);t0SXu-DAG8`Rk(F@y#IX~%G);3gXtO&S4Z~p4ne;7EG6ddw30h7&m16F@T<3zZ z;MOu;X;9~=>pC;{!(1m-g*LPwa7t*_&7`PwpmxIAotLx{C7J#=xU#dX;Gxp|d*#pn2)65Llzepyvsj9fb~oQBn#cbx6+twD!3*t}>ERoLBF`bL;4lqe1=u_V>4Y zX#e$qIbh&V7G%up^XXK2bl|mt=j6lksN5#c<2=W46_WIKF(b|WG}lv49K?gVPvMWk z@k#?j4g`h^5|ji>(AZCBGMTH&VFecoJNshxYT@_7H>#=*u?E`@{?0SS4gdFg2tzZT zh2dNBo>IdIU{8#l8EQ>Th)x{?;FrWUar)%3lh>q_^e0)AydE|NWR^jOfygx=GRQ8n z{gBCcEJvWfcH#iq%C1IR0FN>RToU(qaH9%$AfWu6Rnp4GnddWks`;jO5xm`n6+&bL z{QZl3KL3tcH2bg|!Nm;7$o2eo5QG2%T2+oHy3{5yTnl$6olbuMz#kCc7RfEu+aG0W z?+1yj!gqcJc@v0yQg~Q+4-|0<2pH7&8}bW{w+qLSu}rkRLS9^|QG?!&UV?1j93XS6 zWTPukJrsmMgxZaZRB5)JpN&F!Uh`+xCV?h_eNNy%0R{lFV>^m2d5NO{0000|=%IO(d;U@*-^> zgkA~711q@$Yj>g1-I__x@0X`qANB8K*&@atD74WDNIL)-VpIou z_|lh`hL^7_&$#Pu+2daE?@$LrGuF(Ud3AJr^upu|lNIRt704%GjWhrx^9GQ4=Cw0# z*6!9`#us+MW>(%}x~}gi^FH^P=Xk8{)|uyf%pSBqng3vZ4qmxHUL1%x0CMN8QzuS+ z>EIxuhy%_QDtn)4i-ShW#J%K?g=Ka7S9?yb9&b3Jw9t*=kc6{gk#J>Q*4^+ zy2p_hG9K9^0EGH1Ut6BBa#r5nYl~giH60Yu69cd|#PJB25(f~Ux$=$&ed2$pEyv5Y zV4mib^QvPCg#t58Gk;^{#tf-+Us3>jV9~Nvnb1nm!s=pC&nnQQ??X@$D80jT2YqG1 zQv?7l_6+E(h^iwFD~*z>K_*YMQ8JOUBq=t6yl(t=hkixZ!wV!K6-}jjXKe?c6OYuu}XdQ!dnYtNRIxYH; zZ#x@_0dQrvBMuk#qnU++oGe6$&}9LJ#~3)N zW?1cHDcTiqWJ9ngLwJ^?#f#x^D=7ex+L@ZU2I>--dEr7BXt{UYvQu};VwbcQtC6rq z3k1na;K}3kOxM>GNp}Q*1AjO2#&wWFQR;p;867aofFNr>guS-O!kA1od1=~OKyo8m z&l_ymb>t~&LW6_+k+G4p;X*uMTpp~jrl8I+h+r21xJX1r+fdqV`o**2cVvJkH|*e3 z2hXO-$WTlVCdMajK_qxl=DwlLW)U`9Q;7c=sfz4Nw%hcFCROpg!c^x3T^xCO>5FJ(V&8YNMy(=*f0Lf1W@-;zo|N&&fb4~-u> zVwu(=rg*~ZYVlq(jOC*e7#^JnHO--k5IsmI2kpht@zEo6E8)jkp-%Tg8eOgAm#!>5 z16Jo4=w~?$-jsY-sDzs5${HDlnpMwg24eQ<~ zN6FLP3$@-4^-HgbG5pfEOJi{KvXRkcb1jl1NMfwY?aEuAhIv#)Olok(FwqGBte$-3 zF}o4L()PO?)h)FAYmG#Tzj-^AF&2&<|$$8*qL{m#!_n59XkZd7S4F2#^HJ3yOCwh!a!yOOKU)n0{&cm^Em9iiZ`Qp}Z`Byx^xeZ@bd~y1jYcp#1sX)X}MT zO8ZK$LOyXH?^(%oR%uMCpzxpmz#*^e2gtIG)a&*0j_VXhM@EMaJbBJ(8YGcQ{2M!CRx4 z=6|+77p0M&ojto+pK1LS9{+|h!%KpffD^nD-5q^TpVHd{%>kk)N|8=Qc8W(P+M*JrQ6aJ*S8R}!1d`Epl1L=*`9}O; zd~={BaF>^amjgV)s{@HQ+Tfd25^M|-Sp@KYY7*2dthv-$5fwU%evyQp3L%-bvBR;C zled#iOh7`VQLPdUSl}fJzAt)Q(=`)(Fi1pEv_T;taO9jR8Kh_p4oqMlDt&xuhDM*M zCJg<0yg$AbG;xP%VnN4Vh(Jm3)NK5w*(iPmiQEjY3-6L;`F9o;=hwJF>W04@ep}Dz z>(hFgNQUX)HVLACbExmocJ)d1ZY3nj5pbGK1AsrFO=%GdK9~<4<{JQhTcCm3@WZkM z2=RgRmEq5aPXIJZ!pa7jDRAstNhC1>Bz9Cnq7(t!VVUGj@XTS+Y;Z7J{RiIXs|$3R8HtVJRLBm{jVJ`nE;1OmUYTrn>RZ<&L90RC}^^CuB}usN6q zo;l=5+q$-G0RB#e(Id-%Ov4_Nkqwb3%vXr$2)*D(YDmRU8;%XcPN&9GjfkZb)=~se z`qF`e2l_$9>k&Lg8wy@9!NdA$$CCpN^mt+vSHrti0lN;HtP9^;pSAWL}m?CP-KhlK=_SvrXp~ zv9XdMyVD31S{bsDIcg~ne>p9fnbR)HfY8w3&{hAHV9^aBet6`YY1 zAU^>|`o~Q$foTu4RbmFJNg+cNc;jJJ&w^r}0lr2Pq)}Y_ElNX!QW6!Am;{F!O0LGK zW+wA|CM*n`O9MDVX0)GaR5A*7a68ZUSs^*M1nlVJkWOB;xfmL7%=USOz>O+1HXEvqn;=9!RCg$Zdhn(1U_*db83?SumB9!p}28b(v8 z)Qa=x&VNM-u_%#3!DC0EVItO%j`*J~ zMZ#O=;%Nrzo%>R)WH%g8d14E=CO#NHGj?sP1wO53((|~KJX%0~@|R>2l+I_MH&_#t zgE^t01xV6VXm#k1Qs!EU0CrS5r1T-$=ZdBzkPLQY@ClMQJ9=%@Er}fXpOQ_{gVEDq z_fONk{bDZXz`0FHg%a|MZB}!UES}pfHBKMV2<^+_dB+99EXht@#@6V1RfA<3E~n-oZ~PjyQKv1 zPxS2V`3Phi4hBFVG7Hm^4gNfwJ%AWs{KMN5J1=js?3FKEywI1PO!wlA8hHSIR;$rD zaXW#^{V~=bdyQQY>I*jY(5iNB?>q(bi>OVke^B}e9`BdH4-kAm{BD{#`>Y!R#U#!F zi42f{L<2>gnS6AeK=?CB48&eUw60nA@iOzOOP;fVzw+07AvqA9mQcN;0#o+l0Q7TCM>qly;#;1T&{l`}d2(ov(K8 zfq9Y_d^KNiSR|HT`sC6!ka`b*Z{li?43M@!E^pen=}j=DKiz&y<8k>-y+y+3xRt2o zxUQcosG}ab{hrKI<-Zzu*?mn7Tl16?a}4w>Tf39w(*H^<5%`}I_*Z}d0Qic^d`#4I Q+5i9m07*qoM6N<$f~cW~F#rGn literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/ic_power.png b/core/res/res/drawable/ic_power.png deleted file mode 100755 index cfdf4224289ea44688414b785f6a1b67ae07a226..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 925 zcmV;O17iG%P)`ZJKy)doi{T(Ob7x0bFhYhh5)AmzAE>kKOrBXbqBa& z7YlDjo$$y`l?Rz8bOBn5>m1l2r#y}YK!xX=A0t1`;G=ve^g$lbtN*ug)ACt82t(Kt z30RcxY8f!+cEDPgmv2XE6+pIxAuMq?7Qlf;yO}%G$9#C^&C#?nqW=|8ISo~h$U=;u*5-JPL5z$0S2}zgPBUlyq_kG>KL&0XLSsCKR-9j zwT&2IiG#T65|ES!b<9sqMzFP&0V}gJdvq2YT!*uOFoY!z;v&wP>i`#^N%ZzeT-eUi zJ#lCQQF{C0`Un9z(@d~!6NpDDdO>J)6(X@ujOj!I2wZUliq{Ri+h1C*Z5+a9!K5sL zX53!XTL}@E1c`%Y~lPbyNE~v&I`!V|7 zG`!4O+#zFglWKkJn)SA>kIlR^5LJOkwDxuozjuvudoyiyWr1i?;^1v6rcqwlk@x(T zUhC%Xcv#N~D?(WCHG}Y|GxevTzh&H3Bv3mwaG@E-Li9DisU5dD+3bNmtwITFa|}Su zGhVlVo~4&bq3{VF@Ixzx3I>yIg1!8T-}q-$qh}bf%U+N|trE&cEO8K*4i z$29Xb_qTsr1y3qX9gw~S1s#uNj7%uisP5BU4R(R6HvsaPwz##vHF9b#*^dX4kI;4u zNwxe+8qC#otdiMMO8Pt?2Rgyk(*;te&tQy=pMCLg;?#S>)aWx!YV!^=&WC_8%8G-A zBZ(bSLfH1K^(!+Ij6OCRZFxgLLqM(Lj{pMz3nGJzfvT{P00000NkvXXu0mjf4GyP^ diff --git a/core/res/res/layout/js_prompt.xml b/core/res/res/layout/js_prompt.xml new file mode 100644 index 0000000000000..9ab9d09fee1e6 --- /dev/null +++ b/core/res/res/layout/js_prompt.xml @@ -0,0 +1,38 @@ + + + + + + + + + + diff --git a/core/res/res/layout/zoom_controls.xml b/core/res/res/layout/zoom_controls.xml index ec37417bc2336..729af1b183618 100644 --- a/core/res/res/layout/zoom_controls.xml +++ b/core/res/res/layout/zoom_controls.xml @@ -17,13 +17,7 @@ ** limitations under the License. */ --> - + - + diff --git a/core/res/res/layout/zoom_magnify.xml b/core/res/res/layout/zoom_magnify.xml index b424837d39228..08a5f7b60b407 100644 --- a/core/res/res/layout/zoom_magnify.xml +++ b/core/res/res/layout/zoom_magnify.xml @@ -17,14 +17,13 @@ ** limitations under the License. */ --> - + - + diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 5859b9bc633d4..61a2c29af72d0 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -310,6 +310,14 @@ "Umožňuje aplikaci získat podrobnosti o aktuálně synchronizovaných zdrojích." "zápis odebíraných zdrojů" "Umožňuje aplikaci upravit vaše aktuálně synchronizované zdroje. To může škodlivým aplikacím umožnit změnu vašich synchronizovaných zdrojů." + + + + + + + + "Domů" "Mobil" @@ -406,6 +414,12 @@ "Test FACTORY_TEST lze provést pouze u balíčků nainstalovaných ve složce /system/app." "Nebyl nalezen žádný balíček umožňující test FACTORY_TEST." "Restartovat" + + + + + + "Potvrdit" "Chcete, aby si prohlížeč zapamatoval toto heslo?" "Nyní ne" diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 0b2c7a7227f73..44671e60062a1 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -310,36 +310,44 @@ "Ermöglicht einer Anwendung, Details zu den zurzeit synchronisierten Feeds abzurufen." "Abonnierte Feeds schreiben" "Ermöglicht einer Anwendung, Änderungen an den kürzlich synchronisierten Feeds vorzunehmen. Schädliche Anwendungen könnten so Ihre synchronisierten Feeds ändern." + + + + + + + + "Privat" "Mobil" - "Beruflich" - "Beruflich (Fax)" - "Faxnummer (privat)" + "Arbeit" + "Fax (Arbeit)" + "Fax (privat)" "Pager" "Andere" "Benutzerdefiniert" "Privat" - "Beruflich" + "Arbeit" "Andere" "Benutzerdefiniert" "Privat" - "Beruflich" + "Arbeit" "Andere" "Benutzerdefiniert" "Privat" - "Beruflich" + "Arbeit" "Andere" "Benutzerdefiniert" - "Beruflich" + "Arbeit" "Andere" "Benutzerdefiniert" @@ -366,7 +374,7 @@ "Korrekt!" "Tut uns leid. Versuchen Sie es noch einmal." "Wird aufgeladen (%d%%)" - "Stecken Sie Ihr Ladegerät ein." + "Bitte Ladegerät anschließen" "Keine SIM-Karte." "Keine SIM-Karte im Telefon." "Bitte legen Sie eine SIM-Karte ein." @@ -406,6 +414,12 @@ "Die Aktion FACTORY_TEST wird nur für unter \"/system/app\" gespeicherte Pakete unterstützt." "Es wurden kein Paket mit der Aktion FACTORY_TEST gefunden." "Neu booten" + + + + + + "Bestätigen" "Möchten Sie, dass der Browser dieses Passwort speichert?" "Nicht jetzt" @@ -505,7 +519,7 @@ ".." - "%m/%d/%Y" + "%d/%m/%Y" "%1$s, %2$s, %3$s%4$s, %5$s, %6$s" "%1$s, %2$s%4$s, %5$s" "%2$s, %3$s%5$s, %6$s" @@ -533,36 +547,36 @@ - "%B %-d, %Y" + "%-d. %B %Y" "%H:%M:%S" - "%H:%M:%S %B %-d, %Y" - "%2$s %3$s%7$s %8$s" - "%1$s, %2$s %3$s%6$s, %7$s %8$s" - "%2$s %3$s%7$s %8$s, %9$s" - "%1$s, %2$s %3$s%6$s, %7$s %8$s, %9$s" - "%2$s %3$s, %5$s%7$s %8$s, %10$s" - "%1$s, %2$s %3$s, %5$s%6$s, %7$s %8$s, %10$s" - "%2$s %3$s, %4$s, %5$s%7$s %8$s, %9$s, %10$s" - "%1$s, %2$s %3$s, %4$s, %5$s%6$s, %7$s %8$s, %9$s, %10$s" - "%2$s/%3$s%7$s/%8$s" - "%1$s, %2$s/%3$s%6$s, %7$s/%8$s" - "%2$s/%3$s/%4$s%7$s/%8$s/%9$s" - "%1$s, %2$s/%3$s/%4$s%6$s, %7$s/%8$s/%9$s" - "%2$s/%3$s, %5$s%7$s/%8$s, %10$s" - "%1$s, %2$s/%3$s, %5$s%6$s, %7$s/%8$s, %10$s" - "%2$s/%3$s/%4$s, %5$s%7$s/%8$s/%9$s, %10$s" - "%1$s, %2$s/%3$s/%4$s, %5$s%6$s, %7$s/%8$s/%9$s, %10$s" - "%2$s %3$s%8$s" - "%1$s, %2$s %3$s%6$s, %7$s %8$s" - "%2$s %3$s%8$s, %9$s" - "%1$s, %2$s %3$s, %4$s%6$s, %7$s %8$s, %9$s" - "%2$s %3$s, %5$s%7$s %8$s, %10$s" - "%1$s, %2$s %3$s, %5$s%6$s, %7$s %8$s, %10$s" - "%2$s %3$s, %4$s, %5$s%7$s %8$s, %9$s, %10$s" - "%1$s, %2$s %3$s, %4$s, %5$s%6$s, %7$s %8$s, %9$s, %10$s" - "%b %-d, %Y" + "%H:%M:%S %-d. %B %Y" + "%3$s. %2$s%8$s. %7$s" + "%1$s, %3$s. %2$s%6$s, %8$s. %7$s" + "%3$s. %2$s%8$s. %7$s %9$s" + "%1$s, %3$s. %2$s%6$s, %8$s. %7$s %9$s" + "%3$s. %2$s %5$s%8$s. %7$s %10$s" + "%1$s, %3$s. %2$s, %5$s%6$s, %8$s. %7$s %10$s" + "%3$s. %2$s, %4$s, %5$s%8$s. %7$s %9$s, %10$s" + "%1$s, %3$s. %2$s %4$s, %5$s%6$s, %8$s. %7$s %9$s, %10$s" + "%3$s/%2$s%8$s/%7$s" + "%1$s, %3$s/%2$s%6$s, %8$s/%7$s" + "%3$s/%2$s/%4$s%8$s/%7$s/%9$s" + "%1$s, %3$s/%2$s/%4$s%6$s, %8$s/%7$s/%9$s" + "%3$s/%2$s, %5$s%8$s/%7$s, %10$s" + "%1$s, %3$s/%2$s, %5$s%6$s, %8$s/%7$s, %10$s" + "%3$s/%2$s/%4$s, %5$s%8$s/%7$s/%9$s, %10$s" + "%1$s, %3$s/%2$s/%4$s, %5$s%6$s, %8$s/%7$s/%9$s, %10$s" + "%3$s. – %8$s. %2$s" + "%1$s, %3$s. %2$s%6$s, %8$s. %7$s" + "%3$s. – %8$s. %2$s %9$s" + "%1$s, %3$s. %2$s %4$s%6$s, %8$s. %7$s %9$s" + "%3$s. %2$s, %5$s%8$s. %7$s, %10$s" + "%1$s, %3$s. %2$s, %5$s%6$s, %8$s. %7$s, %10$s" + "%3$s. %2$s %4$s, %5$s%8$s. %7$s %9$s, %10$s" + "%1$s, %3$s. %2$s %4$s, %5$s%6$s, %8$s. %7$s %9$s, %10$s" + "%-d. %b %Y" diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 6727d5eb8463b..07a92fa3a367b 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -310,6 +310,14 @@ "Permite que una aplicación obtenga detalles sobre los feeds sincronizados en este momento." "escribir feeds a los que está suscrito el usuario" "Permite que una aplicación modifique los feeds sincronizados actualmente. Este permiso podría provocar que una aplicación malintencionada cambie los feeds sincronizados." + + + + + + + + "Casa" "Móvil" @@ -406,6 +414,12 @@ "La acción FACTORY_TEST sólo es compatible con los paquetes instalados en /system/app." "No se ha encontrado ningún paquete que proporcione la acción FACTORY_TEST." "Reiniciar" + + + + + + "Confirmar" "¿Deseas que el navegador recuerde esta contraseña?" "Ahora no" diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index 600bc2c85d4c6..0f58ba1369610 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -310,6 +310,14 @@ "Permet à une application d\'obtenir des informations sur les flux récemment synchronisés." "Écrire les flux auxquels vous êtes abonné" "Permet à une application de modifier vos flux synchronisés actuels. Cette fonctionnalité peut permettre à des applications malveillantes de modifier vos flux synchronisés." + + + + + + + + "Accueil" "Mobile" @@ -406,6 +414,12 @@ "L\'action FACTORY_TEST est uniquement prise en charge pour les paquets de données installés dans in/system/app." "Impossible de trouver un paquet proposant l\'action FACTORY_TEST." "Redémarrer" + + + + + + "Confirmer" "Voulez-vous que le navigateur se souvienne de ce mot de passe ?" "Pas maintenant" diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index b41d449ba535d..8b96f89de6bbc 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -310,6 +310,14 @@ "Consente a un\'applicazione di ottenere dettagli sui feed attualmente sincronizzati." "scrivere feed sottoscritti" "Consente la modifica da parte di un\'applicazione dei feed attualmente sincronizzati. Le applicazioni dannose potrebbero essere in grado di modificare i feed sincronizzati." + + + + + + + + "Casa" "Cellulare" @@ -406,6 +414,12 @@ "L\'azione FACTORY_TEST è supportata soltanto per i pacchetti installati in /system/app." "Nessun pacchetto trovato che fornisca l\'azione FACTORY_TEST." "Riavvia" + + + + + + "Conferma" "Memorizzare la password nel browser?" "Non ora" diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 93b66f35ddd58..07358372a6870 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -310,6 +310,14 @@ "現在同期しているフィードの詳細の取得をアプリケーションに許可します。" "登録したフィードの書き込み" "現在同期しているフィードの変更をアプリケーションに許可します。悪意のあるアプリケーションが同期フィードを変更する恐れがあります。" + + + + + + + + "自宅" "携帯" @@ -406,6 +414,12 @@ "FACTORY_TEST操作は、/system/appにインストールされたパッケージのみが対象です。" "FACTORY_TEST操作を行うパッケージは見つかりませんでした。" "再起動" + + + + + + "確認" "このパスワードをブラウザで保存しますか?" "今は保存しない" diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 54a7321a8a7ce..9426f355eb9d2 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -310,6 +310,14 @@ "Hiermee kan een toepassing details over de huidige gesynchroniseerde feeds achterhalen." "geabonneerde feeds schrijven" "Hiermee kan een toepassing uw huidige gesynchroniseerde feeds wijzigen. Een schadelijke toepassing kan op deze manier uw gesynchroniseerde feeds wijzigen." + + + + + + + + "Thuis" "Mobiel" @@ -406,6 +414,12 @@ "De actie FACTORY_TEST wordt alleen ondersteund voor pakketten die zijn geïnstalleerd in /system/app." "Er is geen pakket gevonden dat de actie FACTORY_TEST levert." "Opnieuw opstarten" + + + + + + "Bevestigen" "Wilt u dat de browser dit wachtwoord onthoudt?" "Niet nu" diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index c3cf8a1f3de62..d76922f4fe01a 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -310,6 +310,14 @@ "Pozwala aplikacjom na pobieranie informacji szczegółowych na temat obecnie zsynchronizowanych źródeł." "zapisywanie subskrybowanych źródeł" "Umożliwia aplikacji zmianę obecnie zsynchronizowanych źródeł. Może to pozwolić szkodliwej aplikacji na zmianę zsynchronizowanych źródeł." + + + + + + + + "Strona główna" "Komórka" @@ -406,6 +414,12 @@ "Czynność FACTORY_TEST jest obsługiwana tylko dla pakietów zainstalowanych w katalogu /system/app." "Nie znaleziono żadnego pakietu, który zapewnia działanie FACTORY_TEST." "Uruchom ponownie" + + + + + + "Potwierdź" "Czy chcesz, aby zapamiętać to hasło w przeglądarce?" "Nie teraz" diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 8d362bdb1dee7..a00973fd44078 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -310,6 +310,14 @@ "Позволяет приложению получать сведения о синхронизированных фидах." "записывать фиды с подпиской" "Разрешает приложению изменять ваши синхронизированные фиды. Это может позволить вредоносному ПО изменять ваши синхронизированные фиды." + + + + + + + + "Домашний" "Мобильный" @@ -406,6 +414,12 @@ "Действие FACTORY_TEST поддерживается только для пакетов, установленных в папке /system/app." "Пакет, предоставляющий действие FACTORY_TEST, не найден." "Перезагрузить" + + + + + + "Подтверждение" "Сохранить этот пароль в браузере?" "Не сейчас" diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 27b8feac45e0c..87bd4e4de4968 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -310,6 +310,14 @@ "允许应用程序获取有关当前同步的供稿的详情。" "写入订阅的供稿" "允许应用程序修改您当前同步的供稿。这样恶意程序可以更改您同步的供稿。" + + + + + + + + "家庭" "手机" @@ -406,6 +414,12 @@ "只有在 /system/app 中安装的包支持 FACTORY_TEST 操作。" "未发现支持 FACTORY_TEST 操作的包。" "重新引导" + + + + + + "确认" "是否希望浏览器记住此密码?" "暂不保存" diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index b95ca98c191db..fbe8c552fdfc5 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -310,6 +310,14 @@ "允許應用程式取得目前已同步處理的資訊提供。" "寫入訂閱資訊提供" "允許應用程式修改已同步處理的資訊提供。惡意程式可使用此功能變更已同步處理的資訊提供。" + + + + + + + + "首頁" "行動" @@ -406,6 +414,12 @@ "FACTORY_TEST 動作只支援安裝在 /system/app 裡的程式。" "找不到提供 FACTORY_TEST 的程式。" "重新開機" + + + + + + "確認" "是否記憶此密碼?" "現在不要" diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 1704179563757..2562a8a9850da 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2468,7 +2468,7 @@ - @@ -2601,9 +2601,7 @@ - + diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index cb364e6ddedeb..f25d8293a3ca5 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -748,7 +748,7 @@ - + @@ -1034,10 +1034,22 @@ - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index f9e2e0fed44dc..978a0244a9dd8 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -979,6 +979,18 @@ your currently synced feeds. This could allow a malicious application to change your synced feeds. + + read user defined dictionary + + Allows an application to read any private + words, names and phrases that the user may have stored in the user dictionary. + + + write to user defined dictionary + + Allows an application to write new words into the + user dictionary. + @@ -1216,6 +1228,14 @@ Mozilla/5.0 (Linux; U; Android %s) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1 + + The page at \'%s\' says: + + JavaScript + + Navigate away from this page?\n\n%s\n\nSelect OK to continue, or Cancel to stay on the current page. + Confirm diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index bc300c379293d..73e7dd0db4949 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -627,4 +627,11 @@ #BB000000 2.75 + + diff --git a/core/res/waitingroom/screen_background_blue-land.png b/core/res/waitingroom/screen_background_blue-land.png deleted file mode 100644 index 50e46b157663a61aaa53ad1c275bb9abc7d2aa16..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11681 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 diff --git a/core/res/waitingroom/screen_background_green-land.png b/core/res/waitingroom/screen_background_green-land.png deleted file mode 100644 index f46afa1676276d4f9e22081e6deeca389a5ff1c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9861 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 { public: - OverlayRef(overlay_handle_t const*, const sp&, + OverlayRef(overlay_handle_t, const sp&, uint32_t w, uint32_t h, int32_t f, uint32_t ws, uint32_t hs); static sp readFromParcel(const Parcel& data); @@ -53,7 +53,7 @@ private: OverlayRef(); virtual ~OverlayRef(); - overlay_handle_t const *mOverlayHandle; + overlay_handle_t mOverlayHandle; sp mOverlayChannel; uint32_t mWidth; uint32_t mHeight; @@ -74,7 +74,7 @@ public: void destroy(); /* get the HAL handle for this overlay */ - overlay_handle_t const* getHandleRef() const; + overlay_handle_t getHandleRef() const; /* blocks until an overlay buffer is available and return that buffer. */ status_t dequeueBuffer(overlay_buffer_t* buffer); diff --git a/include/utils/Parcel.h b/include/utils/Parcel.h index 7c451ab212570..9087c4465b962 100644 --- a/include/utils/Parcel.h +++ b/include/utils/Parcel.h @@ -17,6 +17,7 @@ #ifndef ANDROID_PARCEL_H #define ANDROID_PARCEL_H +#include #include #include #include @@ -78,6 +79,9 @@ public: status_t writeString16(const char16_t* str, size_t len); status_t writeStrongBinder(const sp& val); status_t writeWeakBinder(const wp& val); + + // doesn't take ownership of the native_handle + status_t writeNativeHandle(const native_handle& handle); // Place a file descriptor into the parcel. The given fd must remain // valid for the lifetime of the parcel. @@ -108,6 +112,15 @@ public: const char16_t* readString16Inplace(size_t* outLen) const; sp readStrongBinder() const; wp readWeakBinder() const; + + + // if alloc is NULL, native_handle is allocated with malloc(), otherwise + // alloc is used. If the function fails, the effects of alloc() must be + // reverted by the caller. + native_handle* readNativeHandle( + native_handle* (*alloc)(void* cookie, int numFds, int ints), + void* cookie) const; + // Retrieve a file descriptor from the parcel. This returns the raw fd // in the parcel, which you do not own -- use dup() to get your own copy. diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp index 7242575957492..c8c8431096d7b 100644 --- a/libs/audioflinger/A2dpAudioInterface.cpp +++ b/libs/audioflinger/A2dpAudioInterface.cpp @@ -126,7 +126,7 @@ status_t A2dpAudioInterface::dump(int fd, const Vector& args) // ---------------------------------------------------------------------------- A2dpAudioInterface::A2dpAudioStreamOut::A2dpAudioStreamOut() : - mFd(-1), mStandby(false), mStartCount(0), mRetryCount(0), mData(NULL), + mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL), mInitialized(false) { // use any address by default diff --git a/libs/surfaceflinger/LayerBuffer.h b/libs/surfaceflinger/LayerBuffer.h index 3286535d0b1a5..6e3d49f05373a 100644 --- a/libs/surfaceflinger/LayerBuffer.h +++ b/libs/surfaceflinger/LayerBuffer.h @@ -170,7 +170,7 @@ private: bool mVisibilityChanged; overlay_t* mOverlay; - overlay_handle_t const *mOverlayHandle; + overlay_handle_t mOverlayHandle; overlay_control_device_t* mOverlayDevice; uint32_t mWidth; uint32_t mHeight; diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp index 4a325ac2e0f35..50c60084adf7f 100644 --- a/libs/ui/Camera.cpp +++ b/libs/ui/Camera.cpp @@ -125,10 +125,9 @@ void Camera::disconnect() status_t Camera::reconnect() { LOGV("reconnect"); - if (mCamera != 0) { - return mCamera->connect(this); - } - return NO_INIT; + sp c = mCamera; + if (c == 0) return NO_INIT; + return c->connect(this); } sp Camera::remote() @@ -138,14 +137,16 @@ sp Camera::remote() status_t Camera::lock() { - if (mCamera != 0) return mCamera->lock(); - return NO_INIT; + sp c = mCamera; + if (c == 0) return NO_INIT; + return c->lock(); } status_t Camera::unlock() { - if (mCamera != 0) return mCamera->unlock(); - return NO_INIT; + sp c = mCamera; + if (c == 0) return NO_INIT; + return c->unlock(); } // pass the buffered ISurface to the camera service @@ -156,7 +157,9 @@ status_t Camera::setPreviewDisplay(const sp& surface) LOGE("app passed NULL surface"); return NO_INIT; } - return mCamera->setPreviewDisplay(surface->getISurface()); + sp c = mCamera; + if (c == 0) return NO_INIT; + return c->setPreviewDisplay(surface->getISurface()); } status_t Camera::setPreviewDisplay(const sp& surface) @@ -166,7 +169,9 @@ status_t Camera::setPreviewDisplay(const sp& surface) LOGE("app passed NULL surface"); return NO_INIT; } - return mCamera->setPreviewDisplay(surface); + sp c = mCamera; + if (c == 0) return NO_INIT; + return c->setPreviewDisplay(surface); } @@ -174,48 +179,62 @@ status_t Camera::setPreviewDisplay(const sp& surface) status_t Camera::startPreview() { LOGV("startPreview"); - return mCamera->startPreview(); + sp c = mCamera; + if (c == 0) return NO_INIT; + return c->startPreview(); } // stop preview mode void Camera::stopPreview() { LOGV("stopPreview"); - mCamera->stopPreview(); + sp c = mCamera; + if (c == 0) return; + c->stopPreview(); } // get preview state bool Camera::previewEnabled() { LOGV("previewEnabled"); - return mCamera->previewEnabled(); + sp c = mCamera; + if (c == 0) return false; + return c->previewEnabled(); } status_t Camera::autoFocus() { LOGV("autoFocus"); - return mCamera->autoFocus(); + sp c = mCamera; + if (c == 0) return NO_INIT; + return c->autoFocus(); } // take a picture status_t Camera::takePicture() { LOGV("takePicture"); - return mCamera->takePicture(); + sp c = mCamera; + if (c == 0) return NO_INIT; + return c->takePicture(); } // set preview/capture parameters - key/value pairs status_t Camera::setParameters(const String8& params) { LOGV("setParameters"); - return mCamera->setParameters(params); + sp c = mCamera; + if (c == 0) return NO_INIT; + return c->setParameters(params); } // get preview/capture parameters - key/value pairs String8 Camera::getParameters() const { LOGV("getParameters"); - String8 params = mCamera->getParameters(); + String8 params; + sp c = mCamera; + if (c != 0) params = mCamera->getParameters(); return params; } @@ -252,6 +271,8 @@ void Camera::setFrameCallback(frame_callback cb, void *cookie, int frame_callbac LOGV("setFrameCallback"); mFrameCallback = cb; mFrameCallbackCookie = cookie; + sp c = mCamera; + if (c == 0) return; mCamera->setFrameCallbackFlag(frame_callback_flag); } diff --git a/libs/ui/Overlay.cpp b/libs/ui/Overlay.cpp index 2745f5214c572..c8e61689d5763 100644 --- a/libs/ui/Overlay.cpp +++ b/libs/ui/Overlay.cpp @@ -74,7 +74,7 @@ status_t Overlay::getStatus() const { return mStatus; } -overlay_handle_t const* Overlay::getHandleRef() const { +overlay_handle_t Overlay::getHandleRef() const { if (mStatus != NO_ERROR) return NULL; return mOverlayRef->mOverlayHandle; } @@ -112,7 +112,7 @@ OverlayRef::OverlayRef() { } -OverlayRef::OverlayRef(overlay_handle_t const* handle, const sp& channel, +OverlayRef::OverlayRef(overlay_handle_t handle, const sp& channel, uint32_t w, uint32_t h, int32_t f, uint32_t ws, uint32_t hs) : mOverlayHandle(handle), mOverlayChannel(channel), mWidth(w), mHeight(h), mFormat(f), mWidthStride(ws), mHeightStride(hs), @@ -126,7 +126,7 @@ OverlayRef::~OverlayRef() /* FIXME: handles should be promoted to "real" API and be handled by * the framework */ for (int i=0 ; inumFds ; i++) { - close(mOverlayHandle->fds[i]); + close(mOverlayHandle->data[i]); } free((void*)mOverlayHandle); } @@ -141,16 +141,8 @@ sp OverlayRef::readFromParcel(const Parcel& data) { uint32_t f = data.readInt32(); uint32_t ws = data.readInt32(); uint32_t hs = data.readInt32(); - /* FIXME: handles should be promoted to "real" API and be handled by - * the framework */ - int numfd = data.readInt32(); - int numint = data.readInt32(); - overlay_handle_t* handle = (overlay_handle_t*)malloc( - sizeof(overlay_handle_t) + numint*sizeof(int)); - for (int i=0 ; ifds[i] = data.readFileDescriptor(); - for (int i=0 ; idata[i] = data.readInt32(); + native_handle* handle = data.readNativeHandle(NULL, NULL); + result = new OverlayRef(); result->mOverlayHandle = handle; result->mOverlayChannel = overlay; @@ -171,14 +163,7 @@ status_t OverlayRef::writeToParcel(Parcel* reply, const sp& o) { reply->writeInt32(o->mFormat); reply->writeInt32(o->mWidthStride); reply->writeInt32(o->mHeightStride); - /* FIXME: handles should be promoted to "real" API and be handled by - * the framework */ - reply->writeInt32(o->mOverlayHandle->numFds); - reply->writeInt32(o->mOverlayHandle->numInts); - for (int i=0 ; imOverlayHandle->numFds ; i++) - reply->writeFileDescriptor(o->mOverlayHandle->fds[i]); - for (int i=0 ; imOverlayHandle->numInts ; i++) - reply->writeInt32(o->mOverlayHandle->data[i]); + reply->writeNativeHandle(*(o->mOverlayHandle)); } else { reply->writeStrongBinder(NULL); } diff --git a/libs/utils/Parcel.cpp b/libs/utils/Parcel.cpp index 3eca4b010e3d9..0eba0b07c8d4d 100644 --- a/libs/utils/Parcel.cpp +++ b/libs/utils/Parcel.cpp @@ -650,6 +650,26 @@ status_t Parcel::writeWeakBinder(const wp& val) return flatten_binder(ProcessState::self(), val, this); } +status_t Parcel::writeNativeHandle(const native_handle& handle) +{ + if (handle.version != sizeof(native_handle)) + return BAD_TYPE; + + status_t err; + err = writeInt32(handle.numFds); + if (err != NO_ERROR) return err; + + err = writeInt32(handle.numInts); + if (err != NO_ERROR) return err; + + for (int i=0 ; err==NO_ERROR && i Parcel::readWeakBinder() const return val; } + +native_handle* Parcel::readNativeHandle(native_handle* (*alloc)(void*, int, int), void* cookie) const +{ + int numFds, numInts; + status_t err; + err = readInt32(&numFds); + if (err != NO_ERROR) return 0; + err = readInt32(&numInts); + if (err != NO_ERROR) return 0; + + native_handle* h; + if (alloc == 0) { + size_t size = sizeof(native_handle) + sizeof(int)*(numFds + numInts); + h = (native_handle*)malloc(size); + h->version = sizeof(native_handle); + h->numFds = numFds; + h->numInts = numInts; + } else { + h = alloc(cookie, numFds, numInts); + if (h->version != sizeof(native_handle)) { + return 0; + } + } + + for (int i=0 ; err==NO_ERROR && idata[i] = readFileDescriptor(); + if (h->data[i] < 0) err = BAD_VALUE; + } + + err = read(h->data + numFds, sizeof(int)*numInts); + + if (err != NO_ERROR) { + if (alloc == 0) { + free(h); + } + h = 0; + } + return h; +} + + int Parcel::readFileDescriptor() const { const flat_binder_object* flat = readObject(true); @@ -923,7 +984,7 @@ const flat_binder_object* Parcel::readObject(bool nullMetaData) const = reinterpret_cast(mData+DPOS); mDataPos = DPOS + sizeof(flat_binder_object); if (!nullMetaData && (obj->cookie == NULL && obj->binder == NULL)) { - // When transfering a NULL object, we don't write it into + // When transferring a NULL object, we don't write it into // the object list, so we don't want to check for it when // reading. LOGV("readObject Setting data pos of %p to %d\n", this, mDataPos); diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index bbb9548f27c93..3d39181922f1f 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -245,6 +245,8 @@ status_t AudioRecord::start() if (android_atomic_or(1, &mActive) == 0) { mNewPosition = mCblk->user + mUpdatePeriod; + mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; + mCblk->waitTimeMs = 0; if (t != 0) { t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT); } else { @@ -342,7 +344,7 @@ status_t AudioRecord::getPosition(uint32_t *position) // ------------------------------------------------------------------------- -status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, bool blocking) +status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) { int active; int timeout = 0; @@ -362,14 +364,21 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, bool blocking) active = mActive; if (UNLIKELY(!active)) return NO_MORE_BUFFERS; - if (UNLIKELY(!blocking)) + if (UNLIKELY(!waitCount)) return WOULD_BLOCK; timeout = 0; - result = cblk->cv.waitRelative(cblk->lock, seconds(1)); + result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS)); if (__builtin_expect(result!=NO_ERROR, false)) { - LOGW( "obtainBuffer timed out (is the CPU pegged?) " - "user=%08x, server=%08x", cblk->user, cblk->server); - timeout = 1; + cblk->waitTimeMs += WAIT_PERIOD_MS; + if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { + LOGW( "obtainBuffer timed out (is the CPU pegged?) " + "user=%08x, server=%08x", cblk->user, cblk->server); + timeout = 1; + cblk->waitTimeMs = 0; + } + if (--waitCount == 0) { + return TIMED_OUT; + } } // read the server count again start_loop_here: @@ -382,6 +391,8 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, bool blocking) "but didn't need to be locked. We recovered, but " "this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server); + cblk->waitTimeMs = 0; + if (framesReq > framesReady) { framesReq = framesReady; } @@ -430,7 +441,9 @@ ssize_t AudioRecord::read(void* buffer, size_t userSize) audioBuffer.frameCount = userSize/mChannelCount/sizeof(int16_t); - status_t err = obtainBuffer(&audioBuffer, true); + // Calling obtainBuffer() with a negative wait count causes + // an (almost) infinite wait time. + status_t err = obtainBuffer(&audioBuffer, -1); if (err < 0) { // out of buffers, return #bytes written if (err == status_t(NO_MORE_BUFFERS)) @@ -457,7 +470,7 @@ bool AudioRecord::processAudioBuffer(const sp& thread) { Buffer audioBuffer; uint32_t frames = mRemainingFrames; - size_t readSize = 0; + size_t readSize; // Manage marker callback if (mMarkerPosition > 0) { @@ -477,17 +490,19 @@ bool AudioRecord::processAudioBuffer(const sp& thread) do { audioBuffer.frameCount = frames; - status_t err = obtainBuffer(&audioBuffer, false); + // Calling obtainBuffer() with a wait count of 1 + // limits wait time to WAIT_PERIOD_MS. This prevents from being + // stuck here not being able to handle timed events (position, markers). + status_t err = obtainBuffer(&audioBuffer, 1); if (err < NO_ERROR) { - if (err != WOULD_BLOCK) { + if (err != TIMED_OUT) { LOGE("Error obtaining an audio buffer, giving up."); return false; } + break; } if (err == status_t(STOPPED)) return false; - if (audioBuffer.size == 0) break; - size_t reqSize = audioBuffer.size; mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer); readSize = audioBuffer.size; @@ -514,13 +529,6 @@ bool AudioRecord::processAudioBuffer(const sp& thread) } } - // If no data was read, it is likely that obtainBuffer() did - // not find available data in PCM buffer: we release the processor for - // a few millisecond before polling again for available data. - if (readSize == 0) { - usleep(5000); - } - if (frames == 0) { mRemainingFrames = mNotificationFrames; } else { diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index ce65312020ab6..f9f8568c969a5 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -330,6 +330,8 @@ void AudioTrack::start() if (android_atomic_or(1, &mActive) == 0) { mNewPosition = mCblk->server + mUpdatePeriod; + mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; + mCblk->waitTimeMs = 0; if (t != 0) { t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT); } else { @@ -572,7 +574,7 @@ status_t AudioTrack::reload() // ------------------------------------------------------------------------- -status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, bool blocking) +status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) { int active; int timeout = 0; @@ -594,15 +596,23 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, bool blocking) LOGV("Not active and NO_MORE_BUFFERS"); return NO_MORE_BUFFERS; } - if (UNLIKELY(!blocking)) + if (UNLIKELY(!waitCount)) return WOULD_BLOCK; timeout = 0; - result = cblk->cv.waitRelative(cblk->lock, seconds(1)); - if (__builtin_expect(result!=NO_ERROR, false)) { - LOGW( "obtainBuffer timed out (is the CPU pegged?) " - "user=%08x, server=%08x", cblk->user, cblk->server); - mAudioTrack->start(); // FIXME: Wake up audioflinger - timeout = 1; + result = cblk->cv.waitRelative(cblk->lock, milliseconds(WAIT_PERIOD_MS)); + if (__builtin_expect(result!=NO_ERROR, false)) { + cblk->waitTimeMs += WAIT_PERIOD_MS; + if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) { + LOGW( "obtainBuffer timed out (is the CPU pegged?) " + "user=%08x, server=%08x", cblk->user, cblk->server); + mAudioTrack->start(); // FIXME: Wake up audioflinger + timeout = 1; + cblk->waitTimeMs = 0; + } + ; + if (--waitCount == 0) { + return TIMED_OUT; + } } // read the server count again start_loop_here: @@ -610,6 +620,8 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, bool blocking) } } + cblk->waitTimeMs = 0; + if (framesReq > framesAvail) { framesReq = framesAvail; } @@ -667,8 +679,9 @@ ssize_t AudioTrack::write(const void* buffer, size_t userSize) if (mFormat == AudioSystem::PCM_16_BIT) { audioBuffer.frameCount >>= 1; } - - status_t err = obtainBuffer(&audioBuffer, true); + // Calling obtainBuffer() with a negative wait count causes + // an (almost) infinite wait time. + status_t err = obtainBuffer(&audioBuffer, -1); if (err < 0) { // out of buffers, return #bytes written if (err == status_t(NO_MORE_BUFFERS)) @@ -706,7 +719,7 @@ bool AudioTrack::processAudioBuffer(const sp& thread) { Buffer audioBuffer; uint32_t frames; - size_t writtenSize = 0; + size_t writtenSize; // Manage underrun callback if (mActive && (mCblk->framesReady() == 0)) { @@ -756,18 +769,20 @@ bool AudioTrack::processAudioBuffer(const sp& thread) do { audioBuffer.frameCount = frames; - - status_t err = obtainBuffer(&audioBuffer, false); + + // Calling obtainBuffer() with a wait count of 1 + // limits wait time to WAIT_PERIOD_MS. This prevents from being + // stuck here not being able to handle timed events (position, markers, loops). + status_t err = obtainBuffer(&audioBuffer, 1); if (err < NO_ERROR) { - if (err != WOULD_BLOCK) { + if (err != TIMED_OUT) { LOGE("Error obtaining an audio buffer, giving up."); return false; } + break; } if (err == status_t(STOPPED)) return false; - if (audioBuffer.size == 0) break; - // Divide buffer size by 2 to take into account the expansion // due to 8 to 16 bit conversion: the callback must fill only half // of the destination buffer @@ -802,13 +817,6 @@ bool AudioTrack::processAudioBuffer(const sp& thread) } while (frames); - // If no data was written, it is likely that obtainBuffer() did - // not find room in PCM buffer: we release the processor for - // a few millisecond before polling again for available room. - if (writtenSize == 0) { - usleep(5000); - } - if (frames == 0) { mRemainingFrames = mNotificationFrames; } else { @@ -872,7 +880,12 @@ uint32_t audio_track_cblk_t::stepUser(uint32_t frameCount) u += frameCount; // Ensure that user is never ahead of server for AudioRecord - if (!out && u > this->server) { + if (out) { + // If stepServer() has been called once, switch to normal obtainBuffer() timeout period + if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS-1) { + bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; + } + } else if (u > this->server) { LOGW("stepServer occured after track reset"); u = this->server; } @@ -909,13 +922,20 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount) uint32_t s = this->server; s += frameCount; - // It is possible that we receive a flush() - // while the mixer is processing a block: in this case, - // stepServer() is called After the flush() has reset u & s and - // we have s > u - if (out && s > this->user) { - LOGW("stepServer occured after track reset"); - s = this->user; + if (out) { + // Mark that we have read the first buffer so that next time stepUser() is called + // we switch to normal obtainBuffer() timeout period + if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) { + bufferTimeoutMs = MAX_RUN_TIMEOUT_MS - 1; + } + // It is possible that we receive a flush() + // while the mixer is processing a block: in this case, + // stepServer() is called After the flush() has reset u & s and + // we have s > u + if (s > this->user) { + LOGW("stepServer occured after track reset"); + s = this->user; + } } if (s >= loopEnd) { diff --git a/services/java/com/android/server/GadgetService.java b/services/java/com/android/server/GadgetService.java new file mode 100644 index 0000000000000..4e4925361cc26 --- /dev/null +++ b/services/java/com/android/server/GadgetService.java @@ -0,0 +1,64 @@ +/* + * 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 android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.gadget.GadgetManager; +import android.gadget.GadgetInfo; + +import com.android.internal.gadget.IGadgetService; + +class GadgetService extends IGadgetService.Stub +{ + private static final String TAG = "GadgetService"; + + Context mContext; + + GadgetService(Context context) { + mContext = context; + } + + public int allocateGadgetId(String hostPackage) { + return 42; + } + + public void deleteGadgetId(int gadgetId) { + } + + public void bindGadgetId(int gadgetId, ComponentName provider) { + sendEnabled(provider); + } + + void sendEnabled(ComponentName provider) { + Intent intent = new Intent(GadgetManager.GADGET_ENABLE_ACTION); + intent.setComponent(provider); + mContext.sendBroadcast(intent); + } + + public GadgetInfo getGadgetInfo(int gadgetId) { + GadgetInfo info = new GadgetInfo(); + info.provider = new ComponentName("com.android.gadgethost", + "com.android.gadgethost.TestGadgetProvider"); + info.minWidth = 0; + info.minHeight = 0; + info.updatePeriodMillis = 60 * 1000; // 60s + return info; + } +} + diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index baf57bccac732..7f7a52e0acceb 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -290,7 +290,7 @@ class ServerThread extends Thread { Log.i(TAG, "Starting Audio Service"); ServiceManager.addService(Context.AUDIO_SERVICE, new AudioService(context)); } catch (Throwable e) { - Log.e(TAG, "Failure starting Volume Service", e); + Log.e(TAG, "Failure starting Audio Service", e); } try { @@ -300,6 +300,13 @@ class ServerThread extends Thread { } catch (Throwable e) { Log.e(TAG, "Failure starting HeadsetObserver", e); } + + try { + Log.i(TAG, "Starting Gadget Service"); + ServiceManager.addService(Context.GADGET_SERVICE, new GadgetService(context)); + } catch (Throwable e) { + Log.e(TAG, "Failure starting Gadget Service", e); + } } // make sure the ADB_ENABLED setting value matches the secure property value diff --git a/services/java/com/android/server/WifiWatchdogService.java b/services/java/com/android/server/WifiWatchdogService.java index 9578c2e4ccfbe..fe97b93273055 100644 --- a/services/java/com/android/server/WifiWatchdogService.java +++ b/services/java/com/android/server/WifiWatchdogService.java @@ -23,6 +23,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.database.ContentObserver; import android.net.NetworkInfo; +import android.net.DhcpInfo; import android.net.wifi.ScanResult; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; @@ -30,7 +31,6 @@ import android.net.wifi.WifiStateTracker; import android.os.Handler; import android.os.Looper; import android.os.Message; -import android.os.SystemProperties; import android.provider.Settings; import android.text.TextUtils; import android.util.Config; @@ -241,6 +241,15 @@ public class WifiWatchdogService { return Settings.Secure.getInt(mContentResolver, Settings.Secure.WIFI_WATCHDOG_BACKGROUND_CHECK_TIMEOUT_MS, 1000); } + + /** + * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WATCH_LIST + * @return the comma-separated list of SSIDs + */ + private String getWatchList() { + return Settings.Secure.getString(mContentResolver, + Settings.Secure.WIFI_WATCHDOG_WATCH_LIST); + } /** * Registers to receive the necessary Wi-Fi broadcasts. @@ -304,8 +313,13 @@ public class WifiWatchdogService { * * @return The DNS of the current AP. */ - private static String getDns() { - return SystemProperties.get(SYSTEMPROPERTY_KEY_DNS); + private int getDns() { + DhcpInfo addressInfo = mWifiManager.getDhcpInfo(); + if (addressInfo != null) { + return addressInfo.dns1; + } else { + return -1; + } } /** @@ -315,18 +329,19 @@ public class WifiWatchdogService { * @return Whether the DNS is reachable */ private boolean checkDnsConnectivity() { - String dns = getDns(); - if (V) { - myLogV("checkDnsConnectivity: Checking " + dns + " for connectivity"); - } - - if (TextUtils.isEmpty(dns)) { + int dns = getDns(); + if (dns == -1) { if (V) { myLogV("checkDnsConnectivity: Invalid DNS, returning false"); } return false; } + if (V) { + myLogV("checkDnsConnectivity: Checking 0x" + + Integer.toHexString(Integer.reverseBytes(dns)) + " for connectivity"); + } + int numInitialIgnoredPings = getInitialIgnoredPingCount(); int numPings = getPingCount(); int pingDelay = getPingDelayMs(); @@ -403,13 +418,13 @@ public class WifiWatchdogService { } private boolean backgroundCheckDnsConnectivity() { - String dns = getDns(); + int dns = getDns(); if (false && V) { myLogV("backgroundCheckDnsConnectivity: Background checking " + dns + " for connectivity"); } - if (TextUtils.isEmpty(dns)) { + if (dns == -1) { if (V) { myLogV("backgroundCheckDnsConnectivity: DNS is empty, returning false"); } @@ -557,7 +572,14 @@ public class WifiWatchdogService { return false; } } - + + if (!isOnWatchList(ssid)) { + if (V) { + Log.v(TAG, " SSID not on watch list, returning false"); + } + return false; + } + // The watchdog only monitors networks with multiple APs if (!hasRequiredNumberOfAps(ssid)) { return false; @@ -565,6 +587,24 @@ public class WifiWatchdogService { return true; } + + private boolean isOnWatchList(String ssid) { + String watchList; + + if (ssid == null || (watchList = getWatchList()) == null) { + return false; + } + + String[] list = watchList.split(" *, *"); + + for (String name : list) { + if (ssid.equals(name)) { + return true; + } + } + + return false; + } /** * Checks if the current scan results have multiple access points with an SSID. @@ -1180,7 +1220,7 @@ public class WifiWatchdogService { /** Used to generate IDs */ private static Random sRandom = new Random(); - static boolean isDnsReachable(String dns, int timeout) { + static boolean isDnsReachable(int dns, int timeout) { try { DatagramSocket socket = new DatagramSocket(); @@ -1191,7 +1231,13 @@ public class WifiWatchdogService { fillQuery(buf); // Send the DNS query - InetAddress dnsAddress = InetAddress.getByName(dns); + byte parts[] = new byte[4]; + parts[0] = (byte)(dns & 0xff); + parts[1] = (byte)((dns >> 8) & 0xff); + parts[2] = (byte)((dns >> 16) & 0xff); + parts[3] = (byte)((dns >> 24) & 0xff); + + InetAddress dnsAddress = InetAddress.getByAddress(parts); DatagramPacket packet = new DatagramPacket(buf, buf.length, dnsAddress, DNS_PORT); socket.send(packet); diff --git a/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java b/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java index 7a4c78fac874e..663b7a455d623 100644 --- a/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java +++ b/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java @@ -116,4 +116,35 @@ public class AutoCompleteTextViewPopup ListView.INVALID_POSITION, textView.getListSelection()); } + /** Make sure we handle an empty adapter properly */ + @MediumTest + public void testPopupNavigateNoAdapter() throws Throwable { + AutoCompleteTextViewSimple theActivity = getActivity(); + final AutoCompleteTextView textView = theActivity.getTextView(); + final Instrumentation instrumentation = getInstrumentation(); + + // focus and type + textView.requestFocus(); + instrumentation.waitForIdleSync(); + sendKeys("A"); + + // No initial selection + assertEquals("getListSelection(-1)", + ListView.INVALID_POSITION, textView.getListSelection()); + + // check for selection position as expected + sendKeys("DPAD_DOWN"); + assertEquals("getListSelection(0)", 0, textView.getListSelection()); + + // Now get rid of the adapter + runTestOnUiThread(new Runnable() { + public void run() { + textView.setAdapter((ArrayAdapter) null); + } + }); + instrumentation.waitForIdleSync(); + + // now try moving "down" - nothing should happen since there's no longer an adapter + sendKeys("DPAD_DOWN"); + } } diff --git a/tests/GadgetHost/Android.mk b/tests/GadgetHost/Android.mk new file mode 100644 index 0000000000000..1d88db8023a14 --- /dev/null +++ b/tests/GadgetHost/Android.mk @@ -0,0 +1,11 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := user + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_PACKAGE_NAME := GadgetHost +LOCAL_CERTIFICATE := platform + +include $(BUILD_PACKAGE) diff --git a/tests/GadgetHost/AndroidManifest.xml b/tests/GadgetHost/AndroidManifest.xml new file mode 100644 index 0000000000000..8da44854df150 --- /dev/null +++ b/tests/GadgetHost/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/GadgetHost/res/layout/gadget_host.xml b/tests/GadgetHost/res/layout/gadget_host.xml new file mode 100644 index 0000000000000..824cc44ed7e27 --- /dev/null +++ b/tests/GadgetHost/res/layout/gadget_host.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + +