summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk7
-rw-r--r--api/current.xml280
-rw-r--r--camera/libcameraservice/CameraService.cpp56
-rw-r--r--core/java/android/app/SearchDialog.java9
-rw-r--r--core/java/android/bluetooth/BluetoothA2dp.java66
-rw-r--r--core/java/android/bluetooth/BluetoothHeadset.java109
-rw-r--r--core/java/android/bluetooth/IBluetoothA2dp.aidl2
-rw-r--r--core/java/android/bluetooth/IBluetoothHeadset.aidl18
-rw-r--r--core/java/android/content/Context.java9
-rw-r--r--core/java/android/gadget/GadgetHost.java72
-rw-r--r--core/java/android/gadget/GadgetHostView.java102
-rw-r--r--core/java/android/gadget/GadgetInfo.aidl (renamed from core/java/android/bluetooth/IBluetoothHeadsetCallback.aidl)28
-rw-r--r--core/java/android/gadget/GadgetInfo.java126
-rw-r--r--core/java/android/gadget/GadgetManager.java170
-rw-r--r--core/java/android/gadget/package.html4
-rw-r--r--core/java/android/hardware/Camera.java27
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java198
-rw-r--r--core/java/android/provider/Settings.java38
-rw-r--r--core/java/android/provider/UserDictionary.java127
-rw-r--r--core/java/android/server/BluetoothA2dpService.java52
-rw-r--r--core/java/android/speech/srec/Recognizer.java40
-rw-r--r--core/java/android/speech/srec/WaveHeader.java7
-rw-r--r--core/java/android/view/ViewRoot.java30
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java5
-rw-r--r--core/java/android/webkit/CallbackProxy.java136
-rw-r--r--core/java/android/webkit/TextDialog.java49
-rw-r--r--core/java/android/webkit/WebView.java13
-rw-r--r--core/java/android/widget/AutoCompleteTextView.java2
-rw-r--r--core/java/android/widget/MediaController.java6
-rw-r--r--core/java/android/widget/VideoView.java7
-rw-r--r--core/java/com/android/internal/gadget/IGadgetService.aidl28
-rw-r--r--core/java/com/android/internal/gadget/package.html3
-rw-r--r--core/java/com/android/internal/os/HandlerCaller.java2
-rw-r--r--core/java/com/android/internal/view/menu/IconMenuItemView.java4
-rw-r--r--core/java/com/android/internal/view/menu/ListMenuItemView.java8
-rw-r--r--core/java/com/android/internal/view/menu/MenuBuilder.java13
-rw-r--r--core/java/com/android/internal/widget/NumberPicker.java1
-rw-r--r--core/jni/android_hardware_Camera.cpp40
-rw-r--r--core/res/AndroidManifest.xml18
-rw-r--r--core/res/res/drawable/btn_check_off_longpress.pngbin1633 -> 0 bytes
-rw-r--r--core/res/res/drawable/btn_check_on_longpress.pngbin1661 -> 0 bytes
-rw-r--r--core/res/res/drawable/emo_im_angel.pngbin0 -> 3592 bytes
-rw-r--r--core/res/res/drawable/emo_im_cool.pngbin0 -> 3466 bytes
-rw-r--r--core/res/res/drawable/emo_im_crying.pngbin0 -> 3558 bytes
-rw-r--r--core/res/res/drawable/emo_im_embarrassed.pngbin0 -> 3619 bytes
-rw-r--r--core/res/res/drawable/emo_im_foot_in_mouth.pngbin0 -> 3603 bytes
-rw-r--r--core/res/res/drawable/emo_im_happy.pngbin0 -> 3591 bytes
-rw-r--r--core/res/res/drawable/emo_im_kissing.pngbin0 -> 3492 bytes
-rw-r--r--core/res/res/drawable/emo_im_laughing.pngbin0 -> 3624 bytes
-rw-r--r--core/res/res/drawable/emo_im_lips_are_sealed.pngbin0 -> 3670 bytes
-rw-r--r--core/res/res/drawable/emo_im_money_mouth.pngbin0 -> 3649 bytes
-rw-r--r--core/res/res/drawable/emo_im_sad.pngbin0 -> 3572 bytes
-rw-r--r--core/res/res/drawable/emo_im_surprised.pngbin0 -> 3490 bytes
-rw-r--r--core/res/res/drawable/emo_im_tongue_sticking_out.pngbin0 -> 3653 bytes
-rw-r--r--core/res/res/drawable/emo_im_undecided.pngbin0 -> 3552 bytes
-rw-r--r--core/res/res/drawable/emo_im_winking.pngbin0 -> 3568 bytes
-rw-r--r--core/res/res/drawable/emo_im_wtf.pngbin0 -> 3591 bytes
-rw-r--r--core/res/res/drawable/emo_im_yelling.pngbin0 -> 3575 bytes
-rw-r--r--core/res/res/drawable/ic_menu_account_list.pngbin0 -> 2394 bytes
-rwxr-xr-xcore/res/res/drawable/ic_menu_allfriends.pngbin0 -> 2257 bytes
-rw-r--r--core/res/res/drawable/ic_menu_archive.pngbin0 -> 1354 bytes
-rw-r--r--core/res/res/drawable/ic_menu_attachment.pngbin0 -> 2247 bytes
-rw-r--r--core/res/res/drawable/ic_menu_back.pngbin0 -> 1237 bytes
-rw-r--r--core/res/res/drawable/ic_menu_block.pngbin0 -> 2336 bytes
-rw-r--r--core/res/res/drawable/ic_menu_blocked_user.pngbin0 -> 2408 bytes
-rw-r--r--core/res/res/drawable/ic_menu_cc.pngbin0 -> 2046 bytes
-rw-r--r--core/res/res/drawable/ic_menu_chat_dashboard.pngbin0 -> 1865 bytes
-rw-r--r--core/res/res/drawable/ic_menu_clear_playlist.pngbin0 -> 2281 bytes
-rw-r--r--core/res/res/drawable/ic_menu_compose.pngbin0 -> 2014 bytes
-rw-r--r--core/res/res/drawable/ic_menu_emoticons.pngbin0 -> 2620 bytes
-rw-r--r--core/res/res/drawable/ic_menu_end_conversation.pngbin0 -> 1932 bytes
-rw-r--r--core/res/res/drawable/ic_menu_forward.pngbin0 -> 1228 bytes
-rw-r--r--core/res/res/drawable/ic_menu_friendslist.pngbin0 -> 1561 bytes
-rw-r--r--core/res/res/drawable/ic_menu_goto.pngbin0 -> 1636 bytes
-rw-r--r--core/res/res/drawable/ic_menu_home.pngbin0 -> 2048 bytes
-rw-r--r--core/res/res/drawable/ic_menu_invite.pngbin0 -> 2349 bytes
-rw-r--r--core/res/res/drawable/ic_menu_mark.pngbin0 -> 2519 bytes
-rw-r--r--core/res/res/drawable/ic_menu_play_clip.pngbin0 -> 1471 bytes
-rwxr-xr-xcore/res/res/drawable/ic_menu_star.pngbin0 -> 1608 bytes
-rw-r--r--core/res/res/drawable/ic_menu_start_conversation.pngbin0 -> 1715 bytes
-rw-r--r--core/res/res/drawable/ic_menu_stop.pngbin0 -> 1930 bytes
-rwxr-xr-xcore/res/res/drawable/ic_power.pngbin925 -> 0 bytes
-rw-r--r--core/res/res/layout/js_prompt.xml38
-rw-r--r--core/res/res/layout/zoom_controls.xml10
-rw-r--r--core/res/res/layout/zoom_magnify.xml7
-rw-r--r--core/res/res/values-cs/strings.xml14
-rw-r--r--core/res/res/values-de/strings.xml86
-rw-r--r--core/res/res/values-es/strings.xml14
-rw-r--r--core/res/res/values-fr/strings.xml14
-rw-r--r--core/res/res/values-it/strings.xml14
-rw-r--r--core/res/res/values-ja/strings.xml14
-rw-r--r--core/res/res/values-nl/strings.xml14
-rw-r--r--core/res/res/values-pl/strings.xml14
-rw-r--r--core/res/res/values-ru/strings.xml14
-rw-r--r--core/res/res/values-zh-rCN/strings.xml14
-rw-r--r--core/res/res/values-zh-rTW/strings.xml14
-rw-r--r--core/res/res/values/attrs.xml6
-rw-r--r--core/res/res/values/public.xml26
-rw-r--r--core/res/res/values/strings.xml20
-rw-r--r--core/res/res/values/styles.xml7
-rw-r--r--core/res/waitingroom/screen_background_blue-land.pngbin11681 -> 0 bytes
-rw-r--r--core/res/waitingroom/screen_background_green-land.pngbin9861 -> 0 bytes
-rw-r--r--core/res/waitingroom/screen_background_white-land.pngbin8332 -> 0 bytes
-rw-r--r--include/media/AudioRecord.h2
-rw-r--r--include/media/AudioTrack.h2
-rw-r--r--include/media/ToneGenerator.h2
-rw-r--r--include/private/media/AudioTrackShared.h9
-rw-r--r--include/ui/Overlay.h6
-rw-r--r--include/utils/Parcel.h13
-rw-r--r--libs/audioflinger/A2dpAudioInterface.cpp2
-rw-r--r--libs/surfaceflinger/LayerBuffer.h2
-rw-r--r--libs/ui/Camera.cpp55
-rw-r--r--libs/ui/Overlay.cpp27
-rw-r--r--libs/utils/Parcel.cpp63
-rw-r--r--media/libmedia/AudioRecord.cpp46
-rw-r--r--media/libmedia/AudioTrack.cpp82
-rw-r--r--services/java/com/android/server/GadgetService.java64
-rw-r--r--services/java/com/android/server/SystemServer.java9
-rw-r--r--services/java/com/android/server/WifiWatchdogService.java74
-rw-r--r--tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java31
-rw-r--r--tests/GadgetHost/Android.mk11
-rw-r--r--tests/GadgetHost/AndroidManifest.xml22
-rw-r--r--tests/GadgetHost/res/layout/gadget_host.xml50
-rw-r--r--tests/GadgetHost/res/layout/test_gadget.xml22
-rw-r--r--tests/GadgetHost/res/values/strings.xml22
-rw-r--r--tests/GadgetHost/src/com/android/gadgethost/GadgetContainerView.java32
-rw-r--r--tests/GadgetHost/src/com/android/gadgethost/GadgetHostActivity.java133
-rw-r--r--tests/GadgetHost/src/com/android/gadgethost/GadgetPickActivity.java70
-rw-r--r--tests/GadgetHost/src/com/android/gadgethost/TestGadgetProvider.java32
-rw-r--r--tools/aapt/ResourceTable.cpp5
130 files changed, 2729 insertions, 411 deletions
diff --git a/Android.mk b/Android.mk
index 18051aa..d67a21e 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 f6fa67d..e183217 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -8563,22 +8563,198 @@
visibility="public"
>
</field>
-<field name="gallery_thumb"
+<field name="emo_im_angel"
type="int"
transient="false"
volatile="false"
- value="17301532"
+ value="17301668"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="emo_im_cool"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301669"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="emo_im_crying"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301670"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="emo_im_embarrassed"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301671"
static="true"
final="true"
deprecated="not deprecated"
visibility="public"
>
</field>
-<field name="ic_btn_search"
+<field name="emo_im_foot_in_mouth"
type="int"
transient="false"
volatile="false"
- value="17301662"
+ value="17301672"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="emo_im_happy"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301673"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="emo_im_kissing"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301674"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="emo_im_laughing"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301675"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="emo_im_lips_are_sealed"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301676"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="emo_im_money_mouth"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301677"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="emo_im_sad"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301678"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="emo_im_surprised"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301679"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="emo_im_tongue_sticking_out"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301680"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="emo_im_undecided"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301681"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="emo_im_winking"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301682"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="emo_im_wtf"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301683"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="emo_im_yelling"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301684"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="gallery_thumb"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301532"
static="true"
final="true"
deprecated="not deprecated"
@@ -8651,17 +8827,6 @@
visibility="public"
>
</field>
-<field name="ic_dialog_menu_generic"
- type="int"
- transient="false"
- volatile="false"
- value="17301664"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="ic_input_add"
type="int"
transient="false"
@@ -9014,17 +9179,6 @@
visibility="public"
>
</field>
-<field name="ic_menu_login"
- type="int"
- transient="false"
- volatile="false"
- value="17301665"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="ic_menu_manage"
type="int"
transient="false"
@@ -9102,17 +9256,6 @@
visibility="public"
>
</field>
-<field name="ic_menu_notifications"
- type="int"
- transient="false"
- volatile="false"
- value="17301667"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="ic_menu_preferences"
type="int"
transient="false"
@@ -9135,17 +9278,6 @@
visibility="public"
>
</field>
-<field name="ic_menu_refresh"
- type="int"
- transient="false"
- volatile="false"
- value="17301666"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="ic_menu_report_image"
type="int"
transient="false"
@@ -54475,6 +54607,19 @@
<parameter name="cb" type="android.hardware.Camera.ErrorCallback">
</parameter>
</method>
+<method name="setOneShotPreviewCallback"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cb" type="android.hardware.Camera.PreviewCallback">
+</parameter>
+</method>
<method name="setParameters"
return="void"
abstract="false"
@@ -56475,6 +56620,17 @@
visibility="public"
>
</method>
+<method name="getMaxWidth"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getWindow"
return="android.app.Dialog"
abstract="false"
@@ -56558,6 +56714,23 @@
<parameter name="outInsets" type="android.inputmethodservice.InputMethodService.Insets">
</parameter>
</method>
+<method name="onConfigureWindow"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="win" type="android.view.Window">
+</parameter>
+<parameter name="isFullscreen" type="boolean">
+</parameter>
+<parameter name="isCandidatesOnly" type="boolean">
+</parameter>
+</method>
<method name="onCreateBackgroundDrawable"
return="android.graphics.drawable.Drawable"
abstract="false"
@@ -56760,6 +56933,17 @@
<parameter name="restarting" type="boolean">
</parameter>
</method>
+<method name="onUnbindInput"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="onUpdateCursor"
return="void"
abstract="false"
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 33987c3..36c5ada 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -166,22 +166,26 @@ CameraService::Client::Client(const sp<CameraService>& 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<ICameraClient>& 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<ICameraClient> 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 495156e..5af08f7 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -1129,6 +1129,15 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
}
/**
+ * 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 022a87c..b0b0154 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 905173e..c315271 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.
@@ -97,14 +101,6 @@ public class BluetoothHeadset {
}
/**
- * 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.
*/
public BluetoothHeadset(Context context, ServiceListener l) {
@@ -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 7e0226d..55ff27f 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<String> 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 564861f..582d4e3 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 6da00df..3908aa1 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1249,6 +1249,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 0000000..418f2aa
--- /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 0000000..e2bef8c
--- /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
index 03e884b..7231545 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 0000000..1a7a9a0
--- /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<GadgetInfo> CREATOR
+ = new Parcelable.Creator<GadgetInfo>()
+ {
+ 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 0000000..49c706e
--- /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.
+ *
+ * <p>
+ * The system will respond with an onActivityResult call with the following extras in
+ * the intent:
+ * <ul>
+ * <li><b>gadgetId</b></li>
+ * <li><b>gadgetId</b></li>
+ * <li><b>gadgetId</b></li>
+ * </ul>
+ * 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<Context, WeakReference<GadgetManager>> 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<GadgetManager> 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.
+ *
+ * <p>
+ * 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<GadgetInfo> 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 0000000..280ccfb
--- /dev/null
+++ b/core/java/android/gadget/package.html
@@ -0,0 +1,4 @@
+<body>
+@hide
+</body>
+
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index e2d7097..c09567c 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 21bb38e..1a7547d 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);
}
@@ -469,6 +480,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.
*/
@@ -493,6 +527,27 @@ public class InputMethodService extends AbstractInputMethodService {
}
/**
+ * 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.
+ *
+ * <p>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.
+ *
+ * <p>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.
+ *
+ * <p>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
+ * <em>not</em> 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 7b64405..a18f37c 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 0000000..58e5731
--- /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.
+ * <p>TYPE: TEXT</p>
+ */
+ public static final String WORD = "word";
+
+ /**
+ * The frequency column. A value between 1 and 255.
+ * <p>TYPE: INTEGER</p>
+ */
+ 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 <pre>en_US</pre>.
+ * <p>TYPE: TEXT</p>
+ */
+ public static final String LOCALE = "locale";
+
+ /**
+ * The uid of the application that inserted the word.
+ * <p>TYPE: INTEGER</p>
+ */
+ 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 90ef8f6..be784ff 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 749c923..a03a36a 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 0aa3cc2..a99496d 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 9d7a124..9e0289a 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 a676234..ba40782 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 cae94c9..4f8e5e4 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 30b519a..b7b40b1 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<String> {
+ private TextView mTextView;
+
+ public AutoCompleteAdapter(Context context, ArrayList<String> 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 f00238d..9cfc622 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<String> pastEntries = mDatabase.getFormData(mUrl, mName);
if (pastEntries.size() > 0) {
- ArrayAdapter<String> adapter = new ArrayAdapter<String>(
- 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<String> adapter =
- (ArrayAdapter<String>) 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 024b663..7d52901 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 6c0c164..f2cec92 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 df40156..1227afd 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 0000000..0117d1d
--- /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 0000000..db6f78b
--- /dev/null
+++ b/core/java/com/android/internal/gadget/package.html
@@ -0,0 +1,3 @@
+<body>
+{@hide}
+</body> \ 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 a7081e3..1ec74a1 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 3b11a64..558a4c3 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 e5d57ad..32513cd 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 2987602..cbc4e9f 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<MenuItemImpl>();
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 5590f1a..20ea6a6 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 e1ef459..a81f252 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -70,6 +70,10 @@ sp<Camera> 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<IMemory>& 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<Camera> 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<IMemory>& 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<IMemory>& 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<IMemory>& 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<Camera> 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 29c1f52..ded909f 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" />
+ <!-- Allows an application to read the user dictionary. This should
+ really only be required by an IME, or a dictionary editor like
+ the Settings app.
+ @hide Pending API council approval -->
+ <permission android:name="android.permission.READ_USER_DICTIONARY"
+ android:permissionGroup="android.permission-group.PERSONAL_INFO"
+ android:protectionLevel="dangerous"
+ android:label="@string/permlab_readDictionary"
+ android:description="@string/permdesc_readDictionary" />
+
+ <!-- Allows an application to write to the user dictionary.
+ @hide Pending API council approval -->
+ <permission android:name="android.permission.WRITE_USER_DICTIONARY"
+ android:permissionGroup="android.permission-group.PERSONAL_INFO"
+ android:protectionLevel="normal"
+ android:label="@string/permlab_writeDictionary"
+ android:description="@string/permdesc_writeDictionary" />
+
<!-- ======================================= -->
<!-- Permissions for accessing location info -->
<!-- ======================================= -->
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 c81e119..0000000
--- a/core/res/res/drawable/btn_check_off_longpress.png
+++ /dev/null
Binary files differ
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 367760b..0000000
--- a/core/res/res/drawable/btn_check_on_longpress.png
+++ /dev/null
Binary files differ
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 0000000..c34dfa6
--- /dev/null
+++ b/core/res/res/drawable/emo_im_angel.png
Binary files differ
diff --git a/core/res/res/drawable/emo_im_cool.png b/core/res/res/drawable/emo_im_cool.png
new file mode 100644
index 0000000..d8eeb34
--- /dev/null
+++ b/core/res/res/drawable/emo_im_cool.png
Binary files differ
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 0000000..1cafdb3
--- /dev/null
+++ b/core/res/res/drawable/emo_im_crying.png
Binary files differ
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 0000000..e4db963
--- /dev/null
+++ b/core/res/res/drawable/emo_im_embarrassed.png
Binary files differ
diff --git a/core/res/res/drawable/emo_im_foot_in_mouth.png b/core/res/res/drawable/emo_im_foot_in_mouth.png
new file mode 100644
index 0000000..09d1fba
--- /dev/null
+++ b/core/res/res/drawable/emo_im_foot_in_mouth.png
Binary files differ
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 0000000..b86602a
--- /dev/null
+++ b/core/res/res/drawable/emo_im_happy.png
Binary files differ
diff --git a/core/res/res/drawable/emo_im_kissing.png b/core/res/res/drawable/emo_im_kissing.png
new file mode 100644
index 0000000..56378f6
--- /dev/null
+++ b/core/res/res/drawable/emo_im_kissing.png
Binary files differ
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 0000000..980bf28
--- /dev/null
+++ b/core/res/res/drawable/emo_im_laughing.png
Binary files differ
diff --git a/core/res/res/drawable/emo_im_lips_are_sealed.png b/core/res/res/drawable/emo_im_lips_are_sealed.png
new file mode 100644
index 0000000..f2de993
--- /dev/null
+++ b/core/res/res/drawable/emo_im_lips_are_sealed.png
Binary files differ
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 0000000..08c53fd
--- /dev/null
+++ b/core/res/res/drawable/emo_im_money_mouth.png
Binary files differ
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 0000000..31c08d0
--- /dev/null
+++ b/core/res/res/drawable/emo_im_sad.png
Binary files differ
diff --git a/core/res/res/drawable/emo_im_surprised.png b/core/res/res/drawable/emo_im_surprised.png
new file mode 100644
index 0000000..abe8c7a
--- /dev/null
+++ b/core/res/res/drawable/emo_im_surprised.png
Binary files differ
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 0000000..6f0f47b
--- /dev/null
+++ b/core/res/res/drawable/emo_im_tongue_sticking_out.png
Binary files differ
diff --git a/core/res/res/drawable/emo_im_undecided.png b/core/res/res/drawable/emo_im_undecided.png
new file mode 100644
index 0000000..eb4f8c5
--- /dev/null
+++ b/core/res/res/drawable/emo_im_undecided.png
Binary files differ
diff --git a/core/res/res/drawable/emo_im_winking.png b/core/res/res/drawable/emo_im_winking.png
new file mode 100644
index 0000000..568562a
--- /dev/null
+++ b/core/res/res/drawable/emo_im_winking.png
Binary files differ
diff --git a/core/res/res/drawable/emo_im_wtf.png b/core/res/res/drawable/emo_im_wtf.png
new file mode 100644
index 0000000..41dd47f
--- /dev/null
+++ b/core/res/res/drawable/emo_im_wtf.png
Binary files differ
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 0000000..c3c8612
--- /dev/null
+++ b/core/res/res/drawable/emo_im_yelling.png
Binary files differ
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 0000000..f0945b2
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_account_list.png
Binary files differ
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 0000000..a5bd331
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_allfriends.png
Binary files differ
diff --git a/core/res/res/drawable/ic_menu_archive.png b/core/res/res/drawable/ic_menu_archive.png
new file mode 100644
index 0000000..a4599e3
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_archive.png
Binary files differ
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 0000000..89d626f
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_attachment.png
Binary files differ
diff --git a/core/res/res/drawable/ic_menu_back.png b/core/res/res/drawable/ic_menu_back.png
new file mode 100644
index 0000000..5ce50eb
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_back.png
Binary files differ
diff --git a/core/res/res/drawable/ic_menu_block.png b/core/res/res/drawable/ic_menu_block.png
new file mode 100644
index 0000000..422eeb1
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_block.png
Binary files differ
diff --git a/core/res/res/drawable/ic_menu_blocked_user.png b/core/res/res/drawable/ic_menu_blocked_user.png
new file mode 100644
index 0000000..5a5619b
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_blocked_user.png
Binary files differ
diff --git a/core/res/res/drawable/ic_menu_cc.png b/core/res/res/drawable/ic_menu_cc.png
new file mode 100644
index 0000000..4876021
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_cc.png
Binary files differ
diff --git a/core/res/res/drawable/ic_menu_chat_dashboard.png b/core/res/res/drawable/ic_menu_chat_dashboard.png
new file mode 100644
index 0000000..37fd3cb
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_chat_dashboard.png
Binary files differ
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 0000000..750db62
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_clear_playlist.png
Binary files differ
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 0000000..1b4733e
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_compose.png
Binary files differ
diff --git a/core/res/res/drawable/ic_menu_emoticons.png b/core/res/res/drawable/ic_menu_emoticons.png
new file mode 100644
index 0000000..e8c4e47
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_emoticons.png
Binary files differ
diff --git a/core/res/res/drawable/ic_menu_end_conversation.png b/core/res/res/drawable/ic_menu_end_conversation.png
new file mode 100644
index 0000000..0ea0fcb
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_end_conversation.png
Binary files differ
diff --git a/core/res/res/drawable/ic_menu_forward.png b/core/res/res/drawable/ic_menu_forward.png
new file mode 100644
index 0000000..0936fac
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_forward.png
Binary files differ
diff --git a/core/res/res/drawable/ic_menu_friendslist.png b/core/res/res/drawable/ic_menu_friendslist.png
new file mode 100644
index 0000000..8ec6b1a
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_friendslist.png
Binary files differ
diff --git a/core/res/res/drawable/ic_menu_goto.png b/core/res/res/drawable/ic_menu_goto.png
new file mode 100644
index 0000000..40183eb
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_goto.png
Binary files differ
diff --git a/core/res/res/drawable/ic_menu_home.png b/core/res/res/drawable/ic_menu_home.png
new file mode 100644
index 0000000..34943f6
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_home.png
Binary files differ
diff --git a/core/res/res/drawable/ic_menu_invite.png b/core/res/res/drawable/ic_menu_invite.png
new file mode 100644
index 0000000..7577e6d
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_invite.png
Binary files differ
diff --git a/core/res/res/drawable/ic_menu_mark.png b/core/res/res/drawable/ic_menu_mark.png
new file mode 100644
index 0000000..5e95da7
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_mark.png
Binary files differ
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 0000000..4669947
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_play_clip.png
Binary files differ
diff --git a/core/res/res/drawable/ic_menu_star.png b/core/res/res/drawable/ic_menu_star.png
new file mode 100755
index 0000000..527d74a
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_star.png
Binary files differ
diff --git a/core/res/res/drawable/ic_menu_start_conversation.png b/core/res/res/drawable/ic_menu_start_conversation.png
new file mode 100644
index 0000000..aadcc2f
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_start_conversation.png
Binary files differ
diff --git a/core/res/res/drawable/ic_menu_stop.png b/core/res/res/drawable/ic_menu_stop.png
new file mode 100644
index 0000000..4fc825c
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_stop.png
Binary files differ
diff --git a/core/res/res/drawable/ic_power.png b/core/res/res/drawable/ic_power.png
deleted file mode 100755
index cfdf422..0000000
--- a/core/res/res/drawable/ic_power.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/layout/js_prompt.xml b/core/res/res/layout/js_prompt.xml
new file mode 100644
index 0000000..9ab9d09
--- /dev/null
+++ b/core/res/res/layout/js_prompt.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ >
+
+ <TextView android:id="@+id/message"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ />
+
+ <EditText android:id="@+id/value"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:textStyle="bold"
+ android:selectAllOnFocus="true"
+ android:scrollHorizontally="true"
+ android:layout_marginTop="6dip"
+ />
+
+</LinearLayout>
diff --git a/core/res/res/layout/zoom_controls.xml b/core/res/res/layout/zoom_controls.xml
index ec37417..729af1b 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.
*/
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@android:drawable/zoom_plate"
- android:gravity="bottom"
- android:paddingLeft="15dip"
- android:paddingRight="15dip">
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
<ZoomButton android:id="@+id/zoomIn"
android:background="@android:drawable/btn_plus"
android:layout_width="wrap_content"
@@ -34,4 +28,4 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
- </LinearLayout>
+</merge>
diff --git a/core/res/res/layout/zoom_magnify.xml b/core/res/res/layout/zoom_magnify.xml
index b424837..08a5f7b 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.
*/
-->
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
<ZoomControls android:id="@+id/zoomControls"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ style="@style/ZoomControls"
/>
<ImageView android:id="@+id/zoomMagnify"
android:focusable="true"
@@ -35,4 +34,4 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
- </RelativeLayout>
+</merge>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 5859b9b..61a2c29 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -310,6 +310,14 @@
<string name="permdesc_subscribedFeedsRead">"Umožňuje aplikaci získat podrobnosti o aktuálně synchronizovaných zdrojích."</string>
<string name="permlab_subscribedFeedsWrite">"zápis odebíraných zdrojů"</string>
<string name="permdesc_subscribedFeedsWrite">"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ů."</string>
+ <!-- no translation found for permlab_readDictionary (432535716804748781) -->
+ <skip />
+ <!-- no translation found for permdesc_readDictionary (1082972603576360690) -->
+ <skip />
+ <!-- no translation found for permlab_writeDictionary (6703109511836343341) -->
+ <skip />
+ <!-- no translation found for permdesc_writeDictionary (2241256206524082880) -->
+ <skip />
<string-array name="phoneTypes">
<item>"Domů"</item>
<item>"Mobil"</item>
@@ -406,6 +414,12 @@
<string name="factorytest_not_system">"Test FACTORY_TEST lze provést pouze u balíčků nainstalovaných ve složce /system/app."</string>
<string name="factorytest_no_action">"Nebyl nalezen žádný balíček umožňující test FACTORY_TEST."</string>
<string name="factorytest_reboot">"Restartovat"</string>
+ <!-- no translation found for js_dialog_title (8143918455087008109) -->
+ <skip />
+ <!-- no translation found for js_dialog_title_default (6961903213729667573) -->
+ <skip />
+ <!-- no translation found for js_dialog_before_unload (1901675448179653089) -->
+ <skip />
<string name="save_password_label">"Potvrdit"</string>
<string name="save_password_message">"Chcete, aby si prohlížeč zapamatoval toto heslo?"</string>
<string name="save_password_notnow">"Nyní ne"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 0b2c7a7..44671e6 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -310,36 +310,44 @@
<string name="permdesc_subscribedFeedsRead">"Ermöglicht einer Anwendung, Details zu den zurzeit synchronisierten Feeds abzurufen."</string>
<string name="permlab_subscribedFeedsWrite">"Abonnierte Feeds schreiben"</string>
<string name="permdesc_subscribedFeedsWrite">"Ermöglicht einer Anwendung, Änderungen an den kürzlich synchronisierten Feeds vorzunehmen. Schädliche Anwendungen könnten so Ihre synchronisierten Feeds ändern."</string>
+ <!-- no translation found for permlab_readDictionary (432535716804748781) -->
+ <skip />
+ <!-- no translation found for permdesc_readDictionary (1082972603576360690) -->
+ <skip />
+ <!-- no translation found for permlab_writeDictionary (6703109511836343341) -->
+ <skip />
+ <!-- no translation found for permdesc_writeDictionary (2241256206524082880) -->
+ <skip />
<string-array name="phoneTypes">
<item>"Privat"</item>
<item>"Mobil"</item>
- <item>"Beruflich"</item>
- <item>"Beruflich (Fax)"</item>
- <item>"Faxnummer (privat)"</item>
+ <item>"Arbeit"</item>
+ <item>"Fax (Arbeit)"</item>
+ <item>"Fax (privat)"</item>
<item>"Pager"</item>
<item>"Andere"</item>
<item>"Benutzerdefiniert"</item>
</string-array>
<string-array name="emailAddressTypes">
<item>"Privat"</item>
- <item>"Beruflich"</item>
+ <item>"Arbeit"</item>
<item>"Andere"</item>
<item>"Benutzerdefiniert"</item>
</string-array>
<string-array name="postalAddressTypes">
<item>"Privat"</item>
- <item>"Beruflich"</item>
+ <item>"Arbeit"</item>
<item>"Andere"</item>
<item>"Benutzerdefiniert"</item>
</string-array>
<string-array name="imAddressTypes">
<item>"Privat"</item>
- <item>"Beruflich"</item>
+ <item>"Arbeit"</item>
<item>"Andere"</item>
<item>"Benutzerdefiniert"</item>
</string-array>
<string-array name="organizationTypes">
- <item>"Beruflich"</item>
+ <item>"Arbeit"</item>
<item>"Andere"</item>
<item>"Benutzerdefiniert"</item>
</string-array>
@@ -366,7 +374,7 @@
<string name="lockscreen_pattern_correct">"Korrekt!"</string>
<string name="lockscreen_pattern_wrong">"Tut uns leid. Versuchen Sie es noch einmal."</string>
<string name="lockscreen_plugged_in">"Wird aufgeladen (<xliff:g id="NUMBER">%d%%</xliff:g>)"</string>
- <string name="lockscreen_low_battery">"Stecken Sie Ihr Ladegerät ein."</string>
+ <string name="lockscreen_low_battery">"Bitte Ladegerät anschließen"</string>
<string name="lockscreen_missing_sim_message_short">"Keine SIM-Karte."</string>
<string name="lockscreen_missing_sim_message">"Keine SIM-Karte im Telefon."</string>
<string name="lockscreen_missing_sim_instructions">"Bitte legen Sie eine SIM-Karte ein."</string>
@@ -406,6 +414,12 @@
<string name="factorytest_not_system">"Die Aktion FACTORY_TEST wird nur für unter \"/system/app\" gespeicherte Pakete unterstützt."</string>
<string name="factorytest_no_action">"Es wurden kein Paket mit der Aktion FACTORY_TEST gefunden."</string>
<string name="factorytest_reboot">"Neu booten"</string>
+ <!-- no translation found for js_dialog_title (8143918455087008109) -->
+ <skip />
+ <!-- no translation found for js_dialog_title_default (6961903213729667573) -->
+ <skip />
+ <!-- no translation found for js_dialog_before_unload (1901675448179653089) -->
+ <skip />
<string name="save_password_label">"Bestätigen"</string>
<string name="save_password_message">"Möchten Sie, dass der Browser dieses Passwort speichert?"</string>
<string name="save_password_notnow">"Nicht jetzt"</string>
@@ -505,7 +519,7 @@
<!-- no translation found for am (4885350190794996052) -->
<skip />
<string name="pm">".."</string>
- <string name="numeric_date">"<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string>
+ <string name="numeric_date">"<xliff:g id="DAY">%d</xliff:g>/<xliff:g id="MONTH">%m</xliff:g>/<xliff:g id="YEAR">%Y</xliff:g>"</string>
<string name="wday1_date1_time1_wday2_date2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
<string name="wday1_date1_wday2_date2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DATE1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%4$s</xliff:g>, <xliff:g id="DATE2">%5$s</xliff:g>"</string>
<string name="date1_time1_date2_time2">"<xliff:g id="DATE1">%2$s</xliff:g>, <xliff:g id="TIME1">%3$s</xliff:g> – <xliff:g id="DATE2">%5$s</xliff:g>, <xliff:g id="TIME2">%6$s</xliff:g>"</string>
@@ -533,36 +547,36 @@
<skip />
<!-- no translation found for month (7026169712234774086) -->
<skip />
- <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
+ <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
<!-- no translation found for month_year (9219019380312413367) -->
<skip />
<string name="time_of_day">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g>"</string>
- <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
- <string name="same_year_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>"</string>
- <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>"</string>
- <string name="same_year_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string>
- <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR">%9$s</xliff:g>"</string>
- <string name="same_year_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="numeric_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>"</string>
- <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>"</string>
- <string name="numeric_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string>
- <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string>
- <string name="numeric_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="same_month_md1_md2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>"</string>
- <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>"</string>
- <string name="same_month_mdy1_mdy2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>"</string>
- <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>"</string>
- <string name="same_month_md1_time1_md2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="DAY1_0">%3$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="DAY2_1">%8$s</xliff:g>, <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
- <string name="abbrev_month_day_year">"<xliff:g id="MONTH">%b</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
+ <string name="date_and_time">"<xliff:g id="HOUR">%H</xliff:g>:<xliff:g id="MINUTE">%M</xliff:g>:<xliff:g id="SECOND">%S</xliff:g> <xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
+ <string name="same_year_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
+ <string name="same_year_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
+ <string name="same_year_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string>
+ <string name="same_year_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR">%9$s</xliff:g>"</string>
+ <string name="same_year_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+ <string name="same_year_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+ <string name="same_year_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+ <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+ <string name="numeric_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string>
+ <string name="numeric_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>"</string>
+ <string name="numeric_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string>
+ <string name="numeric_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>"</string>
+ <string name="numeric_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+ <string name="numeric_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+ <string name="numeric_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>/<xliff:g id="MONTH1">%2$s</xliff:g>/<xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>/<xliff:g id="MONTH2">%7$s</xliff:g>/<xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+ <string name="same_month_md1_md2">"<xliff:g id="DAY1">%3$s</xliff:g>. – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>"</string>
+ <string name="same_month_wday1_md1_wday2_md2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>"</string>
+ <string name="same_month_mdy1_mdy2">"<xliff:g id="DAY1">%3$s</xliff:g>. – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string>
+ <string name="same_month_wday1_mdy1_wday2_mdy2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>"</string>
+ <string name="same_month_md1_time1_md2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+ <string name="same_month_wday1_md1_time1_wday2_md2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+ <string name="same_month_mdy1_time1_mdy2_time2">"<xliff:g id="DAY1">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="DAY2">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+ <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">"<xliff:g id="WEEKDAY1">%1$s</xliff:g>, <xliff:g id="DAY1_0">%3$s</xliff:g>. <xliff:g id="MONTH1">%2$s</xliff:g> <xliff:g id="YEAR1">%4$s</xliff:g>, <xliff:g id="TIME1">%5$s</xliff:g> – <xliff:g id="WEEKDAY2">%6$s</xliff:g>, <xliff:g id="DAY2_1">%8$s</xliff:g>. <xliff:g id="MONTH2">%7$s</xliff:g> <xliff:g id="YEAR2">%9$s</xliff:g>, <xliff:g id="TIME2">%10$s</xliff:g>"</string>
+ <string name="abbrev_month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%b</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
<!-- no translation found for abbrev_month_year (3856424847226891943) -->
<skip />
<!-- no translation found for abbrev_month_day (5028815883653985933) -->
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 6727d5e..07a92fa 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -310,6 +310,14 @@
<string name="permdesc_subscribedFeedsRead">"Permite que una aplicación obtenga detalles sobre los feeds sincronizados en este momento."</string>
<string name="permlab_subscribedFeedsWrite">"escribir feeds a los que está suscrito el usuario"</string>
<string name="permdesc_subscribedFeedsWrite">"Permite que una aplicación modifique los feeds sincronizados actualmente. Este permiso podría provocar que una aplicación malintencionada cambie los feeds sincronizados."</string>
+ <!-- no translation found for permlab_readDictionary (432535716804748781) -->
+ <skip />
+ <!-- no translation found for permdesc_readDictionary (1082972603576360690) -->
+ <skip />
+ <!-- no translation found for permlab_writeDictionary (6703109511836343341) -->
+ <skip />
+ <!-- no translation found for permdesc_writeDictionary (2241256206524082880) -->
+ <skip />
<string-array name="phoneTypes">
<item>"Casa"</item>
<item>"Móvil"</item>
@@ -406,6 +414,12 @@
<string name="factorytest_not_system">"La acción FACTORY_TEST sólo es compatible con los paquetes instalados en /system/app."</string>
<string name="factorytest_no_action">"No se ha encontrado ningún paquete que proporcione la acción FACTORY_TEST."</string>
<string name="factorytest_reboot">"Reiniciar"</string>
+ <!-- no translation found for js_dialog_title (8143918455087008109) -->
+ <skip />
+ <!-- no translation found for js_dialog_title_default (6961903213729667573) -->
+ <skip />
+ <!-- no translation found for js_dialog_before_unload (1901675448179653089) -->
+ <skip />
<string name="save_password_label">"Confirmar"</string>
<string name="save_password_message">"¿Deseas que el navegador recuerde esta contraseña?"</string>
<string name="save_password_notnow">"Ahora no"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 600bc2c..0f58ba1 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -310,6 +310,14 @@
<string name="permdesc_subscribedFeedsRead">"Permet à une application d\'obtenir des informations sur les flux récemment synchronisés."</string>
<string name="permlab_subscribedFeedsWrite">"Écrire les flux auxquels vous êtes abonné"</string>
<string name="permdesc_subscribedFeedsWrite">"Permet à une application de modifier vos flux synchronisés actuels. Cette fonctionnalité peut permettre à des applications malveillantes de modifier vos flux synchronisés."</string>
+ <!-- no translation found for permlab_readDictionary (432535716804748781) -->
+ <skip />
+ <!-- no translation found for permdesc_readDictionary (1082972603576360690) -->
+ <skip />
+ <!-- no translation found for permlab_writeDictionary (6703109511836343341) -->
+ <skip />
+ <!-- no translation found for permdesc_writeDictionary (2241256206524082880) -->
+ <skip />
<string-array name="phoneTypes">
<item>"Accueil"</item>
<item>"Mobile"</item>
@@ -406,6 +414,12 @@
<string name="factorytest_not_system">"L\'action FACTORY_TEST est uniquement prise en charge pour les paquets de données installés dans in/system/app."</string>
<string name="factorytest_no_action">"Impossible de trouver un paquet proposant l\'action FACTORY_TEST."</string>
<string name="factorytest_reboot">"Redémarrer"</string>
+ <!-- no translation found for js_dialog_title (8143918455087008109) -->
+ <skip />
+ <!-- no translation found for js_dialog_title_default (6961903213729667573) -->
+ <skip />
+ <!-- no translation found for js_dialog_before_unload (1901675448179653089) -->
+ <skip />
<string name="save_password_label">"Confirmer"</string>
<string name="save_password_message">"Voulez-vous que le navigateur se souvienne de ce mot de passe ?"</string>
<string name="save_password_notnow">"Pas maintenant"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index b41d449..8b96f89 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -310,6 +310,14 @@
<string name="permdesc_subscribedFeedsRead">"Consente a un\'applicazione di ottenere dettagli sui feed attualmente sincronizzati."</string>
<string name="permlab_subscribedFeedsWrite">"scrivere feed sottoscritti"</string>
<string name="permdesc_subscribedFeedsWrite">"Consente la modifica da parte di un\'applicazione dei feed attualmente sincronizzati. Le applicazioni dannose potrebbero essere in grado di modificare i feed sincronizzati."</string>
+ <!-- no translation found for permlab_readDictionary (432535716804748781) -->
+ <skip />
+ <!-- no translation found for permdesc_readDictionary (1082972603576360690) -->
+ <skip />
+ <!-- no translation found for permlab_writeDictionary (6703109511836343341) -->
+ <skip />
+ <!-- no translation found for permdesc_writeDictionary (2241256206524082880) -->
+ <skip />
<string-array name="phoneTypes">
<item>"Casa"</item>
<item>"Cellulare"</item>
@@ -406,6 +414,12 @@
<string name="factorytest_not_system">"L\'azione FACTORY_TEST è supportata soltanto per i pacchetti installati in /system/app."</string>
<string name="factorytest_no_action">"Nessun pacchetto trovato che fornisca l\'azione FACTORY_TEST."</string>
<string name="factorytest_reboot">"Riavvia"</string>
+ <!-- no translation found for js_dialog_title (8143918455087008109) -->
+ <skip />
+ <!-- no translation found for js_dialog_title_default (6961903213729667573) -->
+ <skip />
+ <!-- no translation found for js_dialog_before_unload (1901675448179653089) -->
+ <skip />
<string name="save_password_label">"Conferma"</string>
<string name="save_password_message">"Memorizzare la password nel browser?"</string>
<string name="save_password_notnow">"Non ora"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 93b66f3..0735837 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -310,6 +310,14 @@
<string name="permdesc_subscribedFeedsRead">"現在同期しているフィードの詳細の取得をアプリケーションに許可します。"</string>
<string name="permlab_subscribedFeedsWrite">"登録したフィードの書き込み"</string>
<string name="permdesc_subscribedFeedsWrite">"現在同期しているフィードの変更をアプリケーションに許可します。悪意のあるアプリケーションが同期フィードを変更する恐れがあります。"</string>
+ <!-- no translation found for permlab_readDictionary (432535716804748781) -->
+ <skip />
+ <!-- no translation found for permdesc_readDictionary (1082972603576360690) -->
+ <skip />
+ <!-- no translation found for permlab_writeDictionary (6703109511836343341) -->
+ <skip />
+ <!-- no translation found for permdesc_writeDictionary (2241256206524082880) -->
+ <skip />
<string-array name="phoneTypes">
<item>"自宅"</item>
<item>"携帯"</item>
@@ -406,6 +414,12 @@
<string name="factorytest_not_system">"FACTORY_TEST操作は、/system/appにインストールされたパッケージのみが対象です。"</string>
<string name="factorytest_no_action">"FACTORY_TEST操作を行うパッケージは見つかりませんでした。"</string>
<string name="factorytest_reboot">"再起動"</string>
+ <!-- no translation found for js_dialog_title (8143918455087008109) -->
+ <skip />
+ <!-- no translation found for js_dialog_title_default (6961903213729667573) -->
+ <skip />
+ <!-- no translation found for js_dialog_before_unload (1901675448179653089) -->
+ <skip />
<string name="save_password_label">"確認"</string>
<string name="save_password_message">"このパスワードをブラウザで保存しますか?"</string>
<string name="save_password_notnow">"今は保存しない"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 54a7321..9426f35 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -310,6 +310,14 @@
<string name="permdesc_subscribedFeedsRead">"Hiermee kan een toepassing details over de huidige gesynchroniseerde feeds achterhalen."</string>
<string name="permlab_subscribedFeedsWrite">"geabonneerde feeds schrijven"</string>
<string name="permdesc_subscribedFeedsWrite">"Hiermee kan een toepassing uw huidige gesynchroniseerde feeds wijzigen. Een schadelijke toepassing kan op deze manier uw gesynchroniseerde feeds wijzigen."</string>
+ <!-- no translation found for permlab_readDictionary (432535716804748781) -->
+ <skip />
+ <!-- no translation found for permdesc_readDictionary (1082972603576360690) -->
+ <skip />
+ <!-- no translation found for permlab_writeDictionary (6703109511836343341) -->
+ <skip />
+ <!-- no translation found for permdesc_writeDictionary (2241256206524082880) -->
+ <skip />
<string-array name="phoneTypes">
<item>"Thuis"</item>
<item>"Mobiel"</item>
@@ -406,6 +414,12 @@
<string name="factorytest_not_system">"De actie FACTORY_TEST wordt alleen ondersteund voor pakketten die zijn geïnstalleerd in /system/app."</string>
<string name="factorytest_no_action">"Er is geen pakket gevonden dat de actie FACTORY_TEST levert."</string>
<string name="factorytest_reboot">"Opnieuw opstarten"</string>
+ <!-- no translation found for js_dialog_title (8143918455087008109) -->
+ <skip />
+ <!-- no translation found for js_dialog_title_default (6961903213729667573) -->
+ <skip />
+ <!-- no translation found for js_dialog_before_unload (1901675448179653089) -->
+ <skip />
<string name="save_password_label">"Bevestigen"</string>
<string name="save_password_message">"Wilt u dat de browser dit wachtwoord onthoudt?"</string>
<string name="save_password_notnow">"Niet nu"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index c3cf8a1..d76922f 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -310,6 +310,14 @@
<string name="permdesc_subscribedFeedsRead">"Pozwala aplikacjom na pobieranie informacji szczegółowych na temat obecnie zsynchronizowanych źródeł."</string>
<string name="permlab_subscribedFeedsWrite">"zapisywanie subskrybowanych źródeł"</string>
<string name="permdesc_subscribedFeedsWrite">"Umożliwia aplikacji zmianę obecnie zsynchronizowanych źródeł. Może to pozwolić szkodliwej aplikacji na zmianę zsynchronizowanych źródeł."</string>
+ <!-- no translation found for permlab_readDictionary (432535716804748781) -->
+ <skip />
+ <!-- no translation found for permdesc_readDictionary (1082972603576360690) -->
+ <skip />
+ <!-- no translation found for permlab_writeDictionary (6703109511836343341) -->
+ <skip />
+ <!-- no translation found for permdesc_writeDictionary (2241256206524082880) -->
+ <skip />
<string-array name="phoneTypes">
<item>"Strona główna"</item>
<item>"Komórka"</item>
@@ -406,6 +414,12 @@
<string name="factorytest_not_system">"Czynność FACTORY_TEST jest obsługiwana tylko dla pakietów zainstalowanych w katalogu /system/app."</string>
<string name="factorytest_no_action">"Nie znaleziono żadnego pakietu, który zapewnia działanie FACTORY_TEST."</string>
<string name="factorytest_reboot">"Uruchom ponownie"</string>
+ <!-- no translation found for js_dialog_title (8143918455087008109) -->
+ <skip />
+ <!-- no translation found for js_dialog_title_default (6961903213729667573) -->
+ <skip />
+ <!-- no translation found for js_dialog_before_unload (1901675448179653089) -->
+ <skip />
<string name="save_password_label">"Potwierdź"</string>
<string name="save_password_message">"Czy chcesz, aby zapamiętać to hasło w przeglądarce?"</string>
<string name="save_password_notnow">"Nie teraz"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 8d362bd..a00973f 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -310,6 +310,14 @@
<string name="permdesc_subscribedFeedsRead">"Позволяет приложению получать сведения о синхронизированных фидах."</string>
<string name="permlab_subscribedFeedsWrite">"записывать фиды с подпиской"</string>
<string name="permdesc_subscribedFeedsWrite">"Разрешает приложению изменять ваши синхронизированные фиды. Это может позволить вредоносному ПО изменять ваши синхронизированные фиды."</string>
+ <!-- no translation found for permlab_readDictionary (432535716804748781) -->
+ <skip />
+ <!-- no translation found for permdesc_readDictionary (1082972603576360690) -->
+ <skip />
+ <!-- no translation found for permlab_writeDictionary (6703109511836343341) -->
+ <skip />
+ <!-- no translation found for permdesc_writeDictionary (2241256206524082880) -->
+ <skip />
<string-array name="phoneTypes">
<item>"Домашний"</item>
<item>"Мобильный"</item>
@@ -406,6 +414,12 @@
<string name="factorytest_not_system">"Действие FACTORY_TEST поддерживается только для пакетов, установленных в папке /system/app."</string>
<string name="factorytest_no_action">"Пакет, предоставляющий действие FACTORY_TEST, не найден."</string>
<string name="factorytest_reboot">"Перезагрузить"</string>
+ <!-- no translation found for js_dialog_title (8143918455087008109) -->
+ <skip />
+ <!-- no translation found for js_dialog_title_default (6961903213729667573) -->
+ <skip />
+ <!-- no translation found for js_dialog_before_unload (1901675448179653089) -->
+ <skip />
<string name="save_password_label">"Подтверждение"</string>
<string name="save_password_message">"Сохранить этот пароль в браузере?"</string>
<string name="save_password_notnow">"Не сейчас"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 27b8fea..87bd4e4 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -310,6 +310,14 @@
<string name="permdesc_subscribedFeedsRead">"允许应用程序获取有关当前同步的供稿的详情。"</string>
<string name="permlab_subscribedFeedsWrite">"写入订阅的供稿"</string>
<string name="permdesc_subscribedFeedsWrite">"允许应用程序修改您当前同步的供稿。这样恶意程序可以更改您同步的供稿。"</string>
+ <!-- no translation found for permlab_readDictionary (432535716804748781) -->
+ <skip />
+ <!-- no translation found for permdesc_readDictionary (1082972603576360690) -->
+ <skip />
+ <!-- no translation found for permlab_writeDictionary (6703109511836343341) -->
+ <skip />
+ <!-- no translation found for permdesc_writeDictionary (2241256206524082880) -->
+ <skip />
<string-array name="phoneTypes">
<item>"家庭"</item>
<item>"手机"</item>
@@ -406,6 +414,12 @@
<string name="factorytest_not_system">"只有在 /system/app 中安装的包支持 FACTORY_TEST 操作。"</string>
<string name="factorytest_no_action">"未发现支持 FACTORY_TEST 操作的包。"</string>
<string name="factorytest_reboot">"重新引导"</string>
+ <!-- no translation found for js_dialog_title (8143918455087008109) -->
+ <skip />
+ <!-- no translation found for js_dialog_title_default (6961903213729667573) -->
+ <skip />
+ <!-- no translation found for js_dialog_before_unload (1901675448179653089) -->
+ <skip />
<string name="save_password_label">"确认"</string>
<string name="save_password_message">"是否希望浏览器记住此密码?"</string>
<string name="save_password_notnow">"暂不保存"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index b95ca98..fbe8c55 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -310,6 +310,14 @@
<string name="permdesc_subscribedFeedsRead">"允許應用程式取得目前已同步處理的資訊提供。"</string>
<string name="permlab_subscribedFeedsWrite">"寫入訂閱資訊提供"</string>
<string name="permdesc_subscribedFeedsWrite">"允許應用程式修改已同步處理的資訊提供。惡意程式可使用此功能變更已同步處理的資訊提供。"</string>
+ <!-- no translation found for permlab_readDictionary (432535716804748781) -->
+ <skip />
+ <!-- no translation found for permdesc_readDictionary (1082972603576360690) -->
+ <skip />
+ <!-- no translation found for permlab_writeDictionary (6703109511836343341) -->
+ <skip />
+ <!-- no translation found for permdesc_writeDictionary (2241256206524082880) -->
+ <skip />
<string-array name="phoneTypes">
<item>"首頁"</item>
<item>"行動"</item>
@@ -406,6 +414,12 @@
<string name="factorytest_not_system">"FACTORY_TEST 動作只支援安裝在 /system/app 裡的程式。"</string>
<string name="factorytest_no_action">"找不到提供 FACTORY_TEST 的程式。"</string>
<string name="factorytest_reboot">"重新開機"</string>
+ <!-- no translation found for js_dialog_title (8143918455087008109) -->
+ <skip />
+ <!-- no translation found for js_dialog_title_default (6961903213729667573) -->
+ <skip />
+ <!-- no translation found for js_dialog_before_unload (1901675448179653089) -->
+ <skip />
<string name="save_password_label">"確認"</string>
<string name="save_password_message">"是否記憶此密碼?"</string>
<string name="save_password_notnow">"現在不要"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 1704179..2562a8a 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2468,7 +2468,7 @@
<!-- ***************************************************************** -->
<eat-comment />
- <!-- Searchable activities &amp; applications must provide search configuration information
+ <!-- Searchable activities and applications must provide search configuration information
in an XML file, typically called searchable.xml. This file is referenced in your manifest.
For a more in-depth discussion of search configuration, please refer to
{@link android.app.SearchManager}. -->
@@ -2601,9 +2601,7 @@
<!-- The set of attributes for a MapView. -->
<declare-styleable name="MapView">
- <!-- An API Key required to use MapView. Currently, this can be an arbitrary string.
- In order to run on actual devices, though, your app will need an authentic key, but
- the process for issuing keys is not ready at this time. -->
+ <!-- Value is a string that specifies the Maps API Key to use. -->
<attr name="apiKey" format="string" />
</declare-styleable>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index cb364e6..f25d829 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -748,7 +748,7 @@
<public type="drawable" name="btn_plus" id="0x01080008" />
<public type="drawable" name="btn_radio" id="0x01080009" />
<public type="drawable" name="btn_star" id="0x0108000a" />
- <public type="drawable" name="btn_star_big_off" id="0x0108000b" />
+ <public type="drawable" name="btn_star_big_off" id="0x0108000b" />
<public type="drawable" name="btn_star_big_on" id="0x0108000c" />
<public type="drawable" name="button_onoff_indicator_on" id="0x0108000d" />
<public type="drawable" name="button_onoff_indicator_off" id="0x0108000e" />
@@ -1034,10 +1034,22 @@
<public type="style" name="Theme.NoDisplay" id="0x01030055" />
<public type="style" name="Animation.InputMethod" id="0x01030056" />
<public type="style" name="Widget.KeyboardView" id="0x01030057" />
-
- <public type="drawable" name="ic_btn_search" id="0x0108009e" />
- <public type="drawable" name="ic_dialog_menu_generic" id="0x010800a0" />
- <public type="drawable" name="ic_menu_login" id="0x010800a1" />
- <public type="drawable" name="ic_menu_refresh" id="0x010800a2" />
- <public type="drawable" name="ic_menu_notifications" id="0x010800a3" />
+
+ <public type="drawable" name="emo_im_angel" id="0x010800a4" />
+ <public type="drawable" name="emo_im_cool" id="0x010800a5" />
+ <public type="drawable" name="emo_im_crying" id="0x010800a6" />
+ <public type="drawable" name="emo_im_embarrassed" id="0x010800a7" />
+ <public type="drawable" name="emo_im_foot_in_mouth" id="0x010800a8" />
+ <public type="drawable" name="emo_im_happy" id="0x010800a9" />
+ <public type="drawable" name="emo_im_kissing" id="0x010800aa" />
+ <public type="drawable" name="emo_im_laughing" id="0x010800ab" />
+ <public type="drawable" name="emo_im_lips_are_sealed" id="0x010800ac" />
+ <public type="drawable" name="emo_im_money_mouth" id="0x010800ad" />
+ <public type="drawable" name="emo_im_sad" id="0x010800ae" />
+ <public type="drawable" name="emo_im_surprised" id="0x010800af" />
+ <public type="drawable" name="emo_im_tongue_sticking_out" id="0x010800b0" />
+ <public type="drawable" name="emo_im_undecided" id="0x010800b1" />
+ <public type="drawable" name="emo_im_winking" id="0x010800b2" />
+ <public type="drawable" name="emo_im_wtf" id="0x010800b3" />
+ <public type="drawable" name="emo_im_yelling" id="0x010800b4" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f9e2e0f..978a024 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.</string>
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_readDictionary">read user defined dictionary</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_readDictionary">Allows an application to read any private
+ words, names and phrases that the user may have stored in the user dictionary.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permlab_writeDictionary">write to user defined dictionary</string>
+ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+ <string name="permdesc_writeDictionary">Allows an application to write new words into the
+ user dictionary.</string>
+
<!-- The order of these is important, don't reorder without changing Contacts.java --> <skip />
<!-- Phone number types from android.provider.Contacts. This could be used when adding a new phone number for a contact, for example. -->
<string-array name="phoneTypes">
@@ -1216,6 +1228,14 @@
<string name="web_user_agent"><xliff:g id="x">Mozilla/5.0 (Linux; U; Android %s)
AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1</xliff:g></string>
+ <!-- Title for a JavaScript dialog. "The page at <url of current page> says:" -->
+ <string name="js_dialog_title">The page at \'<xliff:g id="title">%s</xliff:g>\' says:</string>
+ <!-- Default title for a javascript dialog -->
+ <string name="js_dialog_title_default">JavaScript</string>
+ <!-- Message in a javascript dialog asking if the user wishes to leave the
+ current page -->
+ <string name="js_dialog_before_unload">Navigate away from this page?\n\n<xliff:g id="message">%s</xliff:g>\n\nSelect OK to continue, or Cancel to stay on the current page.</string>
+
<!-- Title of the WebView save password dialog. If the user enters a password in a form on a website, a dialog will come up asking if they want to save the password. -->
<string name="save_password_label">Confirm</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index bc300c3..73e7dd0 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -627,4 +627,11 @@
<item name="android:shadowColor">#BB000000</item>
<item name="android:shadowRadius">2.75</item>
</style>
+
+ <style name="ZoomControls">
+ <item name="android:background">@android:drawable/zoom_plate</item>
+ <item name="android:gravity">bottom</item>
+ <item name="android:paddingLeft">15dip</item>
+ <item name="android:paddingRight">15dip</item>
+ </style>
</resources>
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 50e46b1..0000000
--- a/core/res/waitingroom/screen_background_blue-land.png
+++ /dev/null
Binary files differ
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 f46afa1..0000000
--- a/core/res/waitingroom/screen_background_green-land.png
+++ /dev/null
Binary files differ
diff --git a/core/res/waitingroom/screen_background_white-land.png b/core/res/waitingroom/screen_background_white-land.png
deleted file mode 100644
index a179c38..0000000
--- a/core/res/waitingroom/screen_background_white-land.png
+++ /dev/null
Binary files differ
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 71744be..dd585c9 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -275,7 +275,7 @@ public:
STOPPED = 1
};
- status_t obtainBuffer(Buffer* audioBuffer, bool blocking);
+ status_t obtainBuffer(Buffer* audioBuffer, int32_t waitCount);
void releaseBuffer(Buffer* audioBuffer);
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index f382451..fd62daa 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -358,7 +358,7 @@ public:
STOPPED = 1
};
- status_t obtainBuffer(Buffer* audioBuffer, bool blocking);
+ status_t obtainBuffer(Buffer* audioBuffer, int32_t waitCount);
void releaseBuffer(Buffer* audioBuffer);
diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h
index 0ddfb8e..0cfdeec7 100644
--- a/include/media/ToneGenerator.h
+++ b/include/media/ToneGenerator.h
@@ -134,7 +134,7 @@ private:
Condition mWaitCbkCond; // condition enabling interface to wait for audio callback completion after a change is requested
float mVolume; // Volume applied to audio track
int mStreamType; // Audio stream used for output
- int mProcessSize; // Size of audio blocks generated at a time by audioCallback() (in PCM frames).
+ unsigned int mProcessSize; // Size of audio blocks generated at a time by audioCallback() (in PCM frames).
bool initAudioTrack();
static void audioCallback(int event, void* user, void *info);
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 72ed281..1991aa7 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -28,6 +28,11 @@ namespace android {
#define MAX_SAMPLE_RATE 65535
#define THREAD_PRIORITY_AUDIO_CLIENT (ANDROID_PRIORITY_AUDIO)
+// Maximum cumulated timeout milliseconds before restarting audioflinger thread
+#define MAX_STARTUP_TIMEOUT_MS 3000 // Longer timeout period at startup to cope with A2DP init time
+#define MAX_RUN_TIMEOUT_MS 1000
+#define WAIT_PERIOD_MS 10
+
struct audio_track_cblk_t
{
@@ -55,9 +60,11 @@ struct audio_track_cblk_t
int16_t flowControlFlag; // underrun (out) or overrrun (in) indication
uint8_t out; // out equals 1 for AudioTrack and 0 for AudioRecord
uint8_t forceReady;
+ uint16_t bufferTimeoutMs; // Maximum cumulated timeout before restarting audioflinger
+ uint16_t waitTimeMs; // Cumulated wait time
// Padding ensuring that data buffer starts on a cache line boundary (32 bytes).
// See AudioFlinger::TrackBase constructor
- int32_t Padding[4];
+ int32_t Padding[3];
audio_track_cblk_t();
uint32_t stepUser(uint32_t frameCount);
diff --git a/include/ui/Overlay.h b/include/ui/Overlay.h
index 9c7bc47..f8454fd 100644
--- a/include/ui/Overlay.h
+++ b/include/ui/Overlay.h
@@ -40,7 +40,7 @@ class IMemoryHeap;
class OverlayRef : public LightRefBase<OverlayRef>
{
public:
- OverlayRef(overlay_handle_t const*, const sp<IOverlay>&,
+ OverlayRef(overlay_handle_t, const sp<IOverlay>&,
uint32_t w, uint32_t h, int32_t f, uint32_t ws, uint32_t hs);
static sp<OverlayRef> readFromParcel(const Parcel& data);
@@ -53,7 +53,7 @@ private:
OverlayRef();
virtual ~OverlayRef();
- overlay_handle_t const *mOverlayHandle;
+ overlay_handle_t mOverlayHandle;
sp<IOverlay> 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 7c451ab..9087c44 100644
--- a/include/utils/Parcel.h
+++ b/include/utils/Parcel.h
@@ -17,6 +17,7 @@
#ifndef ANDROID_PARCEL_H
#define ANDROID_PARCEL_H
+#include <cutils/native_handle.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/String16.h>
@@ -78,6 +79,9 @@ public:
status_t writeString16(const char16_t* str, size_t len);
status_t writeStrongBinder(const sp<IBinder>& val);
status_t writeWeakBinder(const wp<IBinder>& 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<IBinder> readStrongBinder() const;
wp<IBinder> 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 7242575..c8c8431 100644
--- a/libs/audioflinger/A2dpAudioInterface.cpp
+++ b/libs/audioflinger/A2dpAudioInterface.cpp
@@ -126,7 +126,7 @@ status_t A2dpAudioInterface::dump(int fd, const Vector<String16>& 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 3286535..6e3d49f 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 4a325ac..50c6008 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 <ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->connect(this);
}
sp<ICamera> Camera::remote()
@@ -138,14 +137,16 @@ sp<ICamera> Camera::remote()
status_t Camera::lock()
{
- if (mCamera != 0) return mCamera->lock();
- return NO_INIT;
+ sp <ICamera> 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 <ICamera> 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>& surface)
LOGE("app passed NULL surface");
return NO_INIT;
}
- return mCamera->setPreviewDisplay(surface->getISurface());
+ sp <ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->setPreviewDisplay(surface->getISurface());
}
status_t Camera::setPreviewDisplay(const sp<ISurface>& surface)
@@ -166,7 +169,9 @@ status_t Camera::setPreviewDisplay(const sp<ISurface>& surface)
LOGE("app passed NULL surface");
return NO_INIT;
}
- return mCamera->setPreviewDisplay(surface);
+ sp <ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->setPreviewDisplay(surface);
}
@@ -174,48 +179,62 @@ status_t Camera::setPreviewDisplay(const sp<ISurface>& surface)
status_t Camera::startPreview()
{
LOGV("startPreview");
- return mCamera->startPreview();
+ sp <ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->startPreview();
}
// stop preview mode
void Camera::stopPreview()
{
LOGV("stopPreview");
- mCamera->stopPreview();
+ sp <ICamera> c = mCamera;
+ if (c == 0) return;
+ c->stopPreview();
}
// get preview state
bool Camera::previewEnabled()
{
LOGV("previewEnabled");
- return mCamera->previewEnabled();
+ sp <ICamera> c = mCamera;
+ if (c == 0) return false;
+ return c->previewEnabled();
}
status_t Camera::autoFocus()
{
LOGV("autoFocus");
- return mCamera->autoFocus();
+ sp <ICamera> c = mCamera;
+ if (c == 0) return NO_INIT;
+ return c->autoFocus();
}
// take a picture
status_t Camera::takePicture()
{
LOGV("takePicture");
- return mCamera->takePicture();
+ sp <ICamera> 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 <ICamera> 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 <ICamera> 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 <ICamera> c = mCamera;
+ if (c == 0) return;
mCamera->setFrameCallbackFlag(frame_callback_flag);
}
diff --git a/libs/ui/Overlay.cpp b/libs/ui/Overlay.cpp
index 2745f52..c8e6168 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<IOverlay>& channel,
+OverlayRef::OverlayRef(overlay_handle_t handle, const sp<IOverlay>& 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 ; i<mOverlayHandle->numFds ; i++) {
- close(mOverlayHandle->fds[i]);
+ close(mOverlayHandle->data[i]);
}
free((void*)mOverlayHandle);
}
@@ -141,16 +141,8 @@ sp<OverlayRef> 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 ; i<numfd ; i++)
- handle->fds[i] = data.readFileDescriptor();
- for (int i=0 ; i<numint ; i++)
- handle->data[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<OverlayRef>& 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 ; i<o->mOverlayHandle->numFds ; i++)
- reply->writeFileDescriptor(o->mOverlayHandle->fds[i]);
- for (int i=0 ; i<o->mOverlayHandle->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 3eca4b0..0eba0b0 100644
--- a/libs/utils/Parcel.cpp
+++ b/libs/utils/Parcel.cpp
@@ -650,6 +650,26 @@ status_t Parcel::writeWeakBinder(const wp<IBinder>& 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<handle.numFds ; i++)
+ err = writeDupFileDescriptor(handle.data[i]);
+
+ err = write(handle.data + handle.numFds, sizeof(int)*handle.numInts);
+
+ return err;
+}
+
status_t Parcel::writeFileDescriptor(int fd)
{
flat_binder_object obj;
@@ -902,6 +922,47 @@ wp<IBinder> 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 && i<numFds ; i++) {
+ h->data[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<const flat_binder_object*>(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 bbb9548..3d39181 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<ClientRecordThread>& 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<ClientRecordThread>& 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<ClientRecordThread>& 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 ce65312..f9f8568 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<AudioTrackThread>& 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<AudioTrackThread>& 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<AudioTrackThread>& 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 0000000..4e49253
--- /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 baf57bc..7f7a52e 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 9578c2e..fe97b93 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 7a4c78f..663b7a4 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 0000000..1d88db8
--- /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 0000000..8da4485
--- /dev/null
+++ b/tests/GadgetHost/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.gadgethost">
+ <uses-permission android:name="android.permission.VIBRATE" />
+
+ <application>
+ <activity android:name="GadgetHostActivity" android:label="_GadgetHost">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name="GadgetPickActivity">
+ <intent-filter>
+ <action android:name="android.gadget.action.PICK_GADGET" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+ <receiver android:name="TestGadgetProvider">
+ </receiver>
+ </application>
+</manifest>
diff --git a/tests/GadgetHost/res/layout/gadget_host.xml b/tests/GadgetHost/res/layout/gadget_host.xml
new file mode 100644
index 0000000..824cc44
--- /dev/null
+++ b/tests/GadgetHost/res/layout/gadget_host.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/gadget_view_title"
+ />
+
+ <ScrollView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ >
+
+ <com.android.gadgethost.GadgetContainerView
+ android:id="@+id/gadget_container"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ />
+
+ </ScrollView>
+
+ <Button
+ android:id="@+id/add_gadget"
+ android:text="@string/add_gadget"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ />
+
+</LinearLayout>
+
diff --git a/tests/GadgetHost/res/layout/test_gadget.xml b/tests/GadgetHost/res/layout/test_gadget.xml
new file mode 100644
index 0000000..0fb7929
--- /dev/null
+++ b/tests/GadgetHost/res/layout/test_gadget.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/oh_hai"
+/>
+
diff --git a/tests/GadgetHost/res/values/strings.xml b/tests/GadgetHost/res/values/strings.xml
new file mode 100644
index 0000000..d94cfbd
--- /dev/null
+++ b/tests/GadgetHost/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+ <string name="gadget_view_title">Gadget Test</string>
+ <string name="add_gadget">Add Gadget</string>
+ <string name="oh_hai">Oh hai.</string>
+</resources>
+
diff --git a/tests/GadgetHost/src/com/android/gadgethost/GadgetContainerView.java b/tests/GadgetHost/src/com/android/gadgethost/GadgetContainerView.java
new file mode 100644
index 0000000..159cbe4
--- /dev/null
+++ b/tests/GadgetHost/src/com/android/gadgethost/GadgetContainerView.java
@@ -0,0 +1,32 @@
+/*
+ * 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.gadgethost;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.LinearLayout;
+
+public class GadgetContainerView extends LinearLayout
+{
+ public GadgetContainerView(Context context) {
+ super(context);
+ }
+
+ public GadgetContainerView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+}
diff --git a/tests/GadgetHost/src/com/android/gadgethost/GadgetHostActivity.java b/tests/GadgetHost/src/com/android/gadgethost/GadgetHostActivity.java
new file mode 100644
index 0000000..323141e
--- /dev/null
+++ b/tests/GadgetHost/src/com/android/gadgethost/GadgetHostActivity.java
@@ -0,0 +1,133 @@
+/*
+ * 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.gadgethost;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.gadget.GadgetHost;
+import android.gadget.GadgetHostView;
+import android.gadget.GadgetInfo;
+import android.gadget.GadgetManager;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.ContextMenu;
+import android.view.View;
+import android.widget.LinearLayout;
+
+public class GadgetHostActivity extends Activity
+{
+ static final String TAG = "GadgetHostActivity";
+
+ static final int DISCOVER_GADGET_REQUEST = 1;
+
+ GadgetManager mGadgetManager;
+ GadgetContainerView mGadgetContainer;
+
+ public GadgetHostActivity() {
+ mGadgetManager = GadgetManager.getInstance(this);
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setContentView(R.layout.gadget_host);
+
+ findViewById(R.id.add_gadget).setOnClickListener(mOnClickListener);
+ mGadgetContainer = (GadgetContainerView)findViewById(R.id.gadget_container);
+ }
+
+ View.OnClickListener mOnClickListener = new View.OnClickListener() {
+ public void onClick(View v) {
+ discoverGadget(DISCOVER_GADGET_REQUEST);
+ }
+ };
+
+ void discoverGadget(int requestCode) {
+ Intent intent = new Intent(GadgetManager.GADGET_PICK_ACTION);
+ startActivityForResult(intent, requestCode);
+ }
+
+ void handleGadgetPickResult(int resultCode, Intent data) {
+ if (resultCode == RESULT_OK) {
+ Bundle extras = data.getExtras();
+ int gadgetId = extras.getInt(GadgetManager.EXTRA_GADGET_ID);
+ GadgetInfo gadget = mGadgetManager.getGadgetInfo(gadgetId);
+
+ if (gadget.configure != null) {
+ // configure the gadget if we should
+
+ // TODO: start the activity. Watch for a cancel result. If it returns
+ // RESULT_CANCELED, then remove the gadget.
+ } else {
+ // just add it as is
+ addGadgetView(gadgetId, gadget);
+ }
+ }
+ }
+
+ void addGadgetView(int gadgetId, GadgetInfo gadget) {
+ // TODO: Remove this hard-coded value when the GadgetInfo is real.
+ gadget.initialLayout = R.layout.test_gadget;
+
+ // Inflate the gadget's RemoteViews
+ GadgetHostView view = mHost.createView(this, gadgetId, gadget);
+
+ // Add it to the list
+ LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
+ 65, // LinearLayout.LayoutParams.WRAP_CONTENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT);
+ mGadgetContainer.addView(view, layoutParams);
+ }
+
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ switch (requestCode) {
+ case DISCOVER_GADGET_REQUEST:
+ handleGadgetPickResult(resultCode, data);
+ break;
+ }
+ }
+
+ protected void onStart() {
+ super.onStart();
+ mHost.startListening();
+ }
+
+ protected void onStop() {
+ super.onStop();
+ mHost.stopListening();
+ }
+
+ class MyGadgetView extends GadgetHostView {
+ MyGadgetView() {
+ super(GadgetHostActivity.this);
+ }
+
+ public void createContextMenu(ContextMenu menu) {
+ menu.add("Delete");
+ }
+ }
+
+ GadgetHost mHost = new GadgetHost(this, 0) {
+ protected GadgetHostView onCreateView(Context context, int gadgetId, GadgetInfo gadget) {
+ return new MyGadgetView();
+ }
+ };
+
+}
+
+
diff --git a/tests/GadgetHost/src/com/android/gadgethost/GadgetPickActivity.java b/tests/GadgetHost/src/com/android/gadgethost/GadgetPickActivity.java
new file mode 100644
index 0000000..e8b3121
--- /dev/null
+++ b/tests/GadgetHost/src/com/android/gadgethost/GadgetPickActivity.java
@@ -0,0 +1,70 @@
+/*
+ * 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.gadgethost;
+
+import android.app.ListActivity;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.gadget.GadgetInfo;
+import android.gadget.GadgetManager;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.util.Log;
+
+public class GadgetPickActivity extends ListActivity
+{
+ private static final String TAG = "GadgetPickActivity";
+
+ GadgetManager mGadgetManager;
+
+ public GadgetPickActivity() {
+ mGadgetManager = GadgetManager.getInstance(this);
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ Bundle extras = getIntent().getExtras();
+
+ String[] labels = new String[10];
+ for (int i=0; i<labels.length; i++) {
+ labels[i] = "Gadget " + (i+1);
+ }
+
+ setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, labels));
+ }
+
+ @Override
+ public void onListItemClick(ListView l, View v, int position, long id)
+ {
+ Log.d(TAG, "Clicked item " + position);
+
+ int gadgetId = mGadgetManager.allocateGadgetId(getCallingPackage());
+ mGadgetManager.bindGadgetId(gadgetId, new ComponentName(
+ "com.android.gadgethost", "com.android.gadgethost.TestGadgetProvider"));
+
+ Intent result = new Intent();
+ result.putExtra(GadgetManager.EXTRA_GADGET_ID, gadgetId);
+
+ setResult(RESULT_OK, result);
+ finish();
+ }
+}
+
diff --git a/tests/GadgetHost/src/com/android/gadgethost/TestGadgetProvider.java b/tests/GadgetHost/src/com/android/gadgethost/TestGadgetProvider.java
new file mode 100644
index 0000000..8f9641b
--- /dev/null
+++ b/tests/GadgetHost/src/com/android/gadgethost/TestGadgetProvider.java
@@ -0,0 +1,32 @@
+/*
+ * 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.gadgethost;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+
+public class TestGadgetProvider extends BroadcastReceiver {
+
+ static final String TAG = "TestGadgetProvider";
+
+ public void onReceive(Context context, Intent intent) {
+ Log.d(TAG, "intent=" + intent);
+ }
+}
+
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 877763d..c438366 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -2165,15 +2165,14 @@ ResourceTable::validateLocalizations(void)
// consider that string to have fulfilled the localization requirement.
String8 region(config.string(), 2);
if (configSet.find(region) == configSet.end()) {
- // TODO: force an error if there is no default to fall back to
if (configSet.count(defaultLocale) == 0) {
- fprintf(stdout, "aapt: warning: "
+ fprintf(stdout, "aapt: error: "
"*** string '%s' has no default or required localization "
"for '%s' in %s\n",
String8(nameIter->first).string(),
config.string(),
mBundle->getResourceSourceDirs()[0]);
- //err = UNKNOWN_ERROR;
+ err = UNKNOWN_ERROR;
}
}
}