From b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54 Mon Sep 17 00:00:00 2001 From: The Android Open Source Project Date: Mon, 9 Mar 2009 11:52:12 -0700 Subject: [PATCH] auto import from //branches/cupcake/...@137197 --- api/current.xml | 353 ++++- core/java/android/content/Intent.java | 8 + .../android/content/pm/PackageParser.java | 5 +- .../android/content/res/AssetManager.java | 4 +- core/java/android/emoji/EmojiFactory.java | 273 ++++ .../InputMethodService.java | 8 +- core/java/android/provider/Checkin.java | 2 - .../server/BluetoothDeviceService.java | 33 +- .../android/server/BluetoothEventLoop.java | 9 +- .../text/method/ArrowKeyMovementMethod.java | 2 +- .../text/method/MetaKeyKeyListener.java | 10 +- core/java/android/view/GestureDetector.java | 3 +- .../android/view/HapticFeedbackConstants.java | 3 - core/java/android/view/View.java | 78 +- .../view/inputmethod/BaseInputConnection.java | 9 +- .../android/view/inputmethod/EditorInfo.java | 34 +- .../view/inputmethod/ExtractedText.java | 7 +- .../view/inputmethod/InputConnection.java | 3 +- .../inputmethod/InputConnectionWrapper.java | 105 ++ .../view/inputmethod/InputMethodManager.java | 37 +- core/java/android/webkit/TextDialog.java | 28 +- core/java/android/webkit/WebView.java | 301 +--- core/java/android/widget/AbsListView.java | 47 +- core/java/android/widget/FastScroller.java | 18 +- core/java/android/widget/Filter.java | 11 +- core/java/android/widget/MediaController.java | 1 + core/java/android/widget/TextView.java | 215 ++- core/java/android/widget/VideoView.java | 19 +- .../android/widget/ZoomButtonsController.java | 181 ++- core/java/android/widget/ZoomControls.java | 2 +- core/java/android/widget/ZoomRing.java | 1274 --------------- .../android/widget/ZoomRingController.java | 1383 ----------------- .../internal/view/IInputMethodManager.aidl | 2 +- core/jni/Android.mk | 8 +- core/jni/AndroidRuntime.cpp | 2 + ...ndroid_bluetooth_BluetoothAudioGateway.cpp | 2 - core/jni/android_emoji_EmojiFactory.cpp | 292 ++++ core/jni/android_net_wifi_Wifi.cpp | 12 + core/res/Android.mk | 2 +- core/res/res/anim/zoom_ring_enter.xml | 29 - core/res/res/anim/zoom_ring_exit.xml | 28 - .../drawable-land/statusbar_background.png | Bin 1059 -> 2804 bytes core/res/res/drawable/btn_circle.xml | 32 + core/res/res/drawable/btn_circle_disable.png | Bin 0 -> 938 bytes .../drawable/btn_circle_disable_focused.png | Bin 0 -> 1436 bytes .../res/res/drawable/btn_circle_longpress.png | Bin 0 -> 1590 bytes core/res/res/drawable/btn_circle_normal.png | Bin 0 -> 1249 bytes core/res/res/drawable/btn_circle_pressed.png | Bin 0 -> 1613 bytes core/res/res/drawable/btn_circle_selected.png | Bin 0 -> 1645 bytes core/res/res/drawable/extract_edit_text.xml | 1 - ...ow_rotatable.xml => ic_btn_round_more.xml} | 12 +- .../drawable/ic_btn_round_more_disabled.png | Bin 0 -> 421 bytes .../res/drawable/ic_btn_round_more_normal.png | Bin 0 -> 968 bytes .../drawable/keyboard_textfield_pressed.9.png | Bin 1039 -> 0 bytes core/res/res/drawable/stat_sys_phone_call.png | Bin 772 -> 773 bytes .../stat_sys_phone_call_bluetooth.png | Bin 0 -> 815 bytes .../res/res/drawable/statusbar_background.png | Bin 933 -> 3079 bytes core/res/res/drawable/zoom_ring_arrows.png | Bin 4187 -> 0 bytes .../res/drawable/zoom_ring_overview_tab.9.png | Bin 1792 -> 0 bytes core/res/res/drawable/zoom_ring_thumb.png | Bin 2684 -> 0 bytes .../res/drawable/zoom_ring_thumb_minus.png | Bin 201 -> 0 bytes .../drawable/zoom_ring_thumb_minus_arrow.png | Bin 1941 -> 0 bytes .../res/res/drawable/zoom_ring_thumb_plus.png | Bin 317 -> 0 bytes .../drawable/zoom_ring_thumb_plus_arrow.png | Bin 2272 -> 0 bytes .../zoom_ring_thumb_plus_arrow_rotatable.xml | 22 - core/res/res/drawable/zoom_ring_track.png | Bin 17749 -> 0 bytes .../res/drawable/zoom_ring_track_absolute.png | Bin 18612 -> 0 bytes core/res/res/drawable/zoom_ring_trail.xml | 37 - core/res/res/layout/preferences.xml | 5 +- core/res/res/values/arrays.xml | 7 - core/res/res/values/attrs.xml | 47 +- core/res/res/values/styles.xml | 20 - core/res/res/values/themes.xml | 1 - data/etc/Android.mk | 2 +- data/sounds/Android.mk | 240 --- data/sounds/OriginalAudio.mk | 68 + data/sounds/effects/KeypressDelete.ogg | Bin 6630 -> 6193 bytes data/sounds/effects/KeypressDelete.wav | Bin 33424 -> 29892 bytes data/sounds/effects/KeypressReturn.ogg | Bin 7400 -> 7972 bytes data/sounds/effects/KeypressReturn.wav | Bin 46756 -> 64320 bytes data/sounds/effects/KeypressSpacebar.ogg | Bin 7122 -> 7392 bytes data/sounds/effects/KeypressSpacebar.wav | Bin 35536 -> 49400 bytes data/sounds/effects/KeypressStandard.ogg | Bin 5519 -> 5194 bytes data/sounds/effects/KeypressStandard.wav | Bin 21172 -> 17992 bytes .../html/guide/topics/graphics/2d-graphics.jd | 2 +- libs/audioflinger/A2dpAudioInterface.cpp | 51 +- libs/audioflinger/A2dpAudioInterface.h | 5 +- libs/audioflinger/AudioFlinger.cpp | 311 ++-- libs/audioflinger/AudioFlinger.h | 40 +- location/data/Android.mk | 6 +- media/libmedia/ToneGenerator.cpp | 12 +- .../mediaframeworktest/MediaNames.java | 14 + .../functional/CodecTest.java | 95 ++ .../functional/MediaPlayerApiTest.java | 19 +- packages/SettingsProvider/Android.mk | 2 +- packages/SettingsProvider/etc/Android.mk | 4 +- services/{ => java}/Android.mk | 0 .../server/InputMethodManagerService.java | 77 +- .../java/com/android/server/WifiService.java | 12 +- {core/jni/server => services/jni}/Android.mk | 0 ...com_android_server_AlarmManagerService.cpp | 0 .../com_android_server_BatteryService.cpp | 0 .../com_android_server_HardwareService.cpp | 0 .../jni}/com_android_server_KeyInputQueue.cpp | 0 .../jni}/com_android_server_SensorService.cpp | 0 .../jni}/com_android_server_SystemServer.cpp | 0 {core/jni/server => services/jni}/onload.cpp | 0 .../layout/table/VerticalGravityTest.java | 2 + tests/StatusBar/Android.mk | 2 +- wifi/java/android/net/wifi/WifiNative.java | 10 + .../android/net/wifi/WifiStateTracker.java | 33 + 111 files changed, 2191 insertions(+), 3843 deletions(-) create mode 100644 core/java/android/emoji/EmojiFactory.java create mode 100644 core/java/android/view/inputmethod/InputConnectionWrapper.java delete mode 100644 core/java/android/widget/ZoomRing.java delete mode 100644 core/java/android/widget/ZoomRingController.java create mode 100644 core/jni/android_emoji_EmojiFactory.cpp delete mode 100644 core/res/res/anim/zoom_ring_enter.xml delete mode 100644 core/res/res/anim/zoom_ring_exit.xml create mode 100644 core/res/res/drawable/btn_circle.xml create mode 100644 core/res/res/drawable/btn_circle_disable.png create mode 100644 core/res/res/drawable/btn_circle_disable_focused.png create mode 100644 core/res/res/drawable/btn_circle_longpress.png create mode 100644 core/res/res/drawable/btn_circle_normal.png create mode 100644 core/res/res/drawable/btn_circle_pressed.png create mode 100644 core/res/res/drawable/btn_circle_selected.png rename core/res/res/drawable/{zoom_ring_thumb_minus_arrow_rotatable.xml => ic_btn_round_more.xml} (71%) create mode 100644 core/res/res/drawable/ic_btn_round_more_disabled.png create mode 100644 core/res/res/drawable/ic_btn_round_more_normal.png delete mode 100644 core/res/res/drawable/keyboard_textfield_pressed.9.png create mode 100644 core/res/res/drawable/stat_sys_phone_call_bluetooth.png delete mode 100644 core/res/res/drawable/zoom_ring_arrows.png delete mode 100644 core/res/res/drawable/zoom_ring_overview_tab.9.png delete mode 100644 core/res/res/drawable/zoom_ring_thumb.png delete mode 100644 core/res/res/drawable/zoom_ring_thumb_minus.png delete mode 100644 core/res/res/drawable/zoom_ring_thumb_minus_arrow.png delete mode 100644 core/res/res/drawable/zoom_ring_thumb_plus.png delete mode 100644 core/res/res/drawable/zoom_ring_thumb_plus_arrow.png delete mode 100644 core/res/res/drawable/zoom_ring_thumb_plus_arrow_rotatable.xml delete mode 100644 core/res/res/drawable/zoom_ring_track.png delete mode 100644 core/res/res/drawable/zoom_ring_track_absolute.png delete mode 100644 core/res/res/drawable/zoom_ring_trail.xml delete mode 100644 data/sounds/Android.mk create mode 100644 data/sounds/OriginalAudio.mk rename services/{ => java}/Android.mk (100%) rename {core/jni/server => services/jni}/Android.mk (100%) rename {core/jni/server => services/jni}/com_android_server_AlarmManagerService.cpp (100%) rename {core/jni/server => services/jni}/com_android_server_BatteryService.cpp (100%) rename {core/jni/server => services/jni}/com_android_server_HardwareService.cpp (100%) rename {core/jni/server => services/jni}/com_android_server_KeyInputQueue.cpp (100%) rename {core/jni/server => services/jni}/com_android_server_SensorService.cpp (100%) rename {core/jni/server => services/jni}/com_android_server_SystemServer.cpp (100%) rename {core/jni/server => services/jni}/onload.cpp (100%) diff --git a/api/current.xml b/api/current.xml index 55c775677370c..96998ed0e3508 100644 --- a/api/current.xml +++ b/api/current.xml @@ -27761,6 +27761,17 @@ visibility="public" > + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -not receive this through components declared diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 4ae8b08847086..2dcb4830bf484 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -260,8 +260,9 @@ public class PackageParser { boolean assetError = true; try { assmgr = new AssetManager(); - if(assmgr.addAssetPath(mArchiveSourcePath) != 0) { - parser = assmgr.openXmlResourceParser("AndroidManifest.xml"); + int cookie = assmgr.addAssetPath(mArchiveSourcePath); + if(cookie != 0) { + parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml"); assetError = false; } else { Log.w(TAG, "Failed adding asset path:"+mArchiveSourcePath); diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index fadcb352261ff..1c9173694d2bc 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -567,8 +567,8 @@ public final class AssetManager { /** * Add an additional set of assets to the asset manager. This can be - * either a directory or ZIP file. Not for use by applications. A - * zero return value indicates failure. + * either a directory or ZIP file. Not for use by applications. Returns + * the cookie of the added asset, or 0 on failure. * {@hide} */ public native final int addAssetPath(String path); diff --git a/core/java/android/emoji/EmojiFactory.java b/core/java/android/emoji/EmojiFactory.java new file mode 100644 index 0000000000000..389bd07d6b735 --- /dev/null +++ b/core/java/android/emoji/EmojiFactory.java @@ -0,0 +1,273 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.emoji; + +import android.graphics.Bitmap; + +import java.lang.ref.WeakReference; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * A class for the factories which produce Emoji (pictgram) images. + * This is intended to be used by IME, Email app, etc. + * There's no plan to make this public for now. + * @hide + */ +public final class EmojiFactory { + // private static final String LOG_TAG = "EmojiFactory"; + + private int sCacheSize = 100; + + // HashMap for caching Bitmap object. In order not to make an cache object + // blow up, we use LinkedHashMap with size limit. + private class CustomLinkedHashMap extends LinkedHashMap { + public CustomLinkedHashMap() { + // These magic numbers are gotten from the source code of + // LinkedHashMap.java and HashMap.java. + super(16, 0.75f, true); + } + + /* + * If size() becomes more than sCacheSize, least recently used cache + * is erased. + * @see java.util.LinkedHashMap#removeEldestEntry(java.util.Map.Entry) + */ + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > sCacheSize; + } + } + + // A pointer to native EmojiFactory object. + private int mNativeEmojiFactory; + private String mName; + // Cache. + private Map> mCache; + + /** + * @noinspection UnusedDeclaration + */ + /* + * Private constructor that must received an already allocated native + * EmojiFactory int (pointer). + * + * This can be called from JNI code. + */ + private EmojiFactory(int nativeEmojiFactory, String name) { + mNativeEmojiFactory = nativeEmojiFactory; + mName = name; + mCache = new CustomLinkedHashMap>(); + } + + @Override + protected void finalize() throws Throwable { + try { + nativeDestructor(mNativeEmojiFactory); + } finally { + super.finalize(); + } + } + + public String name() { + return mName; + } + + /** + * Returns Bitmap object corresponding to the AndroidPua. + * + * Note that each Bitmap is cached by this class, which means that, if you modify a + * Bitmap object (using setPos() method), all same emoji Bitmap will be modified. + * If it is unacceptable, please copy the object before modifying it. + * + * @param pua A unicode codepoint. + * @return Bitmap object when this factory knows the Bitmap relevant to the codepoint. + * Otherwise null is returned. + */ + public synchronized Bitmap getBitmapFromAndroidPua(int pua) { + WeakReference cache = mCache.get(pua); + if (cache == null) { + Bitmap ret = nativeGetBitmapFromAndroidPua(mNativeEmojiFactory, pua); + // There is no need to cache returned null, since in most cases it means there + // is no map from the AndroidPua to a specific image. In other words, it usually does + // not include the cost of creating Bitmap object. + if (ret != null) { + mCache.put(pua, new WeakReference(ret)); + } + return ret; + } else { + Bitmap tmp = cache.get(); + if (tmp == null) { + Bitmap ret = nativeGetBitmapFromAndroidPua(mNativeEmojiFactory, pua); + mCache.put(pua, new WeakReference(ret)); + return ret; + } else { + return tmp; + } + } + } + + /** + * Returns Bitmap object corresponding to the vendor specified sjis. + * + * See comments in getBitmapFromAndroidPua(). + * + * @param sjis sjis code specific to each career(vendor) + * @return Bitmap object when this factory knows the Bitmap relevant to the code. Otherwise + * null is returned. + */ + public synchronized Bitmap getBitmapFromVendorSpecificSjis(char sjis) { + return getBitmapFromAndroidPua(getAndroidPuaFromVendorSpecificSjis(sjis)); + } + + /** + * Returns Bitmap object corresponding to the vendor specific Unicode. + * + * See comments in getBitmapFromAndroidPua(). + * + * @param vsp vendor specific PUA. + * @return Bitmap object when this factory knows the Bitmap relevant to the code. Otherwise + * null is returned. + */ + public synchronized Bitmap getBitmapFromVendorSpecificPua(int vsp) { + return getBitmapFromAndroidPua(getAndroidPuaFromVendorSpecificPua(vsp)); + } + + /** + * Returns Unicode PUA for Android corresponding to the vendor specific sjis. + * + * @param sjis vendor specific sjis + * @return Unicode PUA for Android, or -1 if there's no map for the sjis. + */ + public int getAndroidPuaFromVendorSpecificSjis(char sjis) { + return nativeGetAndroidPuaFromVendorSpecificSjis(mNativeEmojiFactory, sjis); + } + + /** + * Returns vendor specific sjis corresponding to the Unicode AndroidPua. + * + * @param pua Unicode PUA for Android, + * @return vendor specific sjis, or -1 if there's no map for the AndroidPua. + */ + public int getVendorSpecificSjisFromAndroidPua(int pua) { + return nativeGetVendorSpecificSjisFromAndroidPua(mNativeEmojiFactory, pua); + } + + /** + * Returns Unicode PUA for Android corresponding to the vendor specific Unicode. + * + * @param vsp vendor specific PUA. + * @return Unicode PUA for Android, or -1 if there's no map for the + * Unicode. + */ + public int getAndroidPuaFromVendorSpecificPua(int vsp) { + return nativeGetAndroidPuaFromVendorSpecificPua(mNativeEmojiFactory, vsp); + } + + public String getAndroidPuaFromVendorSpecificPua(String vspString) { + if (vspString == null) { + return null; + } + int minVsp = nativeGetMinimumVendorSpecificPua(mNativeEmojiFactory); + int maxVsp = nativeGetMaximumVendorSpecificPua(mNativeEmojiFactory); + int len = vspString.length(); + int[] codePoints = new int[vspString.codePointCount(0, len)]; + + int new_len = 0; + for (int i = 0; i < len; i = vspString.offsetByCodePoints(i, 1), new_len++) { + int codePoint = vspString.codePointAt(i); + if (minVsp <= codePoint && codePoint <= maxVsp) { + int newCodePoint = getAndroidPuaFromVendorSpecificPua(codePoint); + if (newCodePoint > 0) { + codePoints[new_len] = newCodePoint; + continue; + } + } + codePoints[new_len] = codePoint; + } + return new String(codePoints, 0, new_len); + } + + /** + * Returns vendor specific Unicode corresponding to the Unicode AndroidPua. + * + * @param pua Unicode PUA for Android, + * @return vendor specific sjis, or -1 if there's no map for the AndroidPua. + */ + public int getVendorSpecificPuaFromAndroidPua(int pua) { + return nativeGetVendorSpecificPuaFromAndroidPua(mNativeEmojiFactory, pua); + } + + public String getVendorSpecificPuaFromAndroidPua(String puaString) { + if (puaString == null) { + return null; + } + int minVsp = nativeGetMinimumAndroidPua(mNativeEmojiFactory); + int maxVsp = nativeGetMaximumAndroidPua(mNativeEmojiFactory); + int len = puaString.length(); + int[] codePoints = new int[puaString.codePointCount(0, len)]; + + int new_len = 0; + for (int i = 0; i < len; i = puaString.offsetByCodePoints(i, 1), new_len++) { + int codePoint = puaString.codePointAt(i); + if (minVsp <= codePoint && codePoint <= maxVsp) { + int newCodePoint = getVendorSpecificPuaFromAndroidPua(codePoint); + if (newCodePoint > 0) { + codePoints[new_len] = newCodePoint; + continue; + } + } + codePoints[new_len] = codePoint; + } + return new String(codePoints, 0, new_len); + } + + /** + * Constructs an instance of EmojiFactory corresponding to the name. + * + * @param class_name Name of the factory. This must include complete package name. + * @return A concrete EmojiFactory instance corresponding to factory_name. + * If factory_name is invalid, null is returned. + */ + public static native EmojiFactory newInstance(String class_name); + + /** + * Constructs an instance of available EmojiFactory. + * + * @return A concrete EmojiFactory instance. If there are several available + * EmojiFactory class, preferred one is chosen by the system. If there isn't, null + * is returned. + */ + public static native EmojiFactory newAvailableInstance(); + + // native methods + + private native void nativeDestructor(int factory); + private native Bitmap nativeGetBitmapFromAndroidPua(int nativeEmojiFactory, int AndroidPua); + private native int nativeGetAndroidPuaFromVendorSpecificSjis(int nativeEmojiFactory, + char sjis); + private native int nativeGetVendorSpecificSjisFromAndroidPua(int nativeEmojiFactory, + int pua); + private native int nativeGetAndroidPuaFromVendorSpecificPua(int nativeEmojiFactory, + int vsp); + private native int nativeGetVendorSpecificPuaFromAndroidPua(int nativeEmojiFactory, + int pua); + private native int nativeGetMaximumVendorSpecificPua(int nativeEmojiFactory); + private native int nativeGetMinimumVendorSpecificPua(int nativeEmojiFactory); + private native int nativeGetMaximumAndroidPua(int nativeEmojiFactory); + private native int nativeGetMinimumAndroidPua(int nativeEmojiFactory); +} diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java index f1e613eea5dc6..34d569592fd3d 100644 --- a/core/java/android/inputmethodservice/InputMethodService.java +++ b/core/java/android/inputmethodservice/InputMethodService.java @@ -1377,9 +1377,11 @@ public class InputMethodService extends AbstractInputMethodService { if (mExtractedToken != token) { return; } - if (mExtractEditText != null && text != null) { - mExtractedText = text; - mExtractEditText.setExtractedText(text); + if (text != null) { + if (mExtractEditText != null) { + mExtractedText = text; + mExtractEditText.setExtractedText(text); + } } } diff --git a/core/java/android/provider/Checkin.java b/core/java/android/provider/Checkin.java index 1454089e70baa..d11a9c52f86dd 100644 --- a/core/java/android/provider/Checkin.java +++ b/core/java/android/provider/Checkin.java @@ -132,8 +132,6 @@ public final class Checkin { BROWSER_SNAP_CENTER, BROWSER_TEXT_SIZE_CHANGE, BROWSER_ZOOM_OVERVIEW, - BROWSER_ZOOM_RING, - BROWSER_ZOOM_RING_DRAG, CRASHES_REPORTED, CRASHES_TRUNCATED, ELAPSED_REALTIME_SEC, diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java index 87153cf340fa8..6f5513a369ae9 100644 --- a/core/java/android/server/BluetoothDeviceService.java +++ b/core/java/android/server/BluetoothDeviceService.java @@ -237,7 +237,28 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { public void run() { boolean res = (enableNative() == 0); if (res) { - mEventLoop.start(); + int retryCount = 2; + boolean running = false; + while ((retryCount-- > 0) && !running) { + mEventLoop.start(); + // it may take a momement for the other thread to do its + // thing. Check periodically for a while. + int pollCount = 5; + while ((pollCount-- > 0) && !running) { + if (mEventLoop.isEventLoopRunning()) { + running = true; + break; + } + try { + Thread.sleep(100); + } catch (InterruptedException e) {} + } + } + if (!running) { + log("bt EnableThread giving up"); + res = false; + disableNative(); + } } if (mEnableCallback != null) { @@ -254,14 +275,20 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { persistBluetoothOnSetting(true); } mIsDiscovering = false; - Intent intent = new Intent(BluetoothIntent.ENABLED_ACTION); mBondState.loadBondState(); - mContext.sendBroadcast(intent, BLUETOOTH_PERM); mHandler.sendMessageDelayed(mHandler.obtainMessage(REGISTER_SDP_RECORDS), 3000); // Update mode mEventLoop.onModeChanged(getModeNative()); } + Intent intent = null; + if (res) { + intent = new Intent(BluetoothIntent.ENABLED_ACTION); + } else { + intent = new Intent(BluetoothIntent.DISABLED_ACTION); + } + mContext.sendBroadcast(intent, BLUETOOTH_PERM); + mEnableThread = null; } } diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java index 8b09583492d4b..e4ebcca4d0805 100644 --- a/core/java/android/server/BluetoothEventLoop.java +++ b/core/java/android/server/BluetoothEventLoop.java @@ -44,6 +44,7 @@ class BluetoothEventLoop { private int mNativeData; private Thread mThread; + private boolean mStarted; private boolean mInterrupted; private HashMap mPasskeyAgentRequestData; private HashMap mGetRemoteServiceChannelCallbacks; @@ -122,14 +123,18 @@ class BluetoothEventLoop { public void run() { try { if (setUpEventLoopNative()) { + mStarted = true; while (!mInterrupted) { waitForAndDispatchEvent(0); sleep(500); } - tearDownEventLoopNative(); } + // tear down even in the error case to clean + // up anything we started to setup + tearDownEventLoopNative(); } catch (InterruptedException e) { } if (DBG) log("Event Loop thread finished"); + mThread = null; } }; if (DBG) log("Starting Event Loop thread"); @@ -152,7 +157,7 @@ class BluetoothEventLoop { } public synchronized boolean isEventLoopRunning() { - return mThread != null; + return mThread != null && mStarted; } /*package*/ void onModeChanged(String bluezMode) { diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java index 8aa49afe45c5b..17c7a6cd8c880 100644 --- a/core/java/android/text/method/ArrowKeyMovementMethod.java +++ b/core/java/android/text/method/ArrowKeyMovementMethod.java @@ -204,7 +204,7 @@ implements MovementMethod MotionEvent event) { boolean handled = Touch.onTouchEvent(widget, buffer, event); - if (widget.isFocused() && !widget.didTouchFocusSelectAll()) { + if (widget.isFocused() && !widget.didTouchFocusSelect()) { if (event.getAction() == MotionEvent.ACTION_UP) { int x = (int) event.getX(); int y = (int) event.getY(); diff --git a/core/java/android/text/method/MetaKeyKeyListener.java b/core/java/android/text/method/MetaKeyKeyListener.java index 39ad97689a5dc..61ec67fce237c 100644 --- a/core/java/android/text/method/MetaKeyKeyListener.java +++ b/core/java/android/text/method/MetaKeyKeyListener.java @@ -159,13 +159,21 @@ public abstract class MetaKeyKeyListener { /** * Returns true if this object is one that this class would use to - * keep track of meta state in the specified text. + * keep track of any meta state in the specified text. */ public static boolean isMetaTracker(CharSequence text, Object what) { return what == CAP || what == ALT || what == SYM || what == SELECTING; } + /** + * Returns true if this object is one that this class would use to + * keep track of the selecting meta state in the specified text. + */ + public static boolean isSelectingMetaTracker(CharSequence text, Object what) { + return what == SELECTING; + } + private static void adjust(Spannable content, Object what) { int current = content.getSpanFlags(what); diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java index 88ff3c5a69382..f7ac522aba6e0 100644 --- a/core/java/android/view/GestureDetector.java +++ b/core/java/android/view/GestureDetector.java @@ -498,7 +498,6 @@ public class GestureDetector { if (mIsDoubleTapping) { // Finally, give the up event of the double-tap handled |= mDoubleTapListener.onDoubleTapEvent(ev); - mIsDoubleTapping = false; } else if (mInLongPress) { mHandler.removeMessages(TAP); mInLongPress = false; @@ -520,6 +519,7 @@ public class GestureDetector { mPreviousUpEvent = MotionEvent.obtain(ev); mVelocityTracker.recycle(); mVelocityTracker = null; + mIsDoubleTapping = false; mHandler.removeMessages(SHOW_PRESS); mHandler.removeMessages(LONG_PRESS); break; @@ -529,6 +529,7 @@ public class GestureDetector { mHandler.removeMessages(TAP); mVelocityTracker.recycle(); mVelocityTracker = null; + mIsDoubleTapping = false; mStillDown = false; if (mInLongPress) { mInLongPress = false; diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java index cc3563c40f8da..841066c7ba525 100644 --- a/core/java/android/view/HapticFeedbackConstants.java +++ b/core/java/android/view/HapticFeedbackConstants.java @@ -26,9 +26,6 @@ public class HapticFeedbackConstants { public static final int LONG_PRESS = 0; - /** @hide pending API council */ - public static final int ZOOM_RING_TICK = 1; - /** * Flag for {@link View#performHapticFeedback(int, int) * View.performHapticFeedback(int, int)}: Ignore the setting in the diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 3e762f570fc95..d78320a01b87e 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -3663,8 +3663,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback { * would make sense to automatically display a soft input window for * it. Subclasses should override this if they implement * {@link #onCreateInputConnection(EditorInfo)} to return true if - * a call on that method would return a non-null InputConnection. The - * default implementation always returns false. + * a call on that method would return a non-null InputConnection, and + * they are really a first-class editor that the user would normally + * start typing on when the go into a window containing your view. + * + *

The default implementation always returns false. This does + * not mean that its {@link #onCreateInputConnection(EditorInfo)} + * will not be called or the user can not otherwise perform edits on your + * view; it is just a hint to the system that this is not the primary + * purpose of this view. * * @return Returns true if this view is a text editor, else false. */ @@ -3688,6 +3695,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback { return null; } + /** + * Called by the {@link android.view.inputmethod.InputMethodManager} + * when a view who is not the current + * input connection target is trying to make a call on the manager. The + * default implementation returns false; you can override this to return + * true for certain views if you are performing InputConnection proxying + * to them. + * @param view The View that is making the InputMethodManager call. + * @return Return true to allow the call, false to reject. + */ + public boolean checkInputConnectionProxy(View view) { + return false; + } + /** * Show the context menu for this view. It is not safe to hold on to the * menu after returning from this method. @@ -5016,7 +5037,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback { (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL ? getVerticalScrollbarWidth() : 0; - scrollBar.setBounds(scrollX + (mPaddingLeft & inside) + getScrollBarPaddingLeft(), top, + scrollBar.setBounds(scrollX + (mPaddingLeft & inside), top, scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap, top + size); scrollBar.setParameters( computeHorizontalScrollRange(), @@ -6503,32 +6524,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback { return mBGDrawable; } - private int getScrollBarPaddingLeft() { - // TODO: Deal with RTL languages - return 0; - } - - /* - * Returns the pixels occupied by the vertical scrollbar, if not overlaid - */ - private int getScrollBarPaddingRight() { - // TODO: Deal with RTL languages - if ((mViewFlags & SCROLLBARS_VERTICAL) == 0) { - return 0; - } - return (mViewFlags & SCROLLBARS_INSET_MASK) == 0 ? 0 : getVerticalScrollbarWidth(); - } - - /* - * Returns the pixels occupied by the horizontal scrollbar, if not overlaid - */ - private int getScrollBarPaddingBottom() { - if ((mViewFlags & SCROLLBARS_HORIZONTAL) == 0) { - return 0; - } - return (mViewFlags & SCROLLBARS_INSET_MASK) == 0 ? 0 : getHorizontalScrollbarHeight(); - } - /** * Sets the padding. The view may add on the space required to display * the scrollbars, depending on the style and visibility of the scrollbars. @@ -6552,7 +6547,22 @@ public class View implements Drawable.Callback, KeyEvent.Callback { mUserPaddingRight = right; mUserPaddingBottom = bottom; - if (mPaddingLeft != left + getScrollBarPaddingLeft()) { + final int viewFlags = mViewFlags; + + // Common case is there are no scroll bars. + if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) { + // TODO: Deal with RTL languages to adjust left padding instead of right. + if ((viewFlags & SCROLLBARS_VERTICAL) != 0) { + right += (viewFlags & SCROLLBARS_INSET_MASK) == 0 + ? 0 : getVerticalScrollbarWidth(); + } + if ((viewFlags & SCROLLBARS_HORIZONTAL) == 0) { + bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0 + ? 0 : getHorizontalScrollbarHeight(); + } + } + + if (mPaddingLeft != left) { changed = true; mPaddingLeft = left; } @@ -6560,13 +6570,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback { changed = true; mPaddingTop = top; } - if (mPaddingRight != right + getScrollBarPaddingRight()) { + if (mPaddingRight != right) { changed = true; - mPaddingRight = right + getScrollBarPaddingRight(); + mPaddingRight = right; } - if (mPaddingBottom != bottom + getScrollBarPaddingBottom()) { + if (mPaddingBottom != bottom) { changed = true; - mPaddingBottom = bottom + getScrollBarPaddingBottom(); + mPaddingBottom = bottom; } if (changed) { diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java index 52b4107348082..deca910c6fbfb 100644 --- a/core/java/android/view/inputmethod/BaseInputConnection.java +++ b/core/java/android/view/inputmethod/BaseInputConnection.java @@ -386,7 +386,14 @@ public class BaseInputConnection implements InputConnection { // anyway. return true; } - Selection.setSelection(content, start, end); + if (start == end && MetaKeyKeyListener.getMetaState(content, + MetaKeyKeyListener.META_SELECTING) != 0) { + // If we are in selection mode, then we want to extend the + // selection instead of replacing it. + Selection.extendSelection(content, start); + } else { + Selection.setSelection(content, start, end); + } return true; } diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java index 1c0d42a2c8ef6..b00e565956175 100644 --- a/core/java/android/view/inputmethod/EditorInfo.java +++ b/core/java/android/view/inputmethod/EditorInfo.java @@ -33,43 +33,49 @@ public class EditorInfo implements InputType, Parcelable { public static final int IME_MASK_ACTION = 0x000000ff; /** - * Bits of {@link #IME_MASK_ACTION}: there is no special action - * associated with this editor. + * Bits of {@link #IME_MASK_ACTION}: no specific action has been + * associated with this editor, let the editor come up with its own if + * it can. */ - public static final int IME_ACTION_NONE = 0x00000000; + public static final int IME_ACTION_UNSPECIFIED = 0x00000000; + + /** + * Bits of {@link #IME_MASK_ACTION}: there is no available action. + */ + public static final int IME_ACTION_NONE = 0x00000001; /** * Bits of {@link #IME_MASK_ACTION}: the action key performs a "go" * operation to take the user to the target of the text they typed. * Typically used, for example, when entering a URL. */ - public static final int IME_ACTION_GO = 0x00000001; + public static final int IME_ACTION_GO = 0x00000002; /** * Bits of {@link #IME_MASK_ACTION}: the action key performs a "search" * operation, taking the user to the results of searching for the text * the have typed (in whatever context is appropriate). */ - public static final int IME_ACTION_SEARCH = 0x00000002; + public static final int IME_ACTION_SEARCH = 0x00000003; /** * Bits of {@link #IME_MASK_ACTION}: the action key performs a "send" * operation, delivering the text to its target. This is typically used * when composing a message. */ - public static final int IME_ACTION_SEND = 0x00000003; + public static final int IME_ACTION_SEND = 0x00000004; /** * Bits of {@link #IME_MASK_ACTION}: the action key performs a "next" * operation, taking the user to the next field that will accept text. */ - public static final int IME_ACTION_NEXT = 0x00000004; + public static final int IME_ACTION_NEXT = 0x00000005; /** * Bits of {@link #IME_MASK_ACTION}: the action key performs a "done" * operation, typically meaning the IME will be closed. */ - public static final int IME_ACTION_DONE = 0x00000005; + public static final int IME_ACTION_DONE = 0x00000006; /** * Flag of {@link #imeOptions}: used in conjunction with @@ -82,21 +88,15 @@ public class EditorInfo implements InputType, Parcelable { public static final int IME_FLAG_NO_ENTER_ACTION = 0x40000000; /** - * Generic non-special type for {@link #imeOptions}. + * Generic unspecified type for {@link #imeOptions}. */ - public static final int IME_NORMAL = 0x00000000; - - /** - * Special code for when the ime option has been undefined. This is not - * used with the EditorInfo structure, but can be used elsewhere. - */ - public static final int IME_UNDEFINED = 0x80000000; + public static final int IME_NULL = 0x00000000; /** * Extended type information for the editor, to help the IME better * integrate with it. */ - public int imeOptions = IME_NORMAL; + public int imeOptions = IME_NULL; /** * A string supplying additional information options that are diff --git a/core/java/android/view/inputmethod/ExtractedText.java b/core/java/android/view/inputmethod/ExtractedText.java index e5d3caeef1ced..c2851d6ca6632 100644 --- a/core/java/android/view/inputmethod/ExtractedText.java +++ b/core/java/android/view/inputmethod/ExtractedText.java @@ -54,6 +54,11 @@ public class ExtractedText implements Parcelable { */ public static final int FLAG_SINGLE_LINE = 0x0001; + /** + * Bit for {@link #flags}: set if the editor is currently in selection mode. + */ + public static final int FLAG_SELECTING = 0x0002; + /** * Additional bit flags of information about the edited text. */ @@ -72,7 +77,7 @@ public class ExtractedText implements Parcelable { dest.writeInt(partialEndOffset); dest.writeInt(selectionStart); dest.writeInt(selectionEnd); - dest.writeInt(flags); + dest.writeInt(this.flags); } /** diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java index 32cce35608d41..8b6831e655395 100644 --- a/core/java/android/view/inputmethod/InputConnection.java +++ b/core/java/android/view/inputmethod/InputConnection.java @@ -17,7 +17,6 @@ package android.view.inputmethod; import android.os.Bundle; -import android.text.Spanned; import android.view.KeyCharacterMap; import android.view.KeyEvent; @@ -135,7 +134,7 @@ public interface InputConnection { * @return Returns true on success, false if the input connection is no longer * valid. */ - boolean deleteSurroundingText(int leftLength, int rightLength); + public boolean deleteSurroundingText(int leftLength, int rightLength); /** * Set composing text around the current cursor position with the given text, diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java new file mode 100644 index 0000000000000..e3d5e62151b10 --- /dev/null +++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2007-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.view.inputmethod; + +import android.os.Bundle; +import android.view.KeyEvent; + +/** + *

Wrapper class for proxying calls to another InputConnection. Subclass + * and have fun! + */ +public class InputConnectionWrapper implements InputConnection { + private final InputConnection mTarget; + + public InputConnectionWrapper(InputConnection target) { + mTarget = target; + } + + public CharSequence getTextBeforeCursor(int n, int flags) { + return mTarget.getTextBeforeCursor(n, flags); + } + + public CharSequence getTextAfterCursor(int n, int flags) { + return mTarget.getTextAfterCursor(n, flags); + } + + public int getCursorCapsMode(int reqModes) { + return mTarget.getCursorCapsMode(reqModes); + } + + public ExtractedText getExtractedText(ExtractedTextRequest request, + int flags) { + return mTarget.getExtractedText(request, flags); + } + + public boolean deleteSurroundingText(int leftLength, int rightLength) { + return mTarget.deleteSurroundingText(leftLength, rightLength); + } + + public boolean setComposingText(CharSequence text, int newCursorPosition) { + return mTarget.setComposingText(text, newCursorPosition); + } + + public boolean finishComposingText() { + return mTarget.finishComposingText(); + } + + public boolean commitText(CharSequence text, int newCursorPosition) { + return mTarget.commitText(text, newCursorPosition); + } + + public boolean commitCompletion(CompletionInfo text) { + return mTarget.commitCompletion(text); + } + + public boolean setSelection(int start, int end) { + return mTarget.setSelection(start, end); + } + + public boolean performEditorAction(int editorAction) { + return mTarget.performEditorAction(editorAction); + } + + public boolean performContextMenuAction(int id) { + return mTarget.performContextMenuAction(id); + } + + public boolean beginBatchEdit() { + return mTarget.beginBatchEdit(); + } + + public boolean endBatchEdit() { + return mTarget.endBatchEdit(); + } + + public boolean sendKeyEvent(KeyEvent event) { + return mTarget.sendKeyEvent(event); + } + + public boolean clearMetaKeyStates(int states) { + return mTarget.clearMetaKeyStates(states); + } + + public boolean reportFullscreenMode(boolean enabled) { + return mTarget.reportFullscreenMode(enabled); + } + + public boolean performPrivateCommand(String action, Bundle data) { + return mTarget.performPrivateCommand(action, data); + } +} diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index 916ffea6a7a82..7f2142eda646d 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -529,7 +529,10 @@ public final class InputMethodManager { public boolean isActive(View view) { checkFocus(); synchronized (mH) { - return mServedView == view && mCurrentTextBoxAttribute != null; + return (mServedView == view + || (mServedView != null + && mServedView.checkInputConnectionProxy(view))) + && mCurrentTextBoxAttribute != null; } } @@ -620,7 +623,8 @@ public final class InputMethodManager { public void displayCompletions(View view, CompletionInfo[] completions) { checkFocus(); synchronized (mH) { - if (mServedView != view) { + if (mServedView != view && (mServedView == null + || !mServedView.checkInputConnectionProxy(view))) { return; } @@ -637,7 +641,8 @@ public final class InputMethodManager { public void updateExtractedText(View view, int token, ExtractedText text) { checkFocus(); synchronized (mH) { - if (mServedView != view) { + if (mServedView != view && (mServedView == null + || !mServedView.checkInputConnectionProxy(view))) { return; } @@ -730,7 +735,8 @@ public final class InputMethodManager { ResultReceiver resultReceiver) { checkFocus(); synchronized (mH) { - if (mServedView != view) { + if (mServedView != view && (mServedView == null + || !mServedView.checkInputConnectionProxy(view))) { return false; } @@ -871,7 +877,8 @@ public final class InputMethodManager { public void restartInput(View view) { checkFocus(); synchronized (mH) { - if (mServedView != view) { + if (mServedView != view && (mServedView == null + || !mServedView.checkInputConnectionProxy(view))) { return; } @@ -1032,7 +1039,7 @@ public final class InputMethodManager { if (DEBUG) Log.v(TAG, "focusOut: " + view + " mServedView=" + mServedView + " winFocus=" + view.hasWindowFocus()); - if (mServedView == view) { + if (mServedView != view) { // The following code would auto-hide the IME if we end up // with no more views with focus. This can happen, however, // whenever we go into touch mode, so it ends up hiding @@ -1129,8 +1136,9 @@ public final class InputMethodManager { try { final boolean isTextEditor = focusedView != null && focusedView.onCheckIsTextEditor(); - mService.windowGainedFocus(mClient, focusedView != null, - isTextEditor, softInputMode, first, windowFlags); + mService.windowGainedFocus(mClient, rootView.getWindowToken(), + focusedView != null, isTextEditor, softInputMode, first, + windowFlags); } catch (RemoteException e) { } } @@ -1150,8 +1158,9 @@ public final class InputMethodManager { int candidatesStart, int candidatesEnd) { checkFocus(); synchronized (mH) { - if (mServedView != view || mCurrentTextBoxAttribute == null - || mCurMethod == null) { + if ((mServedView != view && (mServedView == null + || !mServedView.checkInputConnectionProxy(view))) + || mCurrentTextBoxAttribute == null || mCurMethod == null) { return; } @@ -1189,8 +1198,9 @@ public final class InputMethodManager { public void updateCursor(View view, int left, int top, int right, int bottom) { checkFocus(); synchronized (mH) { - if (mServedView != view || mCurrentTextBoxAttribute == null - || mCurMethod == null) { + if ((mServedView != view && (mServedView == null + || !mServedView.checkInputConnectionProxy(view))) + || mCurrentTextBoxAttribute == null || mCurMethod == null) { return; } @@ -1223,7 +1233,8 @@ public final class InputMethodManager { public void sendAppPrivateCommand(View view, String action, Bundle data) { checkFocus(); synchronized (mH) { - if ((view != null && mServedView != view) + if ((mServedView != view && (mServedView == null + || !mServedView.checkInputConnectionProxy(view))) || mCurrentTextBoxAttribute == null || mCurMethod == null) { return; } diff --git a/core/java/android/webkit/TextDialog.java b/core/java/android/webkit/TextDialog.java index 39806dc4b299d..efc131f526279 100644 --- a/core/java/android/webkit/TextDialog.java +++ b/core/java/android/webkit/TextDialog.java @@ -32,8 +32,6 @@ import android.text.Spannable; import android.text.TextPaint; import android.text.TextUtils; 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; @@ -475,15 +473,10 @@ import java.util.ArrayList; * @param inPassword True if the textfield is a password field. */ /* package */ void setInPassword(boolean inPassword) { - PasswordTransformationMethod method; if (inPassword) { - method = PasswordTransformationMethod.getInstance(); - setInputType(EditorInfo.TYPE_CLASS_TEXT|EditorInfo. + setInputType(EditorInfo.TYPE_CLASS_TEXT | EditorInfo. TYPE_TEXT_VARIATION_PASSWORD); - } else { - method = null; } - setTransformationMethod(method); } /* package */ void setMaxLength(int maxLength) { @@ -545,20 +538,13 @@ import java.util.ArrayList; * removing the password input type. */ public void setSingleLine(boolean single) { - if (mSingle != single) { - TextKeyListener.Capitalize cap; - int inputType = EditorInfo.TYPE_CLASS_TEXT; - if (single) { - cap = TextKeyListener.Capitalize.NONE; - } else { - cap = TextKeyListener.Capitalize.SENTENCES; - inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE; - } - setKeyListener(TextKeyListener.getInstance(!single, cap)); - mSingle = single; - setHorizontallyScrolling(single); - setInputType(inputType); + int inputType = EditorInfo.TYPE_CLASS_TEXT; + if (!single) { + inputType |= EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE; } + mSingle = single; + setHorizontallyScrolling(single); + setInputType(inputType); } /** diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 91795a3dc25f7..dc39b90bcc3c6 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -73,7 +73,6 @@ import android.widget.Scroller; import android.widget.Toast; import android.widget.ZoomButtonsController; import android.widget.ZoomControls; -import android.widget.ZoomRingController; import android.widget.FrameLayout; import android.widget.AdapterView.OnItemClickListener; @@ -239,8 +238,8 @@ public class WebView extends AbsoluteLayout */ VelocityTracker mVelocityTracker; - private static boolean mShowZoomRingTutorial = true; - private static final int ZOOM_RING_TUTORIAL_DURATION = 3000; + private static boolean mShowZoomTutorial = true; + private static final int ZOOM_TUTORIAL_DURATION = 3000; /** * Touch mode @@ -265,11 +264,6 @@ public class WebView extends AbsoluteLayout // Whether to forward the touch events to WebCore private boolean mForwardTouchEvents = false; - // Whether we are in the drag tap mode, which exists starting at the second - // tap's down, through its move, and includes its up. These events should be - // given to the method on the zoom controller. - private boolean mInZoomTapDragMode = false; - // Whether to prevent drag during touch. The initial value depends on // mForwardTouchEvents. If WebCore wants touch events, we assume it will // take control of touch events unless it says no for touch down event. @@ -361,7 +355,7 @@ public class WebView extends AbsoluteLayout private static final int UPDATE_TEXT_ENTRY_ADAPTER = 6; private static final int SWITCH_TO_ENTER = 7; private static final int RESUME_WEBCORE_UPDATE = 8; - private static final int DISMISS_ZOOM_RING_TUTORIAL = 9; + private static final int DISMISS_ZOOM_TUTORIAL = 9; //! arg1=x, arg2=y static final int SCROLL_TO_MSG_ID = 10; @@ -417,11 +411,6 @@ public class WebView extends AbsoluteLayout // width which view is considered to be fully zoomed out static final int ZOOM_OUT_WIDTH = 1024; - private static final float MAX_ZOOM_RING_ANGLE = (float) (Math.PI * 2 / 3); - private static final int ZOOM_RING_STEPS = 4; - private static final float ZOOM_RING_ANGLE_UNIT = MAX_ZOOM_RING_ANGLE - / ZOOM_RING_STEPS; - private static final float DEFAULT_MAX_ZOOM_SCALE = 2; private static final float DEFAULT_MIN_ZOOM_SCALE = (float) 1/3; // scale limit, which can be set through viewport meta tag in the web page @@ -560,146 +549,52 @@ public class WebView extends AbsoluteLayout } private ZoomButtonsController mZoomButtonsController; + private ImageView mZoomOverviewButton; - private ZoomRingController mZoomRingController; - private ImageView mZoomRingOverview; - private Animation mZoomRingOverviewExitAnimation; - - // These keep track of the center point of the zoom ring. They are used to + // These keep track of the center point of the zoom. They are used to // determine the point around which we should zoom. private float mZoomCenterX; private float mZoomCenterY; - private ZoomRingController.OnZoomListener mZoomListener = - new ZoomRingController.OnZoomListener() { - - private float mClockwiseBound; - private float mCounterClockwiseBound; - private float mStartScale; + private ZoomButtonsController.OnZoomListener mZoomListener = + new ZoomButtonsController.OnZoomListener() { public void onCenter(int x, int y) { // Don't translate when the control is invoked, hence we do nothing // in this callback } - public void onBeginPan() { - setZoomOverviewVisible(false); + public void onOverview() { + mZoomButtonsController.setVisible(false); + zoomScrollOut(); if (mLogEvent) { Checkin.updateStats(mContext.getContentResolver(), - Checkin.Stats.Tag.BROWSER_ZOOM_RING_DRAG, 1, 0.0); + Checkin.Stats.Tag.BROWSER_ZOOM_OVERVIEW, 1, 0.0); } } - public boolean onPan(int deltaX, int deltaY) { - return pinScrollBy(deltaX, deltaY, false, 0); - } - - public void onEndPan() { - } - public void onVisibilityChanged(boolean visible) { if (visible) { switchOutDrawHistory(); - if (mMaxZoomScale - 1 > ZOOM_RING_STEPS * 0.01f) { - mClockwiseBound = (float) (2 * Math.PI - MAX_ZOOM_RING_ANGLE); - } else { - mClockwiseBound = (float) (2 * Math.PI); - } - mZoomRingController.setThumbClockwiseBound(mClockwiseBound); - if (1 - mMinZoomScale > ZOOM_RING_STEPS * 0.01f) { - mCounterClockwiseBound = MAX_ZOOM_RING_ANGLE; - } else { - mCounterClockwiseBound = 0; - } - mZoomRingController - .setThumbCounterclockwiseBound(mCounterClockwiseBound); - float angle = 0f; - if (mActualScale > 1 && mClockwiseBound < (float) (2 * Math.PI)) { - angle = -(float) Math.round(ZOOM_RING_STEPS - * (mActualScale - 1) / (mMaxZoomScale - 1)) - / ZOOM_RING_STEPS; - } else if (mActualScale < 1 && mCounterClockwiseBound > 0) { - angle = (float) Math.round(ZOOM_RING_STEPS - * (1 - mActualScale) / (1 - mMinZoomScale)) - / ZOOM_RING_STEPS; - } - mZoomRingController.setThumbAngle(angle * MAX_ZOOM_RING_ANGLE); - - // Don't show a thumb if the user cannot zoom - mZoomRingController.setThumbVisible(mMinZoomScale != mMaxZoomScale); - - // Show the zoom overview tab on the ring - setZoomOverviewVisible(true); - if (mLogEvent) { - Checkin.updateStats(mContext.getContentResolver(), - Checkin.Stats.Tag.BROWSER_ZOOM_RING, 1, 0.0); - } + mZoomButtonsController.setOverviewVisible(true); + updateButtonsEnabled(); } } - public void onBeginDrag() { - mPreviewZoomOnly = true; - mStartScale = mActualScale; - setZoomOverviewVisible(false); - } - - public void onEndDrag() { - mPreviewZoomOnly = false; - if (mLogEvent) { - EventLog.writeEvent(EVENT_LOG_ZOOM_LEVEL_CHANGE, - (int) mStartScale * 100, (int) mActualScale * 100, - System.currentTimeMillis()); - } - setNewZoomScale(mActualScale, true); + private void updateButtonsEnabled() { + mZoomButtonsController.setZoomInEnabled(mActualScale < mMaxZoomScale); + mZoomButtonsController.setZoomOutEnabled(mActualScale > mMinZoomScale); } - public boolean onDragZoom(int deltaZoomLevel, int centerX, - int centerY, float startAngle, float curAngle) { - if (deltaZoomLevel < 0 - && Math.abs(mActualScale - mMinZoomScale) < 0.01f - || deltaZoomLevel > 0 - && Math.abs(mActualScale - mMaxZoomScale) < 0.01f - || deltaZoomLevel == 0) { - return false; - } - mZoomCenterX = (float) centerX; - mZoomCenterY = (float) centerY; - - float scale = 1.0f; - // curAngle is [0, 2 * Math.PI) - if (curAngle < (float) Math.PI) { - if (curAngle >= mCounterClockwiseBound) { - scale = mMinZoomScale; - } else { - scale = 1 - (float) Math.round(curAngle - / ZOOM_RING_ANGLE_UNIT) / ZOOM_RING_STEPS - * (1 - mMinZoomScale); - } - } else { - if (curAngle <= mClockwiseBound) { - scale = mMaxZoomScale; - } else { - scale = 1 + (float) Math.round( - ((float) 2 * Math.PI - curAngle) - / ZOOM_RING_ANGLE_UNIT) / ZOOM_RING_STEPS - * (mMaxZoomScale - 1); - } - } - zoomWithPreview(scale); - return true; - } - - public void onSimpleZoom(boolean zoomIn, int centerX, int centerY) { - mZoomCenterX = (float) centerX; - mZoomCenterY = (float) centerY; - + public void onZoom(boolean zoomIn) { if (zoomIn) { zoomIn(); } else { zoomOut(); } + + updateButtonsEnabled(); } - }; /** @@ -738,34 +633,8 @@ public class WebView extends AbsoluteLayout mFocusData.mX = 0; mFocusData.mY = 0; mScroller = new Scroller(context); - mZoomRingController = new ZoomRingController(context, this); - mZoomRingController.setCallback(mZoomListener); - mZoomRingController.setTrackDrawable( - com.android.internal.R.drawable.zoom_ring_track_absolute); - float density = context.getResources().getDisplayMetrics().density; - mZoomRingController.setPannerAcceleration((int) (160 * density)); - mZoomRingController.setPannerStartAcceleratingDuration((int) (700 * density)); - createZoomRingOverviewTab(); mZoomButtonsController = new ZoomButtonsController(context, this); - mZoomButtonsController.setOverviewVisible(true); - mZoomButtonsController.setCallback(new ZoomButtonsController.OnZoomListener() { - public void onCenter(int x, int y) { - mZoomListener.onCenter(x, y); - } - - public void onOverview() { - mZoomButtonsController.setVisible(false); - zoomScrollOut(); - } - - public void onVisibilityChanged(boolean visible) { - mZoomListener.onVisibilityChanged(visible); - } - - public void onZoom(boolean zoomIn) { - mZoomListener.onSimpleZoom(zoomIn, getWidth() / 2, getHeight() / 2); - } - }); + mZoomButtonsController.setCallback(mZoomListener); } private void init() { @@ -783,67 +652,6 @@ public class WebView extends AbsoluteLayout mDoubleTapSlopSquare = doubleTapslop * doubleTapslop; } - private void createZoomRingOverviewTab() { - Context context = getContext(); - - mZoomRingOverviewExitAnimation = AnimationUtils.loadAnimation(context, - com.android.internal.R.anim.fade_out); - - mZoomRingOverview = new ImageView(context); - mZoomRingOverview.setBackgroundResource( - com.android.internal.R.drawable.zoom_ring_overview_tab); - mZoomRingOverview.setImageResource(com.android.internal.R.drawable.btn_zoom_page); - - FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( - FrameLayout.LayoutParams.WRAP_CONTENT, - FrameLayout.LayoutParams.WRAP_CONTENT, - Gravity.CENTER); - // TODO: magic constant that's based on the zoom ring radius + some offset - lp.topMargin = 200; - mZoomRingOverview.setLayoutParams(lp); - mZoomRingOverview.setOnClickListener(new View.OnClickListener() { - public void onClick(View v) { - // Hide the zoom ring - mZoomRingController.setVisible(false); - if (mLogEvent) { - Checkin.updateStats(mContext.getContentResolver(), - Checkin.Stats.Tag.BROWSER_ZOOM_OVERVIEW, 1, 0.0); - } - zoomScrollOut(); - }}); - - // Measure the overview View to figure out its height - mZoomRingOverview.forceLayout(); - mZoomRingOverview.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)); - - ViewGroup container = mZoomRingController.getContainer(); - // Find the index of the zoom ring in the container - View zoomRing = container.findViewById(mZoomRingController.getZoomRingId()); - int zoomRingIndex; - for (zoomRingIndex = container.getChildCount() - 1; zoomRingIndex >= 0; zoomRingIndex--) { - if (container.getChildAt(zoomRingIndex) == zoomRing) break; - } - // Add the overview tab below the zoom ring (so we don't steal its events) - container.addView(mZoomRingOverview, zoomRingIndex); - // Since we use margins to adjust the vertical placement of the tab, the widget - // ends up getting clipped off. Ensure the container is big enough for - // us. - int myHeight = mZoomRingOverview.getMeasuredHeight() + lp.topMargin / 2; - // Multiplied by 2 b/c the zoom ring needs to be centered on the screen - container.setMinimumHeight(myHeight * 2); - } - - private void setZoomOverviewVisible(boolean visible) { - int newVisibility = visible ? View.VISIBLE : View.INVISIBLE; - if (mZoomRingOverview.getVisibility() == newVisibility) return; - - if (!visible) { - mZoomRingOverview.startAnimation(mZoomRingOverviewExitAnimation); - } - mZoomRingOverview.setVisibility(newVisibility); - } - /* package */ boolean onSavePassword(String schemePlusHost, String username, String password, final Message resumeMsg) { boolean rVal = false; @@ -2988,6 +2796,7 @@ public class WebView extends AbsoluteLayout * @param end End of selection to delete. */ /* package */ void deleteSelection(int start, int end) { + mTextGeneration++; mWebViewCore.sendMessage(EventHub.DELETE_SELECTION, start, end, new WebViewCore.FocusData(mFocusData)); } @@ -3452,8 +3261,7 @@ public class WebView extends AbsoluteLayout p.setOnHierarchyChangeListener(null); } - // Clean up the zoom ring - mZoomRingController.setVisible(false); + // Clean up the zoom controller mZoomButtonsController.setVisible(false); } @@ -3565,9 +3373,7 @@ public class WebView extends AbsoluteLayout @Override protected void onSizeChanged(int w, int h, int ow, int oh) { super.onSizeChanged(w, h, ow, oh); - // Center zooming to the center of the screen. This is appropriate for - // this case of zooming, and it also sets us up properly if we remove - // the new zoom ring controller + // Center zooming to the center of the screen. mZoomCenterX = getViewWidth() * .5f; mZoomCenterY = getViewHeight() * .5f; @@ -3641,13 +3447,13 @@ public class WebView extends AbsoluteLayout return false; } - if (mShowZoomRingTutorial && getSettings().supportZoom() - && (mMaxZoomScale - mMinZoomScale) > ZOOM_RING_STEPS * 0.01f) { - ZoomRingController.showZoomTutorialOnce(mContext); - mShowZoomRingTutorial = false; + if (mShowZoomTutorial && getSettings().supportZoom() + && (mMaxZoomScale != mMinZoomScale)) { + ZoomButtonsController.showZoomTutorialOnce(mContext); + mShowZoomTutorial = false; mPrivateHandler.sendMessageDelayed(mPrivateHandler - .obtainMessage(DISMISS_ZOOM_RING_TUTORIAL), - ZOOM_RING_TUTORIAL_DURATION); + .obtainMessage(DISMISS_ZOOM_TUTORIAL), + ZOOM_TUTORIAL_DURATION); } if (LOGV_ENABLED) { @@ -3655,15 +3461,6 @@ public class WebView extends AbsoluteLayout + mTouchMode); } - if ((mZoomRingController.isVisible() || mZoomButtonsController.isVisible()) - && mInZoomTapDragMode) { - if (ev.getAction() == MotionEvent.ACTION_UP) { - // Just released the second tap, no longer in tap-drag mode - mInZoomTapDragMode = false; - } - return mZoomRingController.handleDoubleTapEvent(ev); - } - int action = ev.getAction(); float x = ev.getX(); float y = ev.getY(); @@ -3689,7 +3486,7 @@ public class WebView extends AbsoluteLayout WebViewCore.TouchEventData ted = new WebViewCore.TouchEventData(); ted.mAction = action; ted.mX = viewToContent((int) x + mScrollX); - ted.mY = viewToContent((int) y + mScrollY);; + ted.mY = viewToContent((int) y + mScrollY); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); mLastSentTouchTime = eventTime; } @@ -3721,7 +3518,7 @@ public class WebView extends AbsoluteLayout nativeMoveSelection(viewToContent(mSelectX) , viewToContent(mSelectY), false); mTouchSelection = mExtendSelection = true; - } else if (!ZoomRingController.useOldZoom(mContext) && + } else if (!ZoomButtonsController.useOldZoom(mContext) && mPrivateHandler.hasMessages(RELEASE_SINGLE_TAP) && (deltaX * deltaX + deltaY * deltaY < mDoubleTapSlopSquare)) { // Found doubletap, invoke the zoom controller @@ -3732,13 +3529,11 @@ public class WebView extends AbsoluteLayout mTextEntry.updateCachedTextfield(); } nativeClearFocus(contentX, contentY); - mInZoomTapDragMode = true; if (mLogEvent) { EventLog.writeEvent(EVENT_LOG_DOUBLE_TAP_DURATION, (eventTime - mLastTouchUpTime), eventTime); } - return mZoomRingController.handleDoubleTapEvent(ev) || - mZoomButtonsController.handleDoubleTapEvent(ev); + return mZoomButtonsController.handleDoubleTapEvent(ev); } else { mTouchMode = TOUCH_INIT_MODE; mPreventDrag = mForwardTouchEvents; @@ -3747,9 +3542,8 @@ public class WebView extends AbsoluteLayout (eventTime - mLastTouchUpTime), eventTime); } } - // don't trigger the link if zoom ring is visible - if (mTouchMode == TOUCH_INIT_MODE - && !mZoomRingController.isVisible()) { + // Trigger the link + if (mTouchMode == TOUCH_INIT_MODE) { mPrivateHandler.sendMessageDelayed(mPrivateHandler .obtainMessage(SWITCH_TO_SHORTPRESS), TAP_TIMEOUT); } @@ -3885,7 +3679,7 @@ public class WebView extends AbsoluteLayout mUserScroll = true; } - if (ZoomRingController.useOldZoom(mContext)) { + if (ZoomButtonsController.useOldZoom(mContext)) { boolean showPlusMinus = mMinZoomScale < mMaxZoomScale; boolean showMagnify = canZoomScrollOut(); if (mZoomControls != null && (showPlusMinus || showMagnify)) { @@ -3909,15 +3703,6 @@ public class WebView extends AbsoluteLayout mLastTouchUpTime = eventTime; switch (mTouchMode) { case TOUCH_INIT_MODE: // tap - if (mZoomRingController.isVisible()) { - // don't trigger the link if zoom ring is visible, - // but still allow the double tap - mPrivateHandler.sendMessageDelayed(mPrivateHandler - .obtainMessage(RELEASE_SINGLE_TAP, - new Boolean(false)), - DOUBLE_TAP_TIMEOUT); - break; - } mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS); if (getSettings().supportZoom()) { mPrivateHandler.sendMessageDelayed(mPrivateHandler @@ -4431,14 +4216,6 @@ public class WebView extends AbsoluteLayout return mZoomControls; } - /** - * @hide pending API council? Assuming we make ZoomRingController itself - * public, which I think we will. - */ - public ZoomRingController getZoomRingController() { - return mZoomRingController; - } - /** * Perform zoom in in the webview * @return TRUE if zoom in succeeds. FALSE if no zoom changes. @@ -4482,9 +4259,6 @@ public class WebView extends AbsoluteLayout }); zoomControls.setOnZoomMagnifyClickListener(new OnClickListener() { public void onClick(View v) { - // Hide the zoom ring - mZoomRingController.setVisible(false); - mPrivateHandler.removeCallbacks(mZoomControlRunnable); mPrivateHandler.postDelayed(mZoomControlRunnable, ZOOM_CONTROLS_TIMEOUT); @@ -4693,6 +4467,7 @@ public class WebView extends AbsoluteLayout arg.put("replace", replace); arg.put("start", new Integer(newStart)); arg.put("end", new Integer(newEnd)); + mTextGeneration++; mWebViewCore.sendMessage(EventHub.REPLACE_TEXT, oldStart, oldEnd, arg); } @@ -5006,8 +4781,8 @@ public class WebView extends AbsoluteLayout } break; - case DISMISS_ZOOM_RING_TUTORIAL: - mZoomRingController.finishZoomTutorial(); + case DISMISS_ZOOM_TUTORIAL: + mZoomButtonsController.finishZoomTutorial(); break; default: diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index d72570aca1c33..f517dc9240926 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -41,6 +41,10 @@ import android.view.ViewConfiguration; import android.view.ViewDebug; import android.view.ViewGroup; import android.view.ViewTreeObserver; +import android.view.inputmethod.CompletionInfo; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputConnection; +import android.view.inputmethod.InputConnectionWrapper; import android.view.inputmethod.InputMethodManager; import android.view.ContextMenu.ContextMenuInfo; @@ -899,6 +903,10 @@ public abstract class AbsListView extends AdapterView implements Te } private boolean acceptFilter() { + if (!mTextFilterEnabled || !(getAdapter() instanceof Filterable) || + ((Filterable) getAdapter()).getFilter() == null) { + return false; + } final Context context = mContext; final InputMethodManager inputManager = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); @@ -1107,7 +1115,7 @@ public abstract class AbsListView extends AdapterView implements Te // filter popup needs to follow the widget. if (mFiltered && changed && getWindowVisibility() == View.VISIBLE && mPopup != null && mPopup.isShowing()) { - positionPopup(true); + positionPopup(); } return changed; @@ -2767,20 +2775,20 @@ public abstract class AbsListView extends AdapterView implements Te // Make sure we have a window before showing the popup if (getWindowVisibility() == View.VISIBLE) { createTextFilter(true); - positionPopup(false); + positionPopup(); // Make sure we get focus if we are showing the popup checkFocus(); } } - private void positionPopup(boolean update) { + private void positionPopup() { int screenHeight = getResources().getDisplayMetrics().heightPixels; final int[] xy = new int[2]; getLocationOnScreen(xy); // TODO: The 20 below should come from the theme and be expressed in dip // TODO: And the gravity should be defined in the theme as well final int bottomGap = screenHeight - xy[1] - getHeight() + (int) (mDensityScale * 20); - if (!update) { + if (!mPopup.isShowing()) { mPopup.showAtLocation(this, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, xy[0], bottomGap); } else { @@ -2849,8 +2857,7 @@ public abstract class AbsListView extends AdapterView implements Te * @return True if the text filter handled the event, false otherwise. */ boolean sendToTextFilter(int keyCode, int count, KeyEvent event) { - if (!mTextFilterEnabled || !(getAdapter() instanceof Filterable) || - ((Filterable) getAdapter()).getFilter() == null) { + if (!acceptFilter()) { return false; } @@ -2879,7 +2886,7 @@ public abstract class AbsListView extends AdapterView implements Te break; } - if (okToSend && acceptFilter()) { + if (okToSend) { createTextFilter(true); KeyEvent forwardEvent = event; @@ -2905,6 +2912,27 @@ public abstract class AbsListView extends AdapterView implements Te return handled; } + /** + * Return an InputConnection for editing of the filter text. + */ + @Override + public InputConnection onCreateInputConnection(EditorInfo outAttrs) { + // XXX we need to have the text filter created, so we can get an + // InputConnection to proxy to. Unfortunately this means we pretty + // much need to make it as soon as a list view gets focus. + createTextFilter(false); + return mTextFilter.onCreateInputConnection(outAttrs); + } + + /** + * For filtering we proxy an input connection to an internal text editor, + * and this allows the proxying to happen. + */ + @Override + public boolean checkInputConnectionProxy(View view) { + return view == mTextFilter; + } + /** * Creates the window for the text filter and populates it with an EditText field; * @@ -2918,6 +2946,11 @@ public abstract class AbsListView extends AdapterView implements Te c.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mTextFilter = (EditText) layoutInflater.inflate( com.android.internal.R.layout.typing_filter, null); + // For some reason setting this as the "real" input type changes + // the text view in some way that it doesn't work, and I don't + // want to figure out why this is. + mTextFilter.setRawInputType(EditorInfo.TYPE_CLASS_TEXT + | EditorInfo.TYPE_TEXT_VARIATION_FILTER); mTextFilter.addTextChangedListener(this); p.setFocusable(false); p.setTouchable(false); diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java index 0a552e8cf2add..3368477950253 100644 --- a/core/java/android/widget/FastScroller.java +++ b/core/java/android/widget/FastScroller.java @@ -26,7 +26,6 @@ import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.SystemClock; -import android.util.TypedValue; import android.view.MotionEvent; /** @@ -313,12 +312,17 @@ class FastScroller { // Non-existent letter while (section > 0) { section--; - prevIndex = mSectionIndexer.getPositionForSection(section); - if (prevIndex != index) { - prevSection = section; - sectionIndex = section; - break; - } + prevIndex = mSectionIndexer.getPositionForSection(section); + if (prevIndex != index) { + prevSection = section; + sectionIndex = section; + break; + } else if (section == 0) { + // When section reaches 0 here, sectionIndex must follow it. + // Assuming mSectionIndexer.getPositionForSection(0) == 0. + sectionIndex = 0; + break; + } } } // Find the next index, in case the assumed next index is not diff --git a/core/java/android/widget/Filter.java b/core/java/android/widget/Filter.java index 1d0fd5ead8c90..7e55c78a39b30 100644 --- a/core/java/android/widget/Filter.java +++ b/core/java/android/widget/Filter.java @@ -42,10 +42,12 @@ public abstract class Filter { private static final String THREAD_NAME = "Filter"; private static final int FILTER_TOKEN = 0xD0D0F00D; private static final int FINISH_TOKEN = 0xDEADBEEF; - + private Handler mThreadHandler; private Handler mResultHandler; + private final Object mLock = new Object(); + /** *

Creates a new asynchronous filter.

*/ @@ -81,8 +83,7 @@ public abstract class Filter { * @see #publishResults(CharSequence, android.widget.Filter.FilterResults) */ public final void filter(CharSequence constraint, FilterListener listener) { - synchronized (this) { - + synchronized (mLock) { if (mThreadHandler == null) { HandlerThread thread = new HandlerThread(THREAD_NAME); thread.start(); @@ -221,7 +222,7 @@ public abstract class Filter { message.sendToTarget(); } - synchronized (this) { + synchronized (mLock) { if (mThreadHandler != null) { Message finishMessage = mThreadHandler.obtainMessage(FINISH_TOKEN); mThreadHandler.sendMessageDelayed(finishMessage, 3000); @@ -229,7 +230,7 @@ public abstract class Filter { } break; case FINISH_TOKEN: - synchronized (this) { + synchronized (mLock) { if (mThreadHandler != null) { mThreadHandler.getLooper().quit(); mThreadHandler = null; diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java index f2cec92e708e4..227fb9571d2f7 100644 --- a/core/java/android/widget/MediaController.java +++ b/core/java/android/widget/MediaController.java @@ -451,6 +451,7 @@ public class MediaController extends FrameLayout { public void onProgressChanged(SeekBar bar, int progress, boolean fromtouch) { if (fromtouch) { mDragging = true; + duration = mPlayer.getDuration(); long newposition = (duration * progress) / 1000L; mPlayer.seekTo( (int) newposition); if (mCurrentTime != null) diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 3f4912f3c9fdf..8271a9a071e06 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -43,6 +43,7 @@ import android.text.GetChars; import android.text.GraphicsOperations; import android.text.ClipboardManager; import android.text.InputFilter; +import android.text.InputType; import android.text.Layout; import android.text.ParcelableSpan; import android.text.Selection; @@ -235,7 +236,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private CharWrapper mCharWrapper = null; private boolean mSelectionMoved = false; - private boolean mTouchFocusSelectedAll = false; + private boolean mTouchFocusSelected = false; private Marquee mMarquee; private boolean mRestartMarquee; @@ -243,7 +244,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private int mMarqueeRepeatLimit = 3; class InputContentType { - int imeOptions = EditorInfo.IME_UNDEFINED; + int imeOptions = EditorInfo.IME_NULL; String privateImeOptions; CharSequence imeActionLabel; int imeActionId; @@ -261,6 +262,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final ExtractedText mTmpExtracted = new ExtractedText(); int mBatchEditNesting; boolean mCursorChanged; + boolean mSelectionModeChanged; boolean mContentChanged; int mChangedStart, mChangedEnd, mChangedDelta; } @@ -287,8 +289,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * * @param v The view that was clicked. * @param actionId Identifier of the action. This will be either the - * identifier you supplied, or {@link EditorInfo#IME_UNDEFINED - * EditorInfo.IME_UNDEFINED} if being called due to the enter key + * identifier you supplied, or {@link EditorInfo#IME_NULL + * EditorInfo.IME_NULL} if being called due to the enter key * being pressed. * @param event If triggered by an enter key, this is the event; * otherwise, this is null. @@ -1492,10 +1494,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener @Override public void setPadding(int left, int top, int right, int bottom) { - if (left != getPaddingLeft() || - right != getPaddingRight() || - top != getPaddingTop() || - bottom != getPaddingBottom()) { + if (left != mPaddingLeft || + right != mPaddingRight || + top != mPaddingTop || + bottom != mPaddingBottom) { nullLayouts(); } @@ -2951,7 +2953,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ public int getImeOptions() { return mInputContentType != null - ? mInputContentType.imeOptions : EditorInfo.IME_UNDEFINED; + ? mInputContentType.imeOptions : EditorInfo.IME_NULL; } /** @@ -3013,9 +3015,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * Called when an attached input method calls * {@link InputConnection#performEditorAction(int) * InputConnection.performEditorAction()} - * for this text view. The default implementation will call your click - * listener supplied to {@link #setOnEditorActionListener}, - * or generate an enter key down/up pair to invoke the action if not. + * for this text view. The default implementation will call your action + * listener supplied to {@link #setOnEditorActionListener}, or perform + * a standard operation for {@link EditorInfo#IME_ACTION_NEXT + * EditorInfo.IME_ACTION_NEXT} or {@link EditorInfo#IME_ACTION_DONE + * EditorInfo.IME_ACTION_DONE}. + * + *

For backwards compatibility, if no IME options have been set and the + * text view would not normally advance focus on enter, then + * the NEXT and DONE actions received here will be turned into an enter + * key down/up pair to go through the normal key handling. * * @param actionCode The code of the action being performed. * @@ -3052,6 +3061,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (imm != null) { imm.hideSoftInputFromWindow(getWindowToken(), 0); } + return; } } @@ -3844,7 +3854,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (imm != null) { if (imm.isActive(this)) { boolean reported = false; - if (ims.mContentChanged) { + if (ims.mContentChanged || ims.mSelectionModeChanged) { // We are in extract mode and the content has changed // in some way... just report complete new text to the // input method. @@ -4197,7 +4207,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener && mInputContentType.enterDown) { mInputContentType.enterDown = false; if (mInputContentType.onEditorActionListener.onEditorAction( - this, EditorInfo.IME_UNDEFINED, event)) { + this, EditorInfo.IME_NULL, event)) { return true; } } @@ -4272,17 +4282,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener outAttrs.actionId = mInputContentType.imeActionId; outAttrs.extras = mInputContentType.extras; } else { - outAttrs.imeOptions = EditorInfo.IME_UNDEFINED; + outAttrs.imeOptions = EditorInfo.IME_NULL; } - if (outAttrs.imeOptions == EditorInfo.IME_UNDEFINED) { + if ((outAttrs.imeOptions&EditorInfo.IME_MASK_ACTION) + == EditorInfo.IME_ACTION_UNSPECIFIED) { if (focusSearch(FOCUS_DOWN) != null) { // An action has not been set, but the enter key will move to // the next focus, so set the action to that. - outAttrs.imeOptions = EditorInfo.IME_ACTION_NEXT; + outAttrs.imeOptions |= EditorInfo.IME_ACTION_NEXT; } else { // An action has not been set, and there is no focus to move // to, so let's just supply a "done" action. - outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE; + outAttrs.imeOptions |= EditorInfo.IME_ACTION_DONE; } if (!shouldAdvanceFocusOnEnter()) { outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_ENTER_ACTION; @@ -4307,51 +4318,64 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ public boolean extractText(ExtractedTextRequest request, ExtractedText outText) { - return extractTextInternal(request, -1, -1, -1, outText); + return extractTextInternal(request, EXTRACT_UNKNOWN, EXTRACT_UNKNOWN, + EXTRACT_UNKNOWN, outText); } + static final int EXTRACT_NOTHING = -2; + static final int EXTRACT_UNKNOWN = -1; + boolean extractTextInternal(ExtractedTextRequest request, int partialStartOffset, int partialEndOffset, int delta, ExtractedText outText) { final CharSequence content = mText; if (content != null) { - final int N = content.length(); - if (partialStartOffset < 0) { - outText.partialStartOffset = outText.partialEndOffset = -1; - partialStartOffset = 0; - partialEndOffset = N; - } else { - // Adjust offsets to ensure we contain full spans. - if (content instanceof Spanned) { - Spanned spanned = (Spanned)content; - Object[] spans = spanned.getSpans(partialStartOffset, - partialEndOffset, ParcelableSpan.class); - int i = spans.length; - while (i > 0) { - i--; - int j = spanned.getSpanStart(spans[i]); - if (j < partialStartOffset) partialStartOffset = j; - j = spanned.getSpanEnd(spans[i]); - if (j > partialEndOffset) partialEndOffset = j; + if (partialStartOffset != EXTRACT_NOTHING) { + final int N = content.length(); + if (partialStartOffset < 0) { + outText.partialStartOffset = outText.partialEndOffset = -1; + partialStartOffset = 0; + partialEndOffset = N; + } else { + // Adjust offsets to ensure we contain full spans. + if (content instanceof Spanned) { + Spanned spanned = (Spanned)content; + Object[] spans = spanned.getSpans(partialStartOffset, + partialEndOffset, ParcelableSpan.class); + int i = spans.length; + while (i > 0) { + i--; + int j = spanned.getSpanStart(spans[i]); + if (j < partialStartOffset) partialStartOffset = j; + j = spanned.getSpanEnd(spans[i]); + if (j > partialEndOffset) partialEndOffset = j; + } + } + outText.partialStartOffset = partialStartOffset; + outText.partialEndOffset = partialEndOffset; + // Now use the delta to determine the actual amount of text + // we need. + partialEndOffset += delta; + if (partialEndOffset > N) { + partialEndOffset = N; + } else if (partialEndOffset < 0) { + partialEndOffset = 0; } } - outText.partialStartOffset = partialStartOffset; - outText.partialEndOffset = partialEndOffset; - // Now use the delta to determine the actual amount of text - // we need. - partialEndOffset += delta; - if (partialEndOffset > N) { - partialEndOffset = N; - } else if (partialEndOffset < 0) { - partialEndOffset = 0; + if ((request.flags&InputConnection.GET_TEXT_WITH_STYLES) != 0) { + outText.text = content.subSequence(partialStartOffset, + partialEndOffset); + } else { + outText.text = TextUtils.substring(content, partialStartOffset, + partialEndOffset); } } - if ((request.flags&InputConnection.GET_TEXT_WITH_STYLES) != 0) { - outText.text = content.subSequence(partialStartOffset, - partialEndOffset); - } else { - outText.text = TextUtils.substring(content, partialStartOffset, - partialEndOffset); + outText.flags = 0; + if (MetaKeyKeyListener.getMetaState(mText, MetaKeyKeyListener.META_SELECTING) != 0) { + outText.flags |= ExtractedText.FLAG_SELECTING; + } + if (mSingleLine) { + outText.flags |= ExtractedText.FLAG_SINGLE_LINE; } outText.startOffset = 0; outText.selectionStart = Selection.getSelectionStart(content); @@ -4363,8 +4387,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener boolean reportExtractedText() { final InputMethodState ims = mInputMethodState; - if (ims != null && ims.mContentChanged) { + final boolean contentChanged = ims.mContentChanged; + if (ims != null && (contentChanged || ims.mSelectionModeChanged)) { ims.mContentChanged = false; + ims.mSelectionModeChanged = false; final ExtractedTextRequest req = mInputMethodState.mExtracting; if (req != null) { InputMethodManager imm = InputMethodManager.peekInstance(); @@ -4372,6 +4398,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (DEBUG_EXTRACT) Log.v(TAG, "Retrieving extracted start=" + ims.mChangedStart + " end=" + ims.mChangedEnd + " delta=" + ims.mChangedDelta); + if (ims.mChangedStart < 0 && !contentChanged) { + ims.mChangedStart = EXTRACT_NOTHING; + } if (extractTextInternal(req, ims.mChangedStart, ims.mChangedEnd, ims.mChangedDelta, ims.mTmpExtracted)) { if (DEBUG_EXTRACT) Log.v(TAG, "Reporting extracted start=" @@ -4408,19 +4437,21 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener */ public void setExtractedText(ExtractedText text) { Editable content = getEditableText(); - if (content == null) { - setText(text.text, TextView.BufferType.EDITABLE); - } else if (text.partialStartOffset < 0) { - removeParcelableSpans(content, 0, content.length()); - content.replace(0, content.length(), text.text); - } else { - final int N = content.length(); - int start = text.partialStartOffset; - if (start > N) start = N; - int end = text.partialEndOffset; - if (end > N) end = N; - removeParcelableSpans(content, start, end); - content.replace(start, end, text.text); + if (text.text != null) { + if (content == null) { + setText(text.text, TextView.BufferType.EDITABLE); + } else if (text.partialStartOffset < 0) { + removeParcelableSpans(content, 0, content.length()); + content.replace(0, content.length(), text.text); + } else { + final int N = content.length(); + int start = text.partialStartOffset; + if (start > N) start = N; + int end = text.partialEndOffset; + if (end > N) end = N; + removeParcelableSpans(content, start, end); + content.replace(start, end, text.text); + } } // Now set the selection position... make sure it is in range, to @@ -4436,6 +4467,13 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (end < 0) end = 0; else if (end > N) end = N; Selection.setSelection(sp, start, end); + + // Finally, update the selection mode. + if ((text.flags&ExtractedText.FLAG_SELECTING) != 0) { + MetaKeyKeyListener.startSelecting(this, sp); + } else { + MetaKeyKeyListener.stopSelecting(this, sp); + } } /** @@ -4473,8 +4511,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener ims.mChangedStart = 0; ims.mChangedEnd = mText.length(); } else { - ims.mChangedStart = -1; - ims.mChangedEnd = -1; + ims.mChangedStart = EXTRACT_UNKNOWN; + ims.mChangedEnd = EXTRACT_UNKNOWN; ims.mContentChanged = false; } onBeginBatchEdit(); @@ -4503,7 +4541,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener void finishBatchEdit(final InputMethodState ims) { onEndBatchEdit(); - if (ims.mContentChanged) { + if (ims.mContentChanged || ims.mSelectionModeChanged) { updateAfterEdit(); reportExtractedText(); } else if (ims.mCursorChanged) { @@ -5888,6 +5926,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (MetaKeyKeyListener.isMetaTracker(buf, what)) { mHighlightPathBogus = true; + if (ims != null && MetaKeyKeyListener.isSelectingMetaTracker(buf, what)) { + ims.mSelectionModeChanged = true; + } if (Selection.getSelectionStart(buf) >= 0) { if (ims == null || ims.mBatchEditNesting == 0) { @@ -6026,7 +6067,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mSelectAllOnFocus) { Selection.setSelection((Spannable) mText, 0, mText.length()); - mTouchFocusSelectedAll = true; } if (selMoved && selStart >= 0 && selEnd >= 0) { @@ -6042,6 +6082,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener Selection.setSelection((Spannable) mText, selStart, selEnd); } + mTouchFocusSelected = true; } mFrozenWithFocus = false; @@ -6149,7 +6190,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (action == MotionEvent.ACTION_DOWN) { // Reset this state; it will be re-set if super.onTouchEvent // causes focus to move to the view. - mTouchFocusSelectedAll = false; + mTouchFocusSelected = false; } final boolean superResult = super.onTouchEvent(event); @@ -6218,10 +6259,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener /** * Returns true, only while processing a touch gesture, if the initial * touch down event caused focus to move to the text view and as a result - * it selected all of its text. + * its selection changed. Only valid while processing the touch gesture + * of interest. */ - public boolean didTouchFocusSelectAll() { - return mTouchFocusSelectedAll; + public boolean didTouchFocusSelect() { + return mTouchFocusSelected; } @Override @@ -6351,6 +6393,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return super.computeVerticalScrollRange(); } + @Override + protected int computeVerticalScrollExtent() { + return getHeight() - getCompoundPaddingTop() - getCompoundPaddingBottom(); + } + public enum BufferType { NORMAL, SPANNABLE, EDITABLE, } @@ -6497,6 +6544,26 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener * or null if there is no cursor or no word at the cursor. */ private String getWordForDictionary() { + /* + * Quick return if the input type is one where adding words + * to the dictionary doesn't make any sense. + */ + int klass = mInputType & InputType.TYPE_MASK_CLASS; + if (klass == InputType.TYPE_CLASS_NUMBER || + klass == InputType.TYPE_CLASS_PHONE || + klass == InputType.TYPE_CLASS_DATETIME) { + return null; + } + + int variation = mInputType & InputType.TYPE_MASK_VARIATION; + if (variation == InputType.TYPE_TEXT_VARIATION_URI || + variation == InputType.TYPE_TEXT_VARIATION_PASSWORD || + variation == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD || + variation == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS || + variation == InputType.TYPE_TEXT_VARIATION_FILTER) { + return null; + } + int end = getSelectionEnd(); if (end < 0) { diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java index 1227afd9c186c..ec6f88bd5154f 100644 --- a/core/java/android/widget/VideoView.java +++ b/core/java/android/widget/VideoView.java @@ -46,8 +46,10 @@ import java.io.IOException; * such as scaling and tinting. */ public class VideoView extends SurfaceView implements MediaPlayerControl { + private String TAG = "VideoView"; // settable by the client private Uri mUri; + private int mDuration; // All the stuff we need for playing and showing a video private SurfaceHolder mSurfaceHolder = null; @@ -184,6 +186,8 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { mMediaPlayer.setOnPreparedListener(mPreparedListener); mMediaPlayer.setOnVideoSizeChangedListener(mSizeChangedListener); mIsPrepared = false; + Log.v(TAG, "reset duration to -1 in openVideo"); + mDuration = -1; mMediaPlayer.setOnCompletionListener(mCompletionListener); mMediaPlayer.setOnErrorListener(mErrorListener); mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener); @@ -195,10 +199,10 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { mMediaPlayer.prepareAsync(); attachMediaController(); } catch (IOException ex) { - Log.w("VideoView", "Unable to open content: " + mUri, ex); + Log.w(TAG, "Unable to open content: " + mUri, ex); return; } catch (IllegalArgumentException ex) { - Log.w("VideoView", "Unable to open content: " + mUri, ex); + Log.w(TAG, "Unable to open content: " + mUri, ex); return; } } @@ -299,7 +303,7 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { private MediaPlayer.OnErrorListener mErrorListener = new MediaPlayer.OnErrorListener() { public boolean onError(MediaPlayer mp, int a, int b) { - Log.d("VideoView", "Error: " + a + "," + b); + Log.d(TAG, "Error: " + a + "," + b); if (mMediaController != null) { mMediaController.hide(); } @@ -497,9 +501,14 @@ public class VideoView extends SurfaceView implements MediaPlayerControl { public int getDuration() { if (mMediaPlayer != null && mIsPrepared) { - return mMediaPlayer.getDuration(); + if (mDuration > 0) { + return mDuration; + } + mDuration = mMediaPlayer.getDuration(); + return mDuration; } - return -1; + mDuration = -1; + return mDuration; } public int getCurrentPosition() { diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java index ec45e23a76208..1ba2dce6d76c6 100644 --- a/core/java/android/widget/ZoomButtonsController.java +++ b/core/java/android/widget/ZoomButtonsController.java @@ -16,14 +16,19 @@ package android.widget; +import android.app.AlertDialog; +import android.app.Dialog; import android.content.BroadcastReceiver; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.SharedPreferences; import android.graphics.PixelFormat; import android.graphics.Rect; import android.os.Handler; import android.os.Message; +import android.os.SystemClock; import android.provider.Settings; import android.view.Gravity; import android.view.KeyEvent; @@ -31,6 +36,7 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewConfiguration; +import android.view.Window; import android.view.WindowManager; import android.view.View.OnClickListener; import android.view.WindowManager.LayoutParams; @@ -46,7 +52,7 @@ import android.view.WindowManager.LayoutParams; * * @hide */ -public class ZoomButtonsController implements View.OnTouchListener { +public class ZoomButtonsController implements View.OnTouchListener, View.OnKeyListener { private static final String TAG = "ZoomButtonsController"; @@ -60,13 +66,13 @@ public class ZoomButtonsController implements View.OnTouchListener { private WindowManager mWindowManager; /** - * The view that is being zoomed by this zoom ring. + * The view that is being zoomed by this zoom controller. */ private View mOwnerView; /** * The bounds of the owner view in global coordinates. This is recalculated - * each time the zoom ring is shown. + * each time the zoom controller is shown. */ private Rect mOwnerViewBounds = new Rect(); @@ -89,11 +95,13 @@ public class ZoomButtonsController implements View.OnTouchListener { */ private int[] mTouchTargetLocationInWindow = new int[2]; /** - * If the zoom ring is dismissed but the user is still in a touch + * If the zoom controller is dismissed but the user is still in a touch * interaction, we set this to true. This will ignore all touch events until * up/cancel, and then set the owner's touch listener to null. */ private boolean mReleaseTouchListenerOnUp; + + private boolean mIsSecondTapDown; private boolean mIsVisible; @@ -122,10 +130,16 @@ public class ZoomButtonsController implements View.OnTouchListener { } }; + /** + * The setting name that tracks whether we've shown the zoom tutorial. + */ + private static final String SETTING_NAME_SHOWN_TUTORIAL = "shown_zoom_tutorial"; + private static Dialog sTutorialDialog; + /** When configuration changes, this is called after the UI thread is idle. */ private static final int MSG_POST_CONFIGURATION_CHANGED = 2; - /** Used to delay the zoom ring dismissal. */ - private static final int MSG_DISMISS_ZOOM_RING = 3; + /** Used to delay the zoom controller dismissal. */ + private static final int MSG_DISMISS_ZOOM_CONTROLS = 3; /** * If setVisible(true) is called and the owner view's window token is null, * we delay the setVisible(true) call until it is not null. @@ -140,7 +154,7 @@ public class ZoomButtonsController implements View.OnTouchListener { onPostConfigurationChanged(); break; - case MSG_DISMISS_ZOOM_RING: + case MSG_DISMISS_ZOOM_CONTROLS: setVisible(false); break; @@ -148,7 +162,7 @@ public class ZoomButtonsController implements View.OnTouchListener { if (mOwnerView.getWindowToken() == null) { // Doh, it is still null, throw an exception throw new IllegalArgumentException( - "Cannot make the zoom ring visible if the owner view is " + + "Cannot make the zoom controller visible if the owner view is " + "not attached to a window."); } setVisible(true); @@ -165,11 +179,24 @@ public class ZoomButtonsController implements View.OnTouchListener { mContainer = createContainer(); } - + + public void setZoomInEnabled(boolean enabled) { + mControls.setIsZoomInEnabled(enabled); + } + + public void setZoomOutEnabled(boolean enabled) { + mControls.setIsZoomOutEnabled(enabled); + } + + public void setZoomSpeed(long speed) { + mControls.setZoomSpeed(speed); + } + private FrameLayout createContainer() { LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); lp.gravity = Gravity.BOTTOM | Gravity.CENTER; lp.flags = LayoutParams.FLAG_NOT_TOUCHABLE | + LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_LAYOUT_NO_LIMITS; lp.height = LayoutParams.WRAP_CONTENT; lp.width = LayoutParams.FILL_PARENT; @@ -182,6 +209,7 @@ public class ZoomButtonsController implements View.OnTouchListener { FrameLayout container = new FrameLayout(mContext); container.setLayoutParams(lp); container.setMeasureAllChildren(true); + container.setOnKeyListener(this); LayoutInflater inflater = (LayoutInflater) mContext .getSystemService(Context.LAYOUT_INFLATER_SERVICE); @@ -326,13 +354,13 @@ public class ZoomButtonsController implements View.OnTouchListener { return mContainer; } - public int getZoomRingId() { + public int getZoomControlsId() { return mControls.getId(); } private void dismissControlsDelayed(int delay) { - mHandler.removeMessages(MSG_DISMISS_ZOOM_RING); - mHandler.sendEmptyMessageDelayed(MSG_DISMISS_ZOOM_RING, delay); + mHandler.removeMessages(MSG_DISMISS_ZOOM_CONTROLS); + mHandler.sendEmptyMessageDelayed(MSG_DISMISS_ZOOM_CONTROLS, delay); } /** @@ -351,8 +379,21 @@ public class ZoomButtonsController implements View.OnTouchListener { int x = (int) event.getX(); int y = (int) event.getY(); + /* + * This class will consume all events in the second tap (down, + * move(s), up). But, the owner already got the second tap's down, + * so cancel that. Do this before setVisible, since that call + * will set us as a touch listener. + */ + MotionEvent cancelEvent = MotionEvent.obtain(event.getDownTime(), + SystemClock.elapsedRealtime(), + MotionEvent.ACTION_CANCEL, 0, 0, 0); + mOwnerView.dispatchTouchEvent(cancelEvent); + cancelEvent.recycle(); + setVisible(true); centerPoint(x, y); + mIsSecondTapDown = true; } return true; @@ -373,11 +414,23 @@ public class ZoomButtonsController implements View.OnTouchListener { } } + public boolean onKey(View v, int keyCode, KeyEvent event) { + dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT); + return false; + } + public boolean onTouch(View v, MotionEvent event) { int action = event.getAction(); + // Consume all events during the second-tap interaction (down, move, up/cancel) + boolean consumeEvent = mIsSecondTapDown; + if ((action == MotionEvent.ACTION_UP) || (action == MotionEvent.ACTION_CANCEL)) { + // The second tap can no longer be down + mIsSecondTapDown = false; + } + if (mReleaseTouchListenerOnUp) { - // The ring was dismissed but we need to throw away all events until the up + // The controls were dismissed but we need to throw away all events until the up if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { mOwnerView.setOnTouchListener(null); setTouchTargetView(null); @@ -417,10 +470,10 @@ public class ZoomButtonsController implements View.OnTouchListener { mOwnerViewBounds.top - targetViewRawY); boolean retValue = targetView.dispatchTouchEvent(containerEvent); containerEvent.recycle(); - return retValue; + return retValue || consumeEvent; } else { - return false; + return consumeEvent; } } @@ -465,10 +518,102 @@ public class ZoomButtonsController implements View.OnTouchListener { refreshPositioningVariables(); } - public static boolean useThisZoom(Context context) { - return ZoomRingController.getZoomType(context) == 2; + /* + * This is static so Activities can call this instead of the Views + * (Activities usually do not have a reference to the ZoomButtonsController + * instance.) + */ + /** + * Shows a "tutorial" (some text) to the user teaching her the new zoom + * invocation method. Must call from the main thread. + *

+ * It checks the global system setting to ensure this has not been seen + * before. Furthermore, if the application does not have privilege to write + * to the system settings, it will store this bit locally in a shared + * preference. + * + * @hide This should only be used by our main apps--browser, maps, and + * gallery + */ + public static void showZoomTutorialOnce(Context context) { + ContentResolver cr = context.getContentResolver(); + if (Settings.System.getInt(cr, SETTING_NAME_SHOWN_TUTORIAL, 0) == 1) { + return; + } + + SharedPreferences sp = context.getSharedPreferences("_zoom", Context.MODE_PRIVATE); + if (sp.getInt(SETTING_NAME_SHOWN_TUTORIAL, 0) == 1) { + return; + } + + if (sTutorialDialog != null && sTutorialDialog.isShowing()) { + sTutorialDialog.dismiss(); + } + + LayoutInflater layoutInflater = + (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + TextView textView = (TextView) layoutInflater.inflate( + com.android.internal.R.layout.alert_dialog_simple_text, null) + .findViewById(android.R.id.text1); + textView.setText(com.android.internal.R.string.tutorial_double_tap_to_zoom_message_short); + + sTutorialDialog = new AlertDialog.Builder(context) + .setView(textView) + .setIcon(0) + .create(); + + Window window = sTutorialDialog.getWindow(); + window.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM); + window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND | + WindowManager.LayoutParams.FLAG_BLUR_BEHIND); + window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | + WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); + + sTutorialDialog.show(); } - + + /** @hide Should only be used by Android platform apps */ + public static void finishZoomTutorial(Context context, boolean userNotified) { + if (sTutorialDialog == null) return; + + sTutorialDialog.dismiss(); + sTutorialDialog = null; + + // Record that they have seen the tutorial + if (userNotified) { + try { + Settings.System.putInt(context.getContentResolver(), SETTING_NAME_SHOWN_TUTORIAL, + 1); + } catch (SecurityException e) { + /* + * The app does not have permission to clear this global flag, make + * sure the user does not see the message when he comes back to this + * same app at least. + */ + SharedPreferences sp = context.getSharedPreferences("_zoom", Context.MODE_PRIVATE); + sp.edit().putInt(SETTING_NAME_SHOWN_TUTORIAL, 1).commit(); + } + } + } + + /** @hide Should only be used by Android platform apps */ + public void finishZoomTutorial() { + finishZoomTutorial(mContext, true); + } + + // Temporary methods for different zoom types + static int getZoomType(Context context) { + return Settings.System.getInt(context.getContentResolver(), "zoom", 1); + } + + public static boolean useOldZoom(Context context) { + return getZoomType(context) == 0; + } + + public static boolean useThisZoom(Context context) { + return getZoomType(context) == 2; + } + public interface OnZoomListener { void onCenter(int x, int y); void onVisibilityChanged(boolean visible); diff --git a/core/java/android/widget/ZoomControls.java b/core/java/android/widget/ZoomControls.java index fdc05b6e4b20f..e978db8b12c0b 100644 --- a/core/java/android/widget/ZoomControls.java +++ b/core/java/android/widget/ZoomControls.java @@ -81,7 +81,7 @@ public class ZoomControls extends LinearLayout { } public void show() { - if (ZoomRingController.useOldZoom(mContext)) { + if (ZoomButtonsController.useOldZoom(mContext)) { fade(View.VISIBLE, 0.0f, 1.0f); } } diff --git a/core/java/android/widget/ZoomRing.java b/core/java/android/widget/ZoomRing.java deleted file mode 100644 index 83a1225aed456..0000000000000 --- a/core/java/android/widget/ZoomRing.java +++ /dev/null @@ -1,1274 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.widget; - -import com.android.internal.R; - -import android.content.Context; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.graphics.Canvas; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.RotateDrawable; -import android.os.Handler; -import android.os.Message; -import android.os.SystemClock; -import android.util.AttributeSet; -import android.util.Log; -import android.view.HapticFeedbackConstants; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewConfiguration; - -/** - * A view that has a draggable thumb on a circle. - * - * @hide - */ -public class ZoomRing extends View { - private static final String TAG = "ZoomRing"; - - // TODO: Temporary until the trail is done - private static final boolean DRAW_TRAIL = false; - - /** - * To avoid floating point calculations and int round-offs, we multiply - * radians by this value. - */ - public static final int RADIAN_INT_MULTIPLIER = 10000; - /** The allowable margin of error when comparing two angles. */ - public static final int RADIAN_INT_ERROR = 100; - public static final int PI_INT_MULTIPLIED = (int) (Math.PI * RADIAN_INT_MULTIPLIER); - public static final int TWO_PI_INT_MULTIPLIED = PI_INT_MULTIPLIED * 2; - private static final int HALF_PI_INT_MULTIPLIED = PI_INT_MULTIPLIED / 2; - - private static final int DOUBLE_TAP_DISMISS_TIMEOUT = ViewConfiguration.getDoubleTapTimeout(); - private final int mTouchSlop; - - /** The slop when the user is grabbing the thumb. */ - private static final int THUMB_GRAB_SLOP = PI_INT_MULTIPLIED / 8; - /** The slop until a user starts dragging the thumb. */ - private static final int THUMB_DRAG_SLOP = PI_INT_MULTIPLIED / 12; - - /** The distance (in px) from the center of the ring to the center of the thumb. */ - private int mThumbDistance; - - /** The angle on a unit circle that is considered to be the zoom ring's 0 degree. */ - private int mZeroAngle = HALF_PI_INT_MULTIPLIED * 3; - - /** - * The maximum delta angle that the thumb can move. The primary use is to - * ensure that when a user taps on the ring, the movement to reach that - * target angle is not ambiguous (for example, if the thumb is at 0 and he - * taps 180, should the thumb go clockwise or counterclockwise? - *

- * Includes error because we compare this to the result of - * getDelta(getClosestTickeAngle(..), oldAngle) which ends up having some - * rounding error. - */ - private static final int MAX_ABS_JUMP_DELTA_ANGLE = (2 * PI_INT_MULTIPLIED / 3) + - RADIAN_INT_ERROR; - - /** The cached X of the zoom ring's center (in zoom ring coordinates). */ - private int mCenterX; - /** The cached Y of the zoom ring's center (in zoom ring coordinates). */ - private int mCenterY; - - /** The angle of the thumb (in int radians) */ - private int mThumbAngle; - /** The cached width/2 of the zoom ring. */ - private int mThumbHalfWidth; - /** The cached height/2 of the zoom ring. */ - private int mThumbHalfHeight; - - /** - * The bound for the thumb's movement when it is being dragged clockwise. - * Can be Integer.MIN_VALUE if there is no bound in this direction. - */ - private int mThumbCwBound = Integer.MIN_VALUE; - /** - * The bound for the thumb's movement when it is being dragged - * counterclockwise. Can be Integer.MIN_VALUE if there is no bound in this - * direction. - */ - private int mThumbCcwBound = Integer.MIN_VALUE; - - /** - * Whether to enforce the maximum absolute jump delta. See - * {@link #MAX_ABS_JUMP_DELTA_ANGLE}. - */ - private boolean mEnforceMaxAbsJump = true; - - /** The inner radius of the track. */ - private int mTrackInnerRadius; - /** Cached square of the inner radius of the track. */ - private int mTrackInnerRadiusSquared; - /** The outer radius of the track. */ - private int mTrackOuterRadius; - /** Cached square of the outer radius of the track. */ - private int mTrackOuterRadiusSquared; - - /** The raw X of where the widget previously was located. */ - private int mPreviousWidgetDragX; - /** The raw Y of where the widget previously was located. */ - private int mPreviousWidgetDragY; - - /** Whether the thumb should be visible. */ - private boolean mThumbVisible = true; - - /** The drawable for the thumb. */ - private Drawable mThumbDrawable; - - /** Shown beneath the thumb if we can still zoom in. */ - private Drawable mZoomInArrowDrawable; - /** Shown beneath the thumb if we can still zoom out. */ - private Drawable mZoomOutArrowDrawable; - - /** @see #mThumbArrowsToDraw */ - private static final int THUMB_ARROW_PLUS = 1 << 0; - /** @see #mThumbArrowsToDraw */ - private static final int THUMB_ARROW_MINUS = 1 << 1; - /** Bitwise-OR of {@link #THUMB_ARROW_MINUS} and {@link #THUMB_ARROW_PLUS} */ - private int mThumbArrowsToDraw; - - /** The duration for the thumb arrows fading out */ - private static final int THUMB_ARROWS_FADE_DURATION = 300; - /** The time when the fade out started. */ - private long mThumbArrowsFadeStartTime; - /** The current alpha for the thumb arrows. */ - private int mThumbArrowsAlpha = 255; - - /** The distance from the center to the zoom arrow hints (usually plus and minus). */ - private int mZoomArrowHintDistance; - /** The offset angle from the thumb angle to draw the zoom arrow hints. */ - private int mZoomArrowHintOffsetAngle = TWO_PI_INT_MULTIPLIED / 11; - /** Drawn (without rotation) on top of the arrow. */ - private Drawable mZoomInArrowHintDrawable; - /** Drawn (without rotation) on top of the arrow. */ - private Drawable mZoomOutArrowHintDrawable; - - /** Zoom ring is just chillin' */ - private static final int MODE_IDLE = 0; - /** - * User has his finger down somewhere on the ring (besides the thumb) and we - * are waiting for him to move the slop amount before considering him in the - * drag thumb state. - */ - private static final int MODE_WAITING_FOR_DRAG_THUMB_AFTER_JUMP = 5; - /** User is dragging the thumb. */ - private static final int MODE_DRAG_THUMB = 1; - /** - * User has his finger down, but we are waiting for him to pass the touch - * slop before going into the #MODE_MOVE_ZOOM_RING. This is a good time to - * show the movable hint. - */ - private static final int MODE_WAITING_FOR_MOVE_ZOOM_RING = 4; - /** User is moving the zoom ring. */ - private static final int MODE_MOVE_ZOOM_RING = 2; - /** User is dragging the thumb via tap-drag. */ - private static final int MODE_TAP_DRAG = 3; - /** Ignore the touch interaction until the user touches the thumb again. */ - private static final int MODE_IGNORE_UNTIL_TOUCHES_THUMB = 6; - /** The current mode of interaction. */ - private int mMode; - /** Records the last mode the user was in. */ - private int mPreviousMode; - - /** The previous time of the up-touch on the center. */ - private long mPreviousCenterUpTime; - /** The previous X of down-touch. */ - private int mPreviousDownX; - /** The previous Y of down-touch. */ - private int mPreviousDownY; - - /** The angle where the user first grabbed the thumb. */ - private int mInitialGrabThumbAngle; - - /** The callback. */ - private OnZoomRingCallback mCallback; - /** The tick angle that we previously called back with. */ - private int mPreviousCallbackTickAngle; - /** The delta angle between ticks. A tick is a callback point. */ - private int mTickDelta = Integer.MAX_VALUE; - /** If the user drags to within __% of a tick, snap to that tick. */ - private int mFuzzyTickDelta = Integer.MAX_VALUE; - - /** The angle where the thumb is officially starting to be dragged. */ - private int mThumbDragStartAngle; - - /** The drawable for the zoom trail. */ - private Drawable mTrail; - /** The accumulated angle for the trail. */ - private double mAcculumalatedTrailAngle; - - /** The animation-step tracker for scrolling the thumb to a particular position. */ - private Scroller mThumbScroller; - - /** Whether to ever vibrate when passing a tick. */ - private boolean mVibration = true; - - /** The drawable used to hint that this can pan its owner. */ - private Drawable mPanningArrowsDrawable; - - private static final int MSG_THUMB_SCROLLER_STEP = 1; - private static final int MSG_THUMB_ARROWS_FADE_STEP = 2; - private Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_THUMB_SCROLLER_STEP: - onThumbScrollerStep(); - break; - - case MSG_THUMB_ARROWS_FADE_STEP: - onThumbArrowsFadeStep(); - break; - } - } - }; - - public ZoomRing(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - ViewConfiguration viewConfiguration = ViewConfiguration.get(context); - mTouchSlop = viewConfiguration.getScaledTouchSlop(); - - TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ZoomRing, defStyle, 0); - mThumbDistance = (int) a.getDimension(R.styleable.ZoomRing_thumbDistance, 0); - setTrackRadii( - (int) a.getDimension(R.styleable.ZoomRing_trackInnerRadius, 0), - (int) a.getDimension(R.styleable.ZoomRing_trackOuterRadius, Integer.MAX_VALUE)); - mThumbDrawable = a.getDrawable(R.styleable.ZoomRing_thumbDrawable); - mZoomInArrowDrawable = a.getDrawable(R.styleable.ZoomRing_zoomInArrowDrawable); - mZoomOutArrowDrawable = a.getDrawable(R.styleable.ZoomRing_zoomOutArrowDrawable); - mZoomInArrowHintDrawable = a.getDrawable(R.styleable.ZoomRing_zoomInArrowHintDrawable); - mZoomOutArrowHintDrawable = a.getDrawable(R.styleable.ZoomRing_zoomOutArrowHintDrawable); - mZoomArrowHintDistance = - (int) a.getDimension(R.styleable.ZoomRing_zoomArrowHintDistance, 0); - mZoomArrowHintOffsetAngle = - (int) (a.getInteger(R.styleable.ZoomRing_zoomArrowHintOffsetAngle, 0) - * TWO_PI_INT_MULTIPLIED / 360); - mPanningArrowsDrawable = a.getDrawable(R.styleable.ZoomRing_panningArrowsDrawable); - a.recycle(); - - Resources res = context.getResources(); - if (DRAW_TRAIL) { - // TODO get drawables from style instead - mTrail = res.getDrawable(R.drawable.zoom_ring_trail).mutate(); - } - - mThumbHalfHeight = mThumbDrawable.getIntrinsicHeight() / 2; - mThumbHalfWidth = mThumbDrawable.getIntrinsicWidth() / 2; - - setTickDelta(PI_INT_MULTIPLIED / 6); - } - - public ZoomRing(Context context, AttributeSet attrs) { - this(context, attrs, com.android.internal.R.attr.zoomRingStyle); - } - - public ZoomRing(Context context) { - this(context, null); - } - - public void setTrackDrawable(Drawable drawable) { - setBackgroundDrawable(drawable); - } - - public void setCallback(OnZoomRingCallback callback) { - mCallback = callback; - } - - /** - * Sets the distance between ticks. This will be used as a callback threshold. - * - * @param angle The angle between ticks. - */ - public void setTickDelta(int angle) { - mTickDelta = angle; - mFuzzyTickDelta = (int) (angle * 0.65f); - } - - public void setVibration(boolean vibration) { - mVibration = vibration; - } - - public void setThumbVisible(boolean thumbVisible) { - if (mThumbVisible != thumbVisible) { - mThumbVisible = thumbVisible; - invalidate(); - } - } - - public Drawable getPanningArrowsDrawable() { - return mPanningArrowsDrawable; - } - - public void setTrackRadii(int innerRadius, int outerRadius) { - mTrackInnerRadius = innerRadius; - mTrackOuterRadius = outerRadius; - - mTrackInnerRadiusSquared = innerRadius * innerRadius; - if (mTrackInnerRadiusSquared < innerRadius) { - // Prevent overflow - mTrackInnerRadiusSquared = Integer.MAX_VALUE; - } - - mTrackOuterRadiusSquared = outerRadius * outerRadius; - if (mTrackOuterRadiusSquared < outerRadius) { - // Prevent overflow - mTrackOuterRadiusSquared = Integer.MAX_VALUE; - } - } - - public int getTrackInnerRadius() { - return mTrackInnerRadius; - } - - public int getTrackOuterRadius() { - return mTrackOuterRadius; - } - - public void setThumbClockwiseBound(int angle) { - if (angle < 0) { - mThumbCwBound = Integer.MIN_VALUE; - } else { - mThumbCwBound = getClosestTickAngle(angle); - } - updateEnforceMaxAbsJump(); - } - - public void setThumbCounterclockwiseBound(int angle) { - if (angle < 0) { - mThumbCcwBound = Integer.MIN_VALUE; - } else { - mThumbCcwBound = getClosestTickAngle(angle); - } - updateEnforceMaxAbsJump(); - } - - private void updateEnforceMaxAbsJump() { - // If there are bounds in both direction, there is no reason to restrict - // the amount that a user can absolute jump to - mEnforceMaxAbsJump = - mThumbCcwBound == Integer.MIN_VALUE || mThumbCwBound == Integer.MIN_VALUE; - } - - public int getThumbAngle() { - return mThumbAngle; - } - - public void setThumbAngle(int angle) { - angle = getValidAngle(angle); - mPreviousCallbackTickAngle = getClosestTickAngle(angle); - setThumbAngleAuto(angle, false, false); - } - - /** - * Sets the thumb angle. If already animating, will continue the animation, - * otherwise it will do a direct jump. - * - * @param angle - * @param useDirection Whether to use the ccw parameter - * @param ccw Whether going counterclockwise (only used if useDirection is true) - */ - private void setThumbAngleAuto(int angle, boolean useDirection, boolean ccw) { - if (mThumbScroller == null - || mThumbScroller.isFinished() - || Math.abs(getDelta(angle, getThumbScrollerAngle())) < THUMB_GRAB_SLOP) { - setThumbAngleInt(angle); - } else { - if (useDirection) { - setThumbAngleAnimated(angle, 0, ccw); - } else { - setThumbAngleAnimated(angle, 0); - } - } - } - - private void setThumbAngleInt(int angle) { - mThumbAngle = angle; - int unoffsetAngle = angle + mZeroAngle; - int thumbCenterX = (int) (Math.cos(1f * unoffsetAngle / RADIAN_INT_MULTIPLIER) * - mThumbDistance) + mCenterX; - int thumbCenterY = (int) (Math.sin(1f * unoffsetAngle / RADIAN_INT_MULTIPLIER) * - mThumbDistance) * -1 + mCenterY; - - mThumbDrawable.setBounds(thumbCenterX - mThumbHalfWidth, - thumbCenterY - mThumbHalfHeight, - thumbCenterX + mThumbHalfWidth, - thumbCenterY + mThumbHalfHeight); - - if (mThumbArrowsToDraw > 0) { - setThumbArrowsAngle(angle); - } - - if (DRAW_TRAIL) { - double degrees; - degrees = Math.min(359.0, Math.abs(mAcculumalatedTrailAngle)); - int level = (int) (10000.0 * degrees / 360.0); - - mTrail.setLevel((int) (10000.0 * - (-Math.toDegrees(angle / (double) RADIAN_INT_MULTIPLIER) - - degrees + 90) / 360.0)); - ((RotateDrawable) mTrail).getDrawable().setLevel(level); - } - - invalidate(); - } - - /** - * - * @param angle - * @param duration The animation duration, or 0 for the default duration. - */ - public void setThumbAngleAnimated(int angle, int duration) { - // The angle when going from the current angle to the new angle - int deltaAngle = getDelta(mThumbAngle, angle); - setThumbAngleAnimated(angle, duration, deltaAngle > 0); - } - - public void setThumbAngleAnimated(int angle, int duration, boolean counterClockwise) { - if (mThumbScroller == null) { - mThumbScroller = new Scroller(mContext); - } - - int startAngle = mThumbAngle; - int endAngle = getValidAngle(angle); - int deltaAngle = getDelta(startAngle, endAngle, counterClockwise); - if (startAngle + deltaAngle < 0) { - // Keep our angles positive - startAngle += TWO_PI_INT_MULTIPLIED; - } - - if (!mThumbScroller.isFinished()) { - duration = mThumbScroller.getDuration() - mThumbScroller.timePassed(); - } else if (duration == 0) { - duration = getAnimationDuration(deltaAngle); - } - mThumbScroller.startScroll(startAngle, 0, deltaAngle, 0, duration); - onThumbScrollerStep(); - } - - private int getAnimationDuration(int deltaAngle) { - if (deltaAngle < 0) deltaAngle *= -1; - return 300 + deltaAngle * 300 / RADIAN_INT_MULTIPLIER; - } - - private void onThumbScrollerStep() { - if (!mThumbScroller.computeScrollOffset()) return; - setThumbAngleInt(getThumbScrollerAngle()); - mHandler.sendEmptyMessage(MSG_THUMB_SCROLLER_STEP); - } - - private int getThumbScrollerAngle() { - return mThumbScroller.getCurrX() % TWO_PI_INT_MULTIPLIED; - } - - public void resetThumbAngle() { - mPreviousCallbackTickAngle = 0; - setThumbAngleInt(0); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - setMeasuredDimension(resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec), - resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec)); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, - int bottom) { - super.onLayout(changed, left, top, right, bottom); - - // Cache the center point - mCenterX = (right - left) / 2; - mCenterY = (bottom - top) / 2; - - // Done here since we now have center, which is needed to calculate some - // aux info for thumb angle - if (mThumbAngle == Integer.MIN_VALUE) { - resetThumbAngle(); - } - - if (DRAW_TRAIL) { - mTrail.setBounds(0, 0, right - left, bottom - top); - } - - // These drawables are the same size as the track - mZoomInArrowDrawable.setBounds(0, 0, right - left, bottom - top); - mZoomOutArrowDrawable.setBounds(0, 0, right - left, bottom - top); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - return handleTouch(event.getAction(), event.getEventTime(), - (int) event.getX(), (int) event.getY(), (int) event.getRawX(), - (int) event.getRawY()); - } - - private void resetToIdle() { - setMode(MODE_IDLE); - mPreviousWidgetDragX = mPreviousWidgetDragY = Integer.MIN_VALUE; - mAcculumalatedTrailAngle = 0.0; - } - - public void setTapDragMode(boolean tapDragMode, int x, int y) { - resetToIdle(); - if (tapDragMode) { - setMode(MODE_TAP_DRAG); - mCallback.onUserInteractionStarted(); - onThumbDragStarted(getAngle(x - mCenterX, y - mCenterY)); - } else { - onTouchUp(SystemClock.elapsedRealtime(), true); - } - } - - public boolean handleTouch(int action, long time, int x, int y, int rawX, int rawY) { - // local{X,Y} will be where the center of the widget is (0,0) - int localX = x - mCenterX; - int localY = y - mCenterY; - - /* - * If we are not drawing the thumb, there is no way for the user to be - * touching the thumb. Also, if this is the case, assume they are not - * touching the ring (so the user cannot absolute set the thumb, and - * there will be a larger touch region for going into the move-ring - * mode). - */ - boolean isTouchingThumb = mThumbVisible; - boolean isTouchingRing = mThumbVisible; - - int touchAngle = getAngle(localX, localY); - - int radiusSquared = localX * localX + localY * localY; - if (radiusSquared < mTrackInnerRadiusSquared || - radiusSquared > mTrackOuterRadiusSquared) { - // Out-of-bounds - isTouchingThumb = false; - isTouchingRing = false; - } - - if (isTouchingThumb) { - int deltaThumbAndTouch = getDelta(mThumbAngle, touchAngle); - int absoluteDeltaThumbAndTouch = deltaThumbAndTouch >= 0 ? - deltaThumbAndTouch : -deltaThumbAndTouch; - if (absoluteDeltaThumbAndTouch > THUMB_GRAB_SLOP) { - // Didn't grab close enough to the thumb - isTouchingThumb = false; - } - } - - switch (action) { - case MotionEvent.ACTION_DOWN: - if (!isTouchingRing && - (time - mPreviousCenterUpTime <= DOUBLE_TAP_DISMISS_TIMEOUT)) { - // Make sure the double-tap is in the center of the widget (and not on the ring) - mCallback.onZoomRingDismissed(); - onTouchUp(time, isTouchingRing); - - // Dismissing, so halt here - return true; - } - - resetToIdle(); - mCallback.onUserInteractionStarted(); - mPreviousDownX = x; - mPreviousDownY = y; - // Fall through to code below switch (since the down is used for - // jumping to the touched tick) - break; - - case MotionEvent.ACTION_MOVE: - // Fall through to code below switch - break; - - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - onTouchUp(time, isTouchingRing); - return true; - - default: - return false; - } - - if (mMode == MODE_IDLE) { - if (isTouchingThumb) { - // They grabbed the thumb - setMode(MODE_DRAG_THUMB); - onThumbDragStarted(touchAngle); - - } else if (isTouchingRing) { - // They tapped somewhere else on the ring - int tickAngle = getClosestTickAngle(touchAngle); - int deltaThumbAndTick = getDelta(mThumbAngle, tickAngle); - int boundAngle = getBoundIfExceeds(mThumbAngle, deltaThumbAndTick); - - if (mEnforceMaxAbsJump) { - // Enforcing the max jump - if (deltaThumbAndTick > MAX_ABS_JUMP_DELTA_ANGLE || - deltaThumbAndTick < -MAX_ABS_JUMP_DELTA_ANGLE) { - // Trying to jump too far, ignore this touch interaction - setMode(MODE_IGNORE_UNTIL_TOUCHES_THUMB); - return true; - } - - if (boundAngle != Integer.MIN_VALUE) { - // Cap the user's jump to the bound - tickAngle = boundAngle; - } - } else { - // Not enforcing the max jump, but we have to make sure - // we're getting to the tapped angle by going through the - // in-bounds region - if (boundAngle != Integer.MIN_VALUE) { - // Going this direction hits a bound, let's go the opposite direction - boolean oldDirectionIsCcw = deltaThumbAndTick > 0; - deltaThumbAndTick = getDelta(mThumbAngle, tickAngle, !oldDirectionIsCcw); - boundAngle = getBoundIfExceeds(mThumbAngle, deltaThumbAndTick); - if (boundAngle != Integer.MIN_VALUE) { - // Cannot get to the tapped location because it is out-of-bounds - setMode(MODE_IGNORE_UNTIL_TOUCHES_THUMB); - return true; - } - } - } - - setMode(MODE_WAITING_FOR_DRAG_THUMB_AFTER_JUMP); - mInitialGrabThumbAngle = touchAngle; - boolean ccw = deltaThumbAndTick > 0; - setThumbAngleAnimated(tickAngle, 0, ccw); - - /* - * Our thumb scrolling animation takes us from mThumbAngle to - * tickAngle, so manifest that as the user dragging the thumb - * there. - */ - onThumbDragStarted(mThumbAngle); - // We know which direction we want to go - onThumbDragged(tickAngle, true, ccw); - - } else { - // They tapped somewhere else on the widget - setMode(MODE_WAITING_FOR_MOVE_ZOOM_RING); - mCallback.onZoomRingSetMovableHintVisible(true); - } - - } else if (mMode == MODE_WAITING_FOR_DRAG_THUMB_AFTER_JUMP) { - int deltaDownAngle = getDelta(mInitialGrabThumbAngle, touchAngle); - if ((deltaDownAngle < -THUMB_DRAG_SLOP || deltaDownAngle > THUMB_DRAG_SLOP) && - isDeltaInBounds(mInitialGrabThumbAngle, deltaDownAngle)) { - setMode(MODE_DRAG_THUMB); - - // No need to call onThumbDragStarted, since that was done when they tapped-to-jump - } - - } else if (mMode == MODE_WAITING_FOR_MOVE_ZOOM_RING) { - if (Math.abs(x - mPreviousDownX) > mTouchSlop || - Math.abs(y - mPreviousDownY) > mTouchSlop) { - /* Make sure the user has moved the slop amount before going into that mode. */ - setMode(MODE_MOVE_ZOOM_RING); - mCallback.onZoomRingMovingStarted(); - // Move the zoom ring so it is under the finger where the user first touched - mCallback.onZoomRingMoved(x - mPreviousDownX, y - mPreviousDownY, rawX, rawY); - } - } else if (mMode == MODE_IGNORE_UNTIL_TOUCHES_THUMB) { - if (isTouchingThumb) { - // The user is back on the thumb, let's go back to the previous mode - setMode(mPreviousMode); - } - } - - // Purposefully not an "else if" - if (mMode == MODE_DRAG_THUMB || mMode == MODE_TAP_DRAG) { - if (isTouchingRing) { - onThumbDragged(touchAngle, false, false); - } - } else if (mMode == MODE_MOVE_ZOOM_RING) { - onZoomRingMoved(rawX, rawY); - } - - return true; - } - - private void onTouchUp(long time, boolean isTouchingRing) { - int mode = mMode; - if (mode == MODE_IGNORE_UNTIL_TOUCHES_THUMB) { - // For cleaning up, pretend like the user was still in the previous mode - mode = mPreviousMode; - } - - if (mode == MODE_MOVE_ZOOM_RING || mode == MODE_WAITING_FOR_MOVE_ZOOM_RING) { - mCallback.onZoomRingSetMovableHintVisible(false); - if (mode == MODE_MOVE_ZOOM_RING) { - mCallback.onZoomRingMovingStopped(); - } - } else if (mode == MODE_DRAG_THUMB || mode == MODE_TAP_DRAG || - mode == MODE_WAITING_FOR_DRAG_THUMB_AFTER_JUMP) { - onThumbDragStopped(); - - if (mode == MODE_DRAG_THUMB || mode == MODE_TAP_DRAG) { - // Animate back to a tick - setThumbAngleAnimated(mPreviousCallbackTickAngle, 0); - } - } - mCallback.onUserInteractionStopped(); - - if (!isTouchingRing) { - mPreviousCenterUpTime = time; - } - } - - private void setMode(int mode) { - if (mode != mMode) { - mPreviousMode = mMode; - mMode = mode; - } - } - - private boolean isDeltaInBounds(int startAngle, int deltaAngle) { - return getBoundIfExceeds(startAngle, deltaAngle) == Integer.MIN_VALUE; - } - - private int getBoundIfExceeds(int startAngle, int deltaAngle) { - if (deltaAngle > 0) { - // Counterclockwise movement - if (mThumbCcwBound != Integer.MIN_VALUE && - getDelta(startAngle, mThumbCcwBound, true) < deltaAngle) { - return mThumbCcwBound; - } - } else if (deltaAngle < 0) { - // Clockwise movement, both of these will be negative - int deltaThumbAndBound = getDelta(startAngle, mThumbCwBound, false); - if (mThumbCwBound != Integer.MIN_VALUE && - deltaThumbAndBound > deltaAngle) { - // Tapped outside of the bound in that direction - return mThumbCwBound; - } - } - - return Integer.MIN_VALUE; - } - - private int getDelta(int startAngle, int endAngle, boolean useDirection, boolean ccw) { - return useDirection ? getDelta(startAngle, endAngle, ccw) : getDelta(startAngle, endAngle); - } - - /** - * Gets the smallest delta between two angles, and infers the direction - * based on the shortest path between the two angles. If going from - * startAngle to endAngle is counterclockwise, the result will be positive. - * If it is clockwise, the result will be negative. - * - * @param startAngle The start angle. - * @param endAngle The end angle. - * @return The difference in angles. - */ - private int getDelta(int startAngle, int endAngle) { - int largerAngle, smallerAngle; - if (endAngle > startAngle) { - largerAngle = endAngle; - smallerAngle = startAngle; - } else { - largerAngle = startAngle; - smallerAngle = endAngle; - } - - int delta = largerAngle - smallerAngle; - if (delta <= PI_INT_MULTIPLIED) { - // If going clockwise, negate the delta - return startAngle == largerAngle ? -delta : delta; - } else { - // The other direction is the delta we want (it includes the - // discontinuous 0-2PI angle) - delta = TWO_PI_INT_MULTIPLIED - delta; - // If going clockwise, negate the delta - return startAngle == smallerAngle ? -delta : delta; - } - } - - /** - * Gets the delta between two angles in the direction specified. - * - * @param startAngle The start angle. - * @param endAngle The end angle. - * @param counterClockwise The direction to take when computing the delta. - * @return The difference in angles in the given direction. - */ - private int getDelta(int startAngle, int endAngle, boolean counterClockwise) { - int delta = endAngle - startAngle; - - if (!counterClockwise && delta > 0) { - // Crossed the discontinuous 0/2PI angle, take the leftover slice of - // the pie and negate it - return -TWO_PI_INT_MULTIPLIED + delta; - } else if (counterClockwise && delta < 0) { - // Crossed the discontinuous 0/2PI angle, take the leftover slice of - // the pie (and ensure it is positive) - return TWO_PI_INT_MULTIPLIED + delta; - } else { - return delta; - } - } - - private void onThumbDragStarted(int startAngle) { - setThumbArrowsVisible(false); - mThumbDragStartAngle = startAngle; - mCallback.onZoomRingThumbDraggingStarted(); - } - - private void onThumbDragged(int touchAngle, boolean useDirection, boolean ccw) { - boolean animateThumbToNewAngle = false; - - int totalDeltaAngle; - totalDeltaAngle = getDelta(mPreviousCallbackTickAngle, touchAngle, useDirection, ccw); - if (totalDeltaAngle >= mFuzzyTickDelta - || totalDeltaAngle <= -mFuzzyTickDelta) { - - if (!useDirection) { - // Set ccw to match the direction found by getDelta - ccw = totalDeltaAngle > 0; - } - - /* - * When the user slides the thumb through the tick that corresponds - * to a zoom bound, we don't want to abruptly stop there. Instead, - * let the user slide it to the next tick, and then animate it back - * to the original zoom bound tick. Because of this, we make sure - * the delta from the bound is more than halfway to the next tick. - * We make sure the bound is between the touch and the previous - * callback to ensure we just passed the bound. - */ - int oldTouchAngle = touchAngle; - if (ccw && mThumbCcwBound != Integer.MIN_VALUE) { - int deltaCcwBoundAndTouch = - getDelta(mThumbCcwBound, touchAngle, useDirection, true); - if (deltaCcwBoundAndTouch >= mTickDelta / 2) { - // The touch has past a bound - int deltaPreviousCbAndTouch = getDelta(mPreviousCallbackTickAngle, - touchAngle, useDirection, true); - if (deltaPreviousCbAndTouch >= deltaCcwBoundAndTouch) { - // The bound is between the previous callback angle and the touch - touchAngle = mThumbCcwBound; - // We're moving the touch BACK to the bound, so opposite direction - ccw = false; - } - } - } else if (!ccw && mThumbCwBound != Integer.MIN_VALUE) { - // See block above for general comments - int deltaCwBoundAndTouch = - getDelta(mThumbCwBound, touchAngle, useDirection, false); - if (deltaCwBoundAndTouch <= -mTickDelta / 2) { - int deltaPreviousCbAndTouch = getDelta(mPreviousCallbackTickAngle, - touchAngle, useDirection, false); - /* - * Both of these will be negative since we got delta in - * clockwise direction, and we want the magnitude of - * deltaPreviousCbAndTouch to be greater than the magnitude - * of deltaCwBoundAndTouch - */ - if (deltaPreviousCbAndTouch <= deltaCwBoundAndTouch) { - touchAngle = mThumbCwBound; - ccw = true; - } - } - } - if (touchAngle != oldTouchAngle) { - // We bounded the touch angle - totalDeltaAngle = getDelta(mPreviousCallbackTickAngle, touchAngle, useDirection, ccw); - animateThumbToNewAngle = true; - setMode(MODE_IGNORE_UNTIL_TOUCHES_THUMB); - } - - - // Prevent it from jumping too far - if (mEnforceMaxAbsJump) { - if (totalDeltaAngle <= -MAX_ABS_JUMP_DELTA_ANGLE) { - totalDeltaAngle = -MAX_ABS_JUMP_DELTA_ANGLE; - animateThumbToNewAngle = true; - } else if (totalDeltaAngle >= MAX_ABS_JUMP_DELTA_ANGLE) { - totalDeltaAngle = MAX_ABS_JUMP_DELTA_ANGLE; - animateThumbToNewAngle = true; - } - } - - /* - * We need to cover the edge case of a user grabbing the thumb, - * going into the center of the widget, and then coming out from the - * center to an angle that's slightly below the angle he's trying to - * hit. If we do int division, we'll end up with one level lower - * than the one he was going for. - */ - int deltaLevels = Math.round((float) totalDeltaAngle / mTickDelta); - if (deltaLevels != 0) { - boolean canStillZoom = mCallback.onZoomRingThumbDragged( - deltaLevels, mThumbDragStartAngle, touchAngle); - - if (mVibration) { - // TODO: we're trying the haptics to see how it goes with - // users, so we're ignoring the settings (for now) - performHapticFeedback(HapticFeedbackConstants.ZOOM_RING_TICK, - HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING | - HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); - } - - // Set the callback angle to the actual angle based on how many delta levels we gave - mPreviousCallbackTickAngle = getValidAngle( - mPreviousCallbackTickAngle + (deltaLevels * mTickDelta)); - } - } - - if (DRAW_TRAIL) { - int deltaAngle = getDelta(mThumbAngle, touchAngle, useDirection, ccw); - mAcculumalatedTrailAngle += Math.toDegrees(deltaAngle / (double) RADIAN_INT_MULTIPLIER); - } - - if (animateThumbToNewAngle) { - if (useDirection) { - setThumbAngleAnimated(touchAngle, 0, ccw); - } else { - setThumbAngleAnimated(touchAngle, 0); - } - } else { - setThumbAngleAuto(touchAngle, useDirection, ccw); - } - } -// private void onThumbDragged(int touchAngle, boolean useDirection, boolean ccw) { -// int deltaPrevCbAndTouch = getDelta(mPreviousCallbackAngle, touchAngle, useDirection, ccw); -// -// if (!useDirection) { -// // Set ccw to match the direction found by getDelta -// ccw = deltaPrevCbAndTouch > 0; -// useDirection = true; -// } -// -// boolean animateThumbToNewAngle = false; -// boolean animationCcw = ccw; -// -// if (deltaPrevCbAndTouch >= mFuzzyCallbackThreshold -// || deltaPrevCbAndTouch <= -mFuzzyCallbackThreshold) { -// -// /* -// * When the user slides the thumb through the tick that corresponds -// * to a zoom bound, we don't want to abruptly stop there. Instead, -// * let the user slide it to the next tick, and then animate it back -// * to the original zoom bound tick. Because of this, we make sure -// * the delta from the bound is more than halfway to the next tick. -// * We make sure the bound is between the touch and the previous -// * callback to ensure we JUST passed the bound. -// */ -// int oldTouchAngle = touchAngle; -// if (ccw && mThumbCcwBound != Integer.MIN_VALUE) { -// int deltaCcwBoundAndTouch = -// getDelta(mThumbCcwBound, touchAngle, true, ccw); -// if (deltaCcwBoundAndTouch >= mCallbackThreshold / 2) { -// // The touch has past far enough from the bound -// int deltaPreviousCbAndTouch = getDelta(mPreviousCallbackAngle, -// touchAngle, true, ccw); -// if (deltaPreviousCbAndTouch >= deltaCcwBoundAndTouch) { -// // The bound is between the previous callback angle and the touch -// // Cap to the bound -// touchAngle = mThumbCcwBound; -// /* -// * We're moving the touch BACK to the bound, so animate -// * back in the opposite direction that passed the bound. -// */ -// animationCcw = false; -// } -// } -// } else if (!ccw && mThumbCwBound != Integer.MIN_VALUE) { -// // See block above for general comments -// int deltaCwBoundAndTouch = -// getDelta(mThumbCwBound, touchAngle, true, ccw); -// if (deltaCwBoundAndTouch <= -mCallbackThreshold / 2) { -// int deltaPreviousCbAndTouch = getDelta(mPreviousCallbackAngle, -// touchAngle, true, ccw); -// /* -// * Both of these will be negative since we got delta in -// * clockwise direction, and we want the magnitude of -// * deltaPreviousCbAndTouch to be greater than the magnitude -// * of deltaCwBoundAndTouch -// */ -// if (deltaPreviousCbAndTouch <= deltaCwBoundAndTouch) { -// touchAngle = mThumbCwBound; -// animationCcw = true; -// } -// } -// } -// if (touchAngle != oldTouchAngle) { -// // We bounded the touch angle -// deltaPrevCbAndTouch = getDelta(mPreviousCallbackAngle, touchAngle, true, ccw); -// // Animate back to the bound -// animateThumbToNewAngle = true; -// // Disallow movement now -// setMode(MODE_IGNORE_UNTIL_UP); -// } -// -// -// /* -// * Prevent it from jumping too far (this could happen if the user -// * goes through the center) -// */ -// -// if (mEnforceMaxAbsJump) { -// if (deltaPrevCbAndTouch <= -MAX_ABS_JUMP_DELTA_ANGLE) { -// deltaPrevCbAndTouch = -MAX_ABS_JUMP_DELTA_ANGLE; -// animateThumbToNewAngle = true; -// } else if (deltaPrevCbAndTouch >= MAX_ABS_JUMP_DELTA_ANGLE) { -// deltaPrevCbAndTouch = MAX_ABS_JUMP_DELTA_ANGLE; -// animateThumbToNewAngle = true; -// } -// } -// -// /* -// * We need to cover the edge case of a user grabbing the thumb, -// * going into the center of the widget, and then coming out from the -// * center to an angle that's slightly below the angle he's trying to -// * hit. If we do int division, we'll end up with one level lower -// * than the one he was going for. -// */ -// int deltaLevels = Math.round((float) deltaPrevCbAndTouch / mCallbackThreshold); -// if (deltaLevels != 0) { -// boolean canStillZoom = mCallback.onZoomRingThumbDragged( -// deltaLevels, mThumbDragStartAngle, touchAngle); -// -// if (mVibration) { -// // TODO: we're trying the haptics to see how it goes with -// // users, so we're ignoring the settings (for now) -// performHapticFeedback(HapticFeedbackConstants.ZOOM_RING_TICK, -// HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING | -// HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); -// -// } -// // Set the callback angle to the actual angle based on how many delta levels we gave -// mPreviousCallbackAngle = getValidAngle( -// mPreviousCallbackAngle + (deltaLevels * mCallbackThreshold)); -// } -// } -// -// if (DRAW_TRAIL) { -// int deltaAngle = getDelta(mThumbAngle, touchAngle, true, ccw); -// mAcculumalatedTrailAngle += Math.toDegrees(deltaAngle / (double) RADIAN_INT_MULTIPLIER); -// } -// -// if (animateThumbToNewAngle) { -// setThumbAngleAnimated(touchAngle, 0, animationCcw); -// } else { -// /* -// * Use regular ccw here because animationCcw will never have been -// * changed if animateThumbToNewAngle is false -// */ -// setThumbAngleAuto(touchAngle, true, ccw); -// } -// } - - private int getValidAngle(int invalidAngle) { - if (invalidAngle < 0) { - return (invalidAngle % TWO_PI_INT_MULTIPLIED) + TWO_PI_INT_MULTIPLIED; - } else if (invalidAngle >= TWO_PI_INT_MULTIPLIED) { - return invalidAngle % TWO_PI_INT_MULTIPLIED; - } else { - return invalidAngle; - } - } - - private int getClosestTickAngle(int angle) { - int smallerAngleDistance = angle % mTickDelta; - int smallerAngle = angle - smallerAngleDistance; - if (smallerAngleDistance < mTickDelta / 2) { - // Closer to the smaller angle - return smallerAngle; - } else { - // Closer to the bigger angle (premodding) - return (smallerAngle + mTickDelta) % TWO_PI_INT_MULTIPLIED; - } - } - - private void onThumbDragStopped() { - mCallback.onZoomRingThumbDraggingStopped(); - } - - private void onZoomRingMoved(int rawX, int rawY) { - if (mPreviousWidgetDragX != Integer.MIN_VALUE) { - int deltaX = rawX - mPreviousWidgetDragX; - int deltaY = rawY - mPreviousWidgetDragY; - - mCallback.onZoomRingMoved(deltaX, deltaY, rawX, rawY); - } - - mPreviousWidgetDragX = rawX; - mPreviousWidgetDragY = rawY; - } - - @Override - public void onWindowFocusChanged(boolean hasWindowFocus) { - super.onWindowFocusChanged(hasWindowFocus); - - if (!hasWindowFocus) { - mCallback.onZoomRingDismissed(); - } - } - - private int getAngle(int localX, int localY) { - int radians = (int) (Math.atan2(localY, localX) * RADIAN_INT_MULTIPLIER); - - // Convert from [-pi,pi] to {0,2pi] - if (radians < 0) { - radians = -radians; - } else if (radians > 0) { - radians = 2 * PI_INT_MULTIPLIED - radians; - } else { - radians = 0; - } - - radians = radians - mZeroAngle; - return radians >= 0 ? radians : radians + 2 * PI_INT_MULTIPLIED; - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - - if (mThumbVisible) { - if (DRAW_TRAIL) { - mTrail.draw(canvas); - } - if ((mThumbArrowsToDraw & THUMB_ARROW_PLUS) != 0) { - mZoomInArrowDrawable.draw(canvas); - mZoomInArrowHintDrawable.draw(canvas); - } - if ((mThumbArrowsToDraw & THUMB_ARROW_MINUS) != 0) { - mZoomOutArrowDrawable.draw(canvas); - mZoomOutArrowHintDrawable.draw(canvas); - } - mThumbDrawable.draw(canvas); - } - } - - private void setThumbArrowsAngle(int angle) { - int level = -angle * 10000 / ZoomRing.TWO_PI_INT_MULTIPLIED; - mZoomInArrowDrawable.setLevel(level); - mZoomOutArrowDrawable.setLevel(level); - - // Assume it is a square - int halfSideLength = mZoomInArrowHintDrawable.getIntrinsicHeight() / 2; - int unoffsetAngle = angle + mZeroAngle; - - int plusCenterX = (int) (Math.cos(1f * (unoffsetAngle - mZoomArrowHintOffsetAngle) - / RADIAN_INT_MULTIPLIER) * mZoomArrowHintDistance) + mCenterX; - int plusCenterY = (int) (Math.sin(1f * (unoffsetAngle - mZoomArrowHintOffsetAngle) - / RADIAN_INT_MULTIPLIER) * mZoomArrowHintDistance) * -1 + mCenterY; - mZoomInArrowHintDrawable.setBounds(plusCenterX - halfSideLength, - plusCenterY - halfSideLength, - plusCenterX + halfSideLength, - plusCenterY + halfSideLength); - - int minusCenterX = (int) (Math.cos(1f * (unoffsetAngle + mZoomArrowHintOffsetAngle) - / RADIAN_INT_MULTIPLIER) * mZoomArrowHintDistance) + mCenterX; - int minusCenterY = (int) (Math.sin(1f * (unoffsetAngle + mZoomArrowHintOffsetAngle) - / RADIAN_INT_MULTIPLIER) * mZoomArrowHintDistance) * -1 + mCenterY; - mZoomOutArrowHintDrawable.setBounds(minusCenterX - halfSideLength, - minusCenterY - halfSideLength, - minusCenterX + halfSideLength, - minusCenterY + halfSideLength); - } - - void setThumbArrowsVisible(boolean visible) { - if (visible) { - mThumbArrowsAlpha = 255; - int callbackAngle = mPreviousCallbackTickAngle; - if (callbackAngle < mThumbCwBound - RADIAN_INT_ERROR || - callbackAngle > mThumbCwBound + RADIAN_INT_ERROR) { - mZoomInArrowDrawable.setAlpha(255); - mZoomInArrowHintDrawable.setAlpha(255); - mThumbArrowsToDraw |= THUMB_ARROW_PLUS; - } else { - mThumbArrowsToDraw &= ~THUMB_ARROW_PLUS; - } - if (callbackAngle < mThumbCcwBound - RADIAN_INT_ERROR || - callbackAngle > mThumbCcwBound + RADIAN_INT_ERROR) { - mZoomOutArrowDrawable.setAlpha(255); - mZoomOutArrowHintDrawable.setAlpha(255); - mThumbArrowsToDraw |= THUMB_ARROW_MINUS; - } else { - mThumbArrowsToDraw &= ~THUMB_ARROW_MINUS; - } - invalidate(); - } else if (mThumbArrowsAlpha == 255) { - // Only start fade if we're fully visible (otherwise another fade is happening already) - mThumbArrowsFadeStartTime = SystemClock.elapsedRealtime(); - onThumbArrowsFadeStep(); - } - } - - private void onThumbArrowsFadeStep() { - if (mThumbArrowsAlpha <= 0) { - mThumbArrowsToDraw = 0; - return; - } - - mThumbArrowsAlpha = (int) - (255 - (255 * (SystemClock.elapsedRealtime() - mThumbArrowsFadeStartTime) - / THUMB_ARROWS_FADE_DURATION)); - if (mThumbArrowsAlpha < 0) mThumbArrowsAlpha = 0; - if ((mThumbArrowsToDraw & THUMB_ARROW_PLUS) != 0) { - mZoomInArrowDrawable.setAlpha(mThumbArrowsAlpha); - mZoomInArrowHintDrawable.setAlpha(mThumbArrowsAlpha); - invalidateDrawable(mZoomInArrowHintDrawable); - invalidateDrawable(mZoomInArrowDrawable); - } - if ((mThumbArrowsToDraw & THUMB_ARROW_MINUS) != 0) { - mZoomOutArrowDrawable.setAlpha(mThumbArrowsAlpha); - mZoomOutArrowHintDrawable.setAlpha(mThumbArrowsAlpha); - invalidateDrawable(mZoomOutArrowHintDrawable); - invalidateDrawable(mZoomOutArrowDrawable); - } - - if (!mHandler.hasMessages(MSG_THUMB_ARROWS_FADE_STEP)) { - mHandler.sendEmptyMessage(MSG_THUMB_ARROWS_FADE_STEP); - } - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - - setThumbArrowsAngle(mThumbAngle); - setThumbArrowsVisible(true); - } - - public interface OnZoomRingCallback { - void onZoomRingSetMovableHintVisible(boolean visible); - - void onZoomRingMovingStarted(); - boolean onZoomRingMoved(int deltaX, int deltaY, int rawX, int rawY); - void onZoomRingMovingStopped(); - - void onZoomRingThumbDraggingStarted(); - boolean onZoomRingThumbDragged(int numLevels, int startAngle, int curAngle); - void onZoomRingThumbDraggingStopped(); - - void onZoomRingDismissed(); - - void onUserInteractionStarted(); - void onUserInteractionStopped(); - } - - private static void printAngle(String angleName, int angle) { - Log.d(TAG, angleName + ": " + (long) angle * 180 / PI_INT_MULTIPLIED); - } -} diff --git a/core/java/android/widget/ZoomRingController.java b/core/java/android/widget/ZoomRingController.java deleted file mode 100644 index 3bf3b227dba04..0000000000000 --- a/core/java/android/widget/ZoomRingController.java +++ /dev/null @@ -1,1383 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.widget; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.BroadcastReceiver; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.graphics.PixelFormat; -import android.graphics.Rect; -import android.os.Handler; -import android.os.Message; -import android.os.SystemClock; -import android.provider.Settings; -import android.util.DisplayMetrics; -import android.view.GestureDetector; -import android.view.Gravity; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewConfiguration; -import android.view.Window; -import android.view.WindowManager; -import android.view.WindowManager.LayoutParams; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; -import android.view.animation.DecelerateInterpolator; - -/** - * A controller to simplify the use of the zoom ring widget. - *

- * If you are using this with a custom View, please call - * {@link #setVisible(boolean) setVisible(false)} from the - * {@link View#onDetachedFromWindow}. - * - * @hide - */ -public class ZoomRingController implements ZoomRing.OnZoomRingCallback, - View.OnTouchListener, View.OnKeyListener { - - // Temporary methods for different zoom types - static int getZoomType(Context context) { - return Settings.System.getInt(context.getContentResolver(), "zoom", 1); - } - public static boolean useOldZoom(Context context) { - return getZoomType(context) == 0; - } - private static boolean useThisZoom(Context context) { - return getZoomType(context) == 1; - } - - /** The duration for the animation to re-center the zoom ring. */ - private static final int RECENTERING_DURATION = 500; - - /** The inactivity timeout for the zoom ring. */ - private static final int INACTIVITY_TIMEOUT = - (int) ViewConfiguration.getZoomControlsTimeout(); - - /** - * The delay when the user taps outside to dismiss the zoom ring. This is - * because the user can do a second-tap to recenter the owner view instead - * of dismissing the zoom ring. - */ - private static final int OUTSIDE_TAP_DISMISS_DELAY = - ViewConfiguration.getDoubleTapTimeout() / 2; - - /** - * When the zoom ring is on the edge, this is the delay before we actually - * start panning the owner. - * @see #mInitiatePanGap - */ - private static final int INITIATE_PAN_DELAY = 300; - - /** - * While already panning, if the zoom ring remains this close to an edge, - * the owner will continue to be panned. - */ - private int mPanGap; - - /** To begin a pan, the zoom ring must be this close to an edge. */ - private int mInitiatePanGap; - - /** Initialized from ViewConfiguration. */ - private int mScaledTouchSlop; - - /** - * The setting name that tracks whether we've shown the zoom ring toast. - */ - private static final String SETTING_NAME_SHOWN_TOAST = "shown_zoom_ring_toast"; - - private Context mContext; - private WindowManager mWindowManager; - - /** - * The view that is being zoomed by this zoom ring. - */ - private View mOwnerView; - - /** - * The bounds of the owner view in global coordinates. This is recalculated - * each time the zoom ring is shown. - */ - private Rect mOwnerViewBounds = new Rect(); - - /** - * The container that is added as a window. - */ - private FrameLayout mContainer; - private LayoutParams mContainerLayoutParams; - - /** - * The view (or null) that should receive touch events. This will get set if - * the touch down hits the container. It will be reset on the touch up. - */ - private View mTouchTargetView; - /** - * The {@link #mTouchTargetView}'s location in window, set on touch down. - */ - private int[] mTouchTargetLocationInWindow = new int[2]; - /** - * If the zoom ring is dismissed but the user is still in a touch - * interaction, we set this to true. This will ignore all touch events until - * up/cancel, and then set the owner's touch listener to null. - */ - private boolean mReleaseTouchListenerOnUp; - - - /* - * Tap-drag is an interaction where the user first taps and then (quickly) - * does the clockwise or counter-clockwise drag. In reality, this is: (down, - * up, down, move in circles, up). This differs from the usual events of: - * (down, up, down, up, down, move in circles, up). While the only - * difference is the omission of an (up, down), for power-users this is a - * pretty big improvement as it now only requires them to focus on the - * screen once (for the first tap down) instead of twice (for the first tap - * down and then to grab the thumb). - */ - /** The X where the tap-drag started. */ - private int mTapDragStartX; - /** The Y where the tap-drag started. */ - private int mTapDragStartY; - - /** The controller is idle */ - private static final int TOUCH_MODE_IDLE = 0; - /** - * In the middle of a second-tap interaction, waiting for either an up-touch - * or the user to start dragging to go into tap-drag mode. - */ - private static final int TOUCH_MODE_WAITING_FOR_TAP_DRAG_MOVEMENT = 2; - /** In the middle of a tap-drag. */ - private static final int TOUCH_MODE_FORWARDING_FOR_TAP_DRAG = 3; - private int mTouchMode; - - /** Whether the zoom ring is visible. */ - private boolean mIsZoomRingVisible; - - private ZoomRing mZoomRing; - /** Cached width of the zoom ring. */ - private int mZoomRingWidth; - /** Cached height of the zoom ring. */ - private int mZoomRingHeight; - - /** Invokes panning of owner view if the zoom ring is touching an edge. */ - private Panner mPanner; - /** The time when the zoom ring first touched the edge. */ - private long mTouchingEdgeStartTime; - /** Whether the user has already initiated the panning. */ - private boolean mPanningInitiated; - - /** - * When the finger moves the zoom ring to an edge, this is the horizontal - * accumulator for how much the finger has moved off of its original touch - * point on the zoom ring (OOB = out-of-bounds). If < 0, the finger has - * moved that many px to the left of its original touch point on the ring. - */ - private int mMovingZoomRingOobX; - /** Vertical accumulator, see {@link #mMovingZoomRingOobX} */ - private int mMovingZoomRingOobY; - - /** Arrows that hint that the zoom ring is movable. */ - private ImageView mPanningArrows; - /** The animation shown when the panning arrows are being shown. */ - private Animation mPanningArrowsEnterAnimation; - /** The animation shown when the panning arrows are being hidden. */ - private Animation mPanningArrowsExitAnimation; - - /** - * Temporary rectangle, only use from the UI thread (and ideally don't rely - * on it being unused across many method calls.) - */ - private Rect mTempRect = new Rect(); - - private OnZoomListener mCallback; - - /** - * When the zoom ring is centered on screen, this will be the x value used - * for the container's layout params. - */ - private int mCenteredContainerX = Integer.MIN_VALUE; - - /** - * When the zoom ring is centered on screen, this will be the y value used - * for the container's layout params. - */ - private int mCenteredContainerY = Integer.MIN_VALUE; - - /** - * Scroller used to re-center the zoom ring if the user had dragged it to a - * corner and then double-taps any point on the owner view (the owner view - * will center the double-tapped point, but we should re-center the zoom - * ring). - *

- * The (x,y) of the scroller is the (x,y) of the container's layout params. - */ - private Scroller mScroller; - - /** - * When showing the zoom ring, we add the view as a new window. However, - * there is logic that needs to know the size of the zoom ring which is - * determined after it's laid out. Therefore, we must post this logic onto - * the UI thread so it will be exceuted AFTER the layout. This is the logic. - */ - private Runnable mPostedVisibleInitializer; - - /** - * Only touch from the main thread. - */ - private static Dialog sTutorialDialog; - private static long sTutorialShowTime; - private static final int TUTORIAL_MIN_DISPLAY_TIME = 2000; - - private IntentFilter mConfigurationChangedFilter = - new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED); - - /** Listens for configuration changes so we can make sure we're still in a reasonable state. */ - private BroadcastReceiver mConfigurationChangedReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (!mIsZoomRingVisible) return; - - mHandler.removeMessages(MSG_POST_CONFIGURATION_CHANGED); - mHandler.sendEmptyMessage(MSG_POST_CONFIGURATION_CHANGED); - } - }; - - /** Keeps the scroller going (or starts it). */ - private static final int MSG_SCROLLER_STEP = 1; - /** When configuration changes, this is called after the UI thread is idle. */ - private static final int MSG_POST_CONFIGURATION_CHANGED = 2; - /** Used to delay the zoom ring dismissal. */ - private static final int MSG_DISMISS_ZOOM_RING = 3; - - /** - * If setVisible(true) is called and the owner view's window token is null, - * we delay the setVisible(true) call until it is not null. - */ - private static final int MSG_POST_SET_VISIBLE = 4; - - private Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_SCROLLER_STEP: - onScrollerStep(); - break; - - case MSG_POST_CONFIGURATION_CHANGED: - onPostConfigurationChanged(); - break; - - case MSG_DISMISS_ZOOM_RING: - setVisible(false); - break; - - case MSG_POST_SET_VISIBLE: - if (mOwnerView.getWindowToken() == null) { - // Doh, it is still null, throw an exception - throw new IllegalArgumentException( - "Cannot make the zoom ring visible if the owner view is " + - "not attached to a window."); - } - setVisible(true); - break; - } - - } - }; - - public ZoomRingController(Context context, View ownerView) { - mContext = context; - mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); - - mPanner = new Panner(); - mOwnerView = ownerView; - - mZoomRing = new ZoomRing(context); - mZoomRing.setId(com.android.internal.R.id.zoomControls); - mZoomRing.setLayoutParams(new FrameLayout.LayoutParams( - FrameLayout.LayoutParams.WRAP_CONTENT, - FrameLayout.LayoutParams.WRAP_CONTENT, - Gravity.CENTER)); - mZoomRing.setCallback(this); - - createPanningArrows(); - - mContainerLayoutParams = new LayoutParams(); - mContainerLayoutParams.gravity = Gravity.LEFT | Gravity.TOP; - mContainerLayoutParams.flags = LayoutParams.FLAG_NOT_TOUCHABLE | - LayoutParams.FLAG_NOT_FOCUSABLE | - LayoutParams.FLAG_LAYOUT_NO_LIMITS; - mContainerLayoutParams.height = LayoutParams.WRAP_CONTENT; - mContainerLayoutParams.width = LayoutParams.WRAP_CONTENT; - mContainerLayoutParams.type = LayoutParams.TYPE_APPLICATION_PANEL; - mContainerLayoutParams.format = PixelFormat.TRANSPARENT; - mContainerLayoutParams.windowAnimations = com.android.internal.R.style.Animation_ZoomRing; - - mContainer = new FrameLayout(context); - mContainer.setLayoutParams(mContainerLayoutParams); - mContainer.setMeasureAllChildren(true); - - mContainer.addView(mZoomRing); - mContainer.addView(mPanningArrows); - - mScroller = new Scroller(context, new DecelerateInterpolator()); - - ViewConfiguration vc = ViewConfiguration.get(context); - mScaledTouchSlop = vc.getScaledTouchSlop(); - - float density = context.getResources().getDisplayMetrics().density; - mPanGap = (int) (20 * density); - mInitiatePanGap = (int) (10 * density); - } - - private void createPanningArrows() { - mPanningArrows = new ImageView(mContext); - mPanningArrows.setImageDrawable(mZoomRing.getPanningArrowsDrawable()); - mPanningArrows.setLayoutParams(new FrameLayout.LayoutParams( - FrameLayout.LayoutParams.WRAP_CONTENT, - FrameLayout.LayoutParams.WRAP_CONTENT, - Gravity.CENTER)); - mPanningArrows.setVisibility(View.INVISIBLE); - - mPanningArrowsEnterAnimation = AnimationUtils.loadAnimation(mContext, - com.android.internal.R.anim.fade_in); - mPanningArrowsExitAnimation = AnimationUtils.loadAnimation(mContext, - com.android.internal.R.anim.fade_out); - } - - /** - * Sets the angle (in radians) between ticks. This is also the angle a user - * must move the thumb in order for the client to get a callback. Once there - * is a callback, the accumulator resets. For example, if you set this to - * PI/6, it will give a callback every time the user moves PI/6 amount on - * the ring. - * - * @param angle The angle for the callback threshold, in radians - */ - public void setTickDelta(float angle) { - mZoomRing.setTickDelta((int) (angle * ZoomRing.RADIAN_INT_MULTIPLIER)); - } - - /** - * Sets a drawable for the zoom ring track. - * - * @param drawable The drawable to use for the track. - * @hide Need a better way of doing this, but this one-off for browser so it - * can have its final look for the usability study - */ - public void setTrackDrawable(int drawable) { - mZoomRing.setBackgroundResource(drawable); - } - - /** - * Sets the callback for the zoom ring controller. - * - * @param callback The callback. - */ - public void setCallback(OnZoomListener callback) { - mCallback = callback; - } - - public void setVibration(boolean vibrate) { - mZoomRing.setVibration(vibrate); - } - - public void setThumbAngle(float angle) { - mZoomRing.setThumbAngle((int) (angle * ZoomRing.RADIAN_INT_MULTIPLIER)); - } - - public void setThumbAngleAnimated(float angle) { - mZoomRing.setThumbAngleAnimated((int) (angle * ZoomRing.RADIAN_INT_MULTIPLIER), 0); - } - - public void setThumbVisible(boolean thumbVisible) { - mZoomRing.setThumbVisible(thumbVisible); - } - - public void setThumbClockwiseBound(float angle) { - mZoomRing.setThumbClockwiseBound(angle >= 0 ? - (int) (angle * ZoomRing.RADIAN_INT_MULTIPLIER) : - Integer.MIN_VALUE); - } - - public void setThumbCounterclockwiseBound(float angle) { - mZoomRing.setThumbCounterclockwiseBound(angle >= 0 ? - (int) (angle * ZoomRing.RADIAN_INT_MULTIPLIER) : - Integer.MIN_VALUE); - } - - public boolean isVisible() { - return mIsZoomRingVisible; - } - - public void setVisible(boolean visible) { - - if (!useThisZoom(mContext)) return; - - if (visible) { - if (mOwnerView.getWindowToken() == null) { - /* - * We need a window token to show ourselves, maybe the owner's - * window hasn't been created yet but it will have been by the - * time the looper is idle, so post the setVisible(true) call. - */ - if (!mHandler.hasMessages(MSG_POST_SET_VISIBLE)) { - mHandler.sendEmptyMessage(MSG_POST_SET_VISIBLE); - } - return; - } - - dismissZoomRingDelayed(INACTIVITY_TIMEOUT); - } else { - mPanner.stop(); - } - - if (mIsZoomRingVisible == visible) { - return; - } - mIsZoomRingVisible = visible; - - if (visible) { - if (mContainerLayoutParams.token == null) { - mContainerLayoutParams.token = mOwnerView.getWindowToken(); - } - - mWindowManager.addView(mContainer, mContainerLayoutParams); - - if (mPostedVisibleInitializer == null) { - mPostedVisibleInitializer = new Runnable() { - public void run() { - refreshPositioningVariables(); - resetZoomRing(); - refreshContainerLayout(); - - if (mCallback != null) { - mCallback.onVisibilityChanged(true); - } - } - }; - } - - mPanningArrows.setAnimation(null); - - mHandler.post(mPostedVisibleInitializer); - - // Handle configuration changes when visible - mContext.registerReceiver(mConfigurationChangedReceiver, mConfigurationChangedFilter); - - // Steal key/touches events from the owner - mOwnerView.setOnKeyListener(this); - mOwnerView.setOnTouchListener(this); - mReleaseTouchListenerOnUp = false; - - } else { - // Don't want to steal any more keys/touches - mOwnerView.setOnKeyListener(null); - if (mTouchTargetView != null) { - // We are still stealing the touch events for this touch - // sequence, so release the touch listener later - mReleaseTouchListenerOnUp = true; - } else { - mOwnerView.setOnTouchListener(null); - } - - // No longer care about configuration changes - mContext.unregisterReceiver(mConfigurationChangedReceiver); - - mWindowManager.removeView(mContainer); - mHandler.removeCallbacks(mPostedVisibleInitializer); - - if (mCallback != null) { - mCallback.onVisibilityChanged(false); - } - } - - } - - private void refreshContainerLayout() { - if (mIsZoomRingVisible) { - mWindowManager.updateViewLayout(mContainer, mContainerLayoutParams); - } - } - - /** - * Returns the container of the zoom ring widget. The client can add views - * here to be shown alongside the zoom ring. See {@link #getZoomRingId()}. - *

- * Notes: - *

    - *
  • The controller dispatches touch events differently than the regular view - * framework. - *
  • Please ensure you set your view to INVISIBLE not GONE when hiding it. - *
- * - * @return The layout used by the container. - */ - public FrameLayout getContainer() { - return mContainer; - } - - /** - * Returns the id of the zoom ring widget. - * - * @return The id of the zoom ring widget. - */ - public int getZoomRingId() { - return mZoomRing.getId(); - } - - private void dismissZoomRingDelayed(int delay) { - mHandler.removeMessages(MSG_DISMISS_ZOOM_RING); - mHandler.sendEmptyMessageDelayed(MSG_DISMISS_ZOOM_RING, delay); - } - - private void resetZoomRing() { - mScroller.abortAnimation(); - - mContainerLayoutParams.x = mCenteredContainerX; - mContainerLayoutParams.y = mCenteredContainerY; - - // Reset the thumb - mZoomRing.resetThumbAngle(); - } - - /** - * Should be called by the client for each event belonging to the second tap - * (the down, move, up, and cancel events). - *

- * In most cases, the client can use a {@link GestureDetector} and forward events from - * {@link GestureDetector.OnDoubleTapListener#onDoubleTapEvent(MotionEvent)}. - * - * @param event The event belonging to the second tap. - * @return Whether the event was consumed. - */ - public boolean handleDoubleTapEvent(MotionEvent event) { - if (!useThisZoom(mContext)) return false; - - int action = event.getAction(); - - // TODO: make sure this works well with the - // ownerView.setOnTouchListener(this) instead of window receiving - // touches - if (action == MotionEvent.ACTION_DOWN) { - mTouchMode = TOUCH_MODE_WAITING_FOR_TAP_DRAG_MOVEMENT; - int x = (int) event.getX(); - int y = (int) event.getY(); - - refreshPositioningVariables(); - setVisible(true); - centerPoint(x, y); - ensureZoomRingIsCentered(); - - // Tap drag mode stuff - mTapDragStartX = x; - mTapDragStartY = y; - - } else if (action == MotionEvent.ACTION_CANCEL) { - mTouchMode = TOUCH_MODE_IDLE; - - } else { // action is move or up - switch (mTouchMode) { - case TOUCH_MODE_WAITING_FOR_TAP_DRAG_MOVEMENT: { - switch (action) { - case MotionEvent.ACTION_MOVE: - int x = (int) event.getX(); - int y = (int) event.getY(); - if (Math.abs(x - mTapDragStartX) > mScaledTouchSlop || - Math.abs(y - mTapDragStartY) > - mScaledTouchSlop) { - mZoomRing.setTapDragMode(true, x, y); - mTouchMode = TOUCH_MODE_FORWARDING_FOR_TAP_DRAG; - setTouchTargetView(mZoomRing); - } - return true; - - case MotionEvent.ACTION_UP: - mTouchMode = TOUCH_MODE_IDLE; - break; - } - break; - } - - case TOUCH_MODE_FORWARDING_FOR_TAP_DRAG: { - switch (action) { - case MotionEvent.ACTION_MOVE: - giveTouchToZoomRing(event); - return true; - - case MotionEvent.ACTION_UP: - mTouchMode = TOUCH_MODE_IDLE; - - /* - * This is a power-user feature that only shows the - * zoom while the user is performing the tap-drag. - * That means once it is released, the zoom ring - * should disappear. - */ - mZoomRing.setTapDragMode(false, (int) event.getX(), (int) event.getY()); - dismissZoomRingDelayed(0); - break; - } - break; - } - } - } - - return true; - } - - private void ensureZoomRingIsCentered() { - LayoutParams lp = mContainerLayoutParams; - - if (lp.x != mCenteredContainerX || lp.y != mCenteredContainerY) { - int width = mContainer.getWidth(); - int height = mContainer.getHeight(); - mScroller.startScroll(lp.x, lp.y, mCenteredContainerX - lp.x, - mCenteredContainerY - lp.y, RECENTERING_DURATION); - mHandler.sendEmptyMessage(MSG_SCROLLER_STEP); - } - } - - private void refreshPositioningVariables() { - mZoomRingWidth = mZoomRing.getWidth(); - mZoomRingHeight = mZoomRing.getHeight(); - - // Calculate the owner view's bounds - mOwnerView.getGlobalVisibleRect(mOwnerViewBounds); - - // Get the center - Gravity.apply(Gravity.CENTER, mContainer.getWidth(), mContainer.getHeight(), - mOwnerViewBounds, mTempRect); - mCenteredContainerX = mTempRect.left; - mCenteredContainerY = mTempRect.top; - } - - /** - * Centers the point (in owner view's coordinates). - */ - private void centerPoint(int x, int y) { - if (mCallback != null) { - mCallback.onCenter(x, y); - } - } - - private void giveTouchToZoomRing(MotionEvent event) { - int rawX = (int) event.getRawX(); - int rawY = (int) event.getRawY(); - int x = rawX - mContainerLayoutParams.x - mZoomRing.getLeft(); - int y = rawY - mContainerLayoutParams.y - mZoomRing.getTop(); - mZoomRing.handleTouch(event.getAction(), event.getEventTime(), x, y, rawX, rawY); - } - - /** @hide */ - public void onZoomRingSetMovableHintVisible(boolean visible) { - setPanningArrowsVisible(visible); - } - - /** @hide */ - public void onUserInteractionStarted() { - mHandler.removeMessages(MSG_DISMISS_ZOOM_RING); - } - - /** @hide */ - public void onUserInteractionStopped() { - dismissZoomRingDelayed(INACTIVITY_TIMEOUT); - } - - /** @hide */ - public void onZoomRingMovingStarted() { - mScroller.abortAnimation(); - mTouchingEdgeStartTime = 0; - mMovingZoomRingOobX = 0; - mMovingZoomRingOobY = 0; - if (mCallback != null) { - mCallback.onBeginPan(); - } - } - - private void setPanningArrowsVisible(boolean visible) { - mPanningArrows.startAnimation(visible ? mPanningArrowsEnterAnimation - : mPanningArrowsExitAnimation); - mPanningArrows.setVisibility(visible ? View.VISIBLE : View.INVISIBLE); - } - - /** @hide */ - public boolean onZoomRingMoved(int deltaX, int deltaY, int rawX, int rawY) { - - if (mMovingZoomRingOobX != 0) { - /* - * The finger has moved off the point where it originally touched - * the zidget. - */ - boolean wasOobLeft = mMovingZoomRingOobX < 0; - mMovingZoomRingOobX += deltaX; - if ((wasOobLeft && mMovingZoomRingOobX > 0) || - (!wasOobLeft && mMovingZoomRingOobX < 0)) { - /* - * Woot, the finger is back on the original point. Infact, it - * went PAST its original point, so take the amount it passed - * and use that as the delta to move the zoom ring. - */ - deltaX = mMovingZoomRingOobX; - // No longer out-of-bounds, reset - mMovingZoomRingOobX = 0; - } else { - // The finger is still not back, eat this movement - deltaX = 0; - } - } - - if (mMovingZoomRingOobY != 0) { - // See above for comments - boolean wasOobUp = mMovingZoomRingOobY < 0; - mMovingZoomRingOobY += deltaY; - if ((wasOobUp && mMovingZoomRingOobY > 0) || (!wasOobUp && mMovingZoomRingOobY < 0)) { - deltaY = mMovingZoomRingOobY; - mMovingZoomRingOobY = 0; - } else { - deltaY = 0; - } - } - - WindowManager.LayoutParams lp = mContainerLayoutParams; - Rect ownerBounds = mOwnerViewBounds; - - int zoomRingLeft = mZoomRing.getLeft(); - int zoomRingTop = mZoomRing.getTop(); - - int newX = lp.x + deltaX; - int newZoomRingX = newX + zoomRingLeft; - newZoomRingX = (newZoomRingX <= ownerBounds.left) ? ownerBounds.left : - (newZoomRingX + mZoomRingWidth > ownerBounds.right) ? - ownerBounds.right - mZoomRingWidth : newZoomRingX; - lp.x = newZoomRingX - zoomRingLeft; - - int newY = lp.y + deltaY; - int newZoomRingY = newY + zoomRingTop; - newZoomRingY = (newZoomRingY <= ownerBounds.top) ? ownerBounds.top : - (newZoomRingY + mZoomRingHeight > ownerBounds.bottom) ? - ownerBounds.bottom - mZoomRingHeight : newZoomRingY; - lp.y = newZoomRingY - zoomRingTop; - - refreshContainerLayout(); - - // Check for pan - boolean horizontalPanning = true; - int leftGap = newZoomRingX - ownerBounds.left; - if (leftGap < mPanGap) { - if (leftGap == 0 && deltaX != 0 && mMovingZoomRingOobX == 0) { - // Future moves in this direction should be accumulated in mMovingZoomRingOobX - mMovingZoomRingOobX = deltaX / Math.abs(deltaX); - } - if (shouldPan(leftGap)) { - mPanner.setHorizontalStrength(-getStrengthFromGap(leftGap)); - } - } else { - int rightGap = ownerBounds.right - (lp.x + mZoomRingWidth + zoomRingLeft); - if (rightGap < mPanGap) { - if (rightGap == 0 && deltaX != 0 && mMovingZoomRingOobX == 0) { - mMovingZoomRingOobX = deltaX / Math.abs(deltaX); - } - if (shouldPan(rightGap)) { - mPanner.setHorizontalStrength(getStrengthFromGap(rightGap)); - } - } else { - mPanner.setHorizontalStrength(0); - horizontalPanning = false; - } - } - - int topGap = newZoomRingY - ownerBounds.top; - if (topGap < mPanGap) { - if (topGap == 0 && deltaY != 0 && mMovingZoomRingOobY == 0) { - mMovingZoomRingOobY = deltaY / Math.abs(deltaY); - } - if (shouldPan(topGap)) { - mPanner.setVerticalStrength(-getStrengthFromGap(topGap)); - } - } else { - int bottomGap = ownerBounds.bottom - (lp.y + mZoomRingHeight + zoomRingTop); - if (bottomGap < mPanGap) { - if (bottomGap == 0 && deltaY != 0 && mMovingZoomRingOobY == 0) { - mMovingZoomRingOobY = deltaY / Math.abs(deltaY); - } - if (shouldPan(bottomGap)) { - mPanner.setVerticalStrength(getStrengthFromGap(bottomGap)); - } - } else { - mPanner.setVerticalStrength(0); - if (!horizontalPanning) { - // Neither are panning, reset any timer to start pan mode - mTouchingEdgeStartTime = 0; - mPanningInitiated = false; - mPanner.stop(); - } - } - } - - return true; - } - - private boolean shouldPan(int gap) { - if (mPanningInitiated) return true; - - if (gap < mInitiatePanGap) { - long time = SystemClock.elapsedRealtime(); - if (mTouchingEdgeStartTime != 0 && - mTouchingEdgeStartTime + INITIATE_PAN_DELAY < time) { - mPanningInitiated = true; - return true; - } else if (mTouchingEdgeStartTime == 0) { - mTouchingEdgeStartTime = time; - } else { - } - } else { - // Moved away from the initiate pan gap, so reset the timer - mTouchingEdgeStartTime = 0; - } - return false; - } - - /** @hide */ - public void onZoomRingMovingStopped() { - mPanner.stop(); - setPanningArrowsVisible(false); - if (mCallback != null) { - mCallback.onEndPan(); - } - } - - private int getStrengthFromGap(int gap) { - return gap > mPanGap ? 0 : - (mPanGap - gap) * 100 / mPanGap; - } - - /** @hide */ - public void onZoomRingThumbDraggingStarted() { - if (mCallback != null) { - mCallback.onBeginDrag(); - } - } - - /** @hide */ - public boolean onZoomRingThumbDragged(int numLevels, int startAngle, int curAngle) { - if (mCallback != null) { - int deltaZoomLevel = -numLevels; - - return mCallback.onDragZoom(deltaZoomLevel, - getZoomRingCenterXInOwnerCoordinates(), - getZoomRingCenterYInOwnerCoordinates(), - (float) startAngle / ZoomRing.RADIAN_INT_MULTIPLIER, - (float) curAngle / ZoomRing.RADIAN_INT_MULTIPLIER); - } - - return false; - } - - private int getZoomRingCenterXInOwnerCoordinates() { - int globalZoomCenterX = mContainerLayoutParams.x + mZoomRing.getLeft() + - mZoomRingWidth / 2; - return globalZoomCenterX - mOwnerViewBounds.left; - } - - private int getZoomRingCenterYInOwnerCoordinates() { - int globalZoomCenterY = mContainerLayoutParams.y + mZoomRing.getTop() + - mZoomRingHeight / 2; - return globalZoomCenterY - mOwnerViewBounds.top; - } - - /** @hide */ - public void onZoomRingThumbDraggingStopped() { - if (mCallback != null) { - mCallback.onEndDrag(); - } - } - - /** @hide */ - public void onZoomRingDismissed() { - mHandler.removeMessages(MSG_DISMISS_ZOOM_RING); - setVisible(false); - } - - /** @hide */ - public void onRingDown(int tickAngle, int touchAngle) { - } - - /** @hide */ - public boolean onTouch(View v, MotionEvent event) { - if (sTutorialDialog != null && sTutorialDialog.isShowing() && - SystemClock.elapsedRealtime() - sTutorialShowTime >= TUTORIAL_MIN_DISPLAY_TIME) { - finishZoomTutorial(); - } - - int action = event.getAction(); - - if (mReleaseTouchListenerOnUp) { - // The ring was dismissed but we need to throw away all events until the up - if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) { - mOwnerView.setOnTouchListener(null); - setTouchTargetView(null); - mReleaseTouchListenerOnUp = false; - } - - // Eat this event - return true; - } - - View targetView = mTouchTargetView; - - switch (action) { - case MotionEvent.ACTION_DOWN: - targetView = getViewForTouch((int) event.getRawX(), (int) event.getRawY()); - setTouchTargetView(targetView); - break; - - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - setTouchTargetView(null); - break; - } - - if (targetView != null) { - // The upperleft corner of the target view in raw coordinates - int targetViewRawX = mContainerLayoutParams.x + mTouchTargetLocationInWindow[0]; - int targetViewRawY = mContainerLayoutParams.y + mTouchTargetLocationInWindow[1]; - - MotionEvent containerEvent = MotionEvent.obtain(event); - // Convert the motion event into the target view's coordinates (from - // owner view's coordinates) - containerEvent.offsetLocation(mOwnerViewBounds.left - targetViewRawX, - mOwnerViewBounds.top - targetViewRawY); - boolean retValue = targetView.dispatchTouchEvent(containerEvent); - containerEvent.recycle(); - return retValue; - - } else { -// dismissZoomRingDelayed(ZOOM_CONTROLS_TIMEOUT); - if (action == MotionEvent.ACTION_DOWN) { - dismissZoomRingDelayed(OUTSIDE_TAP_DISMISS_DELAY); - } - - return false; - } - } - - private void setTouchTargetView(View view) { - mTouchTargetView = view; - if (view != null) { - view.getLocationInWindow(mTouchTargetLocationInWindow); - } - } - - /** - * Returns the View that should receive a touch at the given coordinates. - * - * @param rawX The raw X. - * @param rawY The raw Y. - * @return The view that should receive the touches, or null if there is not one. - */ - private View getViewForTouch(int rawX, int rawY) { - // Check to see if it is touching the ring - int containerCenterX = mContainerLayoutParams.x + mContainer.getWidth() / 2; - int containerCenterY = mContainerLayoutParams.y + mContainer.getHeight() / 2; - int distanceFromCenterX = rawX - containerCenterX; - int distanceFromCenterY = rawY - containerCenterY; - int zoomRingRadius = mZoomRing.getTrackOuterRadius(); - if (distanceFromCenterX * distanceFromCenterX + - distanceFromCenterY * distanceFromCenterY <= - zoomRingRadius * zoomRingRadius) { - return mZoomRing; - } - - // Check to see if it is touching any other clickable View. - // Reverse order so the child drawn on top gets first dibs. - int containerCoordsX = rawX - mContainerLayoutParams.x; - int containerCoordsY = rawY - mContainerLayoutParams.y; - Rect frame = mTempRect; - for (int i = mContainer.getChildCount() - 1; i >= 0; i--) { - View child = mContainer.getChildAt(i); - if (child == mZoomRing || child.getVisibility() != View.VISIBLE || - !child.isClickable()) { - continue; - } - - child.getHitRect(frame); - if (frame.contains(containerCoordsX, containerCoordsY)) { - return child; - } - } - - return null; - } - - /** - * Steals key events from the owner view. - * - * @hide - */ - public boolean onKey(View v, int keyCode, KeyEvent event) { - switch (keyCode) { - case KeyEvent.KEYCODE_DPAD_LEFT: - case KeyEvent.KEYCODE_DPAD_RIGHT: - // Eat these - return true; - - case KeyEvent.KEYCODE_DPAD_UP: - case KeyEvent.KEYCODE_DPAD_DOWN: - // Keep the zoom alive a little longer - dismissZoomRingDelayed(INACTIVITY_TIMEOUT); - // They started zooming, hide the thumb arrows - mZoomRing.setThumbArrowsVisible(false); - - if (mCallback != null && event.getAction() == KeyEvent.ACTION_DOWN) { - mCallback.onSimpleZoom(keyCode == KeyEvent.KEYCODE_DPAD_UP, - getZoomRingCenterXInOwnerCoordinates(), - getZoomRingCenterYInOwnerCoordinates()); - } - - return true; - } - - return false; - } - - private void onScrollerStep() { - if (!mScroller.computeScrollOffset() || !mIsZoomRingVisible) return; - - mContainerLayoutParams.x = mScroller.getCurrX(); - mContainerLayoutParams.y = mScroller.getCurrY(); - refreshContainerLayout(); - - mHandler.sendEmptyMessage(MSG_SCROLLER_STEP); - } - - private void onPostConfigurationChanged() { - dismissZoomRingDelayed(INACTIVITY_TIMEOUT); - refreshPositioningVariables(); - ensureZoomRingIsCentered(); - } - - /* - * This is static so Activities can call this instead of the Views - * (Activities usually do not have a reference to the ZoomRingController - * instance.) - */ - /** - * Shows a "tutorial" (some text) to the user teaching her the new zoom - * invocation method. Must call from the main thread. - *

- * It checks the global system setting to ensure this has not been seen - * before. Furthermore, if the application does not have privilege to write - * to the system settings, it will store this bit locally in a shared - * preference. - * - * @hide This should only be used by our main apps--browser, maps, and - * gallery - */ - public static void showZoomTutorialOnce(Context context) { - ContentResolver cr = context.getContentResolver(); - if (Settings.System.getInt(cr, SETTING_NAME_SHOWN_TOAST, 0) == 1) { - return; - } - - SharedPreferences sp = context.getSharedPreferences("_zoom", Context.MODE_PRIVATE); - if (sp.getInt(SETTING_NAME_SHOWN_TOAST, 0) == 1) { - return; - } - - if (sTutorialDialog != null && sTutorialDialog.isShowing()) { - sTutorialDialog.dismiss(); - } - - LayoutInflater layoutInflater = - (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - TextView textView = (TextView) layoutInflater.inflate( - com.android.internal.R.layout.alert_dialog_simple_text, null) - .findViewById(android.R.id.text1); - textView.setText(com.android.internal.R.string.tutorial_double_tap_to_zoom_message_short); - - sTutorialDialog = new AlertDialog.Builder(context) - .setView(textView) - .setIcon(0) - .create(); - - Window window = sTutorialDialog.getWindow(); - window.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM); - window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND | - WindowManager.LayoutParams.FLAG_BLUR_BEHIND); - window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | - WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE); - - sTutorialDialog.show(); - sTutorialShowTime = SystemClock.elapsedRealtime(); - } - - /** @hide Should only be used by Android platform apps */ - public static void finishZoomTutorial(Context context, boolean userNotified) { - if (sTutorialDialog == null) return; - - sTutorialDialog.dismiss(); - sTutorialDialog = null; - - // Record that they have seen the tutorial - if (userNotified) { - try { - Settings.System.putInt(context.getContentResolver(), SETTING_NAME_SHOWN_TOAST, 1); - } catch (SecurityException e) { - /* - * The app does not have permission to clear this global flag, make - * sure the user does not see the message when he comes back to this - * same app at least. - */ - SharedPreferences sp = context.getSharedPreferences("_zoom", Context.MODE_PRIVATE); - sp.edit().putInt(SETTING_NAME_SHOWN_TOAST, 1).commit(); - } - } - } - - /** @hide Should only be used by Android platform apps */ - public void finishZoomTutorial() { - finishZoomTutorial(mContext, true); - } - - /** - * Sets the initial velocity of a pan. - * - * @param startVelocity The initial velocity to move the owner view, in - * pixels per second. - */ - public void setPannerStartVelocity(float startVelocity) { - mPanner.mStartVelocity = startVelocity; - } - - /** - * Sets the accelartion of the pan. - * - * @param acceleration The acceleration, in pixels per second squared. - */ - public void setPannerAcceleration(float acceleration) { - mPanner.mAcceleration = acceleration; - } - - /** - * Sets the maximum velocity of a pan. - * - * @param maxVelocity The max velocity to move the owner view, in pixels per - * second. - */ - public void setPannerMaxVelocity(float maxVelocity) { - mPanner.mMaxVelocity = maxVelocity; - } - - /** - * Sets the duration before acceleration will be applied. - * - * @param duration The duration, in milliseconds. - */ - public void setPannerStartAcceleratingDuration(int duration) { - mPanner.mStartAcceleratingDuration = duration; - } - - private class Panner implements Runnable { - private static final int RUN_DELAY = 15; - private static final float STOP_SLOWDOWN = 0.8f; - - private final Handler mUiHandler = new Handler(); - - private int mVerticalStrength; - private int mHorizontalStrength; - - private boolean mStopping; - - /** The time this current pan started. */ - private long mStartTime; - - /** The time of the last callback to pan the map/browser/etc. */ - private long mPreviousCallbackTime; - - // TODO Adjust to be DPI safe - private float mStartVelocity = 135; - private float mAcceleration = 160; - private float mMaxVelocity = 1000; - private int mStartAcceleratingDuration = 700; - private float mVelocity; - - /** -100 (full left) to 0 (none) to 100 (full right) */ - public void setHorizontalStrength(int horizontalStrength) { - if (mHorizontalStrength == 0 && mVerticalStrength == 0 && horizontalStrength != 0) { - start(); - } else if (mVerticalStrength == 0 && horizontalStrength == 0) { - stop(); - } - - mHorizontalStrength = horizontalStrength; - mStopping = false; - } - - /** -100 (full up) to 0 (none) to 100 (full down) */ - public void setVerticalStrength(int verticalStrength) { - if (mHorizontalStrength == 0 && mVerticalStrength == 0 && verticalStrength != 0) { - start(); - } else if (mHorizontalStrength == 0 && verticalStrength == 0) { - stop(); - } - - mVerticalStrength = verticalStrength; - mStopping = false; - } - - private void start() { - mUiHandler.post(this); - mPreviousCallbackTime = 0; - mStartTime = 0; - } - - public void stop() { - mStopping = true; - } - - public void run() { - if (mStopping) { - mHorizontalStrength *= STOP_SLOWDOWN; - mVerticalStrength *= STOP_SLOWDOWN; - } - - if (mHorizontalStrength == 0 && mVerticalStrength == 0) { - return; - } - - boolean firstRun = mPreviousCallbackTime == 0; - long curTime = SystemClock.elapsedRealtime(); - int panAmount = getPanAmount(mPreviousCallbackTime, curTime); - mPreviousCallbackTime = curTime; - - if (firstRun) { - mStartTime = curTime; - mVelocity = mStartVelocity; - } else { - int panX = panAmount * mHorizontalStrength / 100; - int panY = panAmount * mVerticalStrength / 100; - - if (mCallback != null) { - mCallback.onPan(panX, panY); - } - } - - mUiHandler.postDelayed(this, RUN_DELAY); - } - - private int getPanAmount(long previousTime, long currentTime) { - if (mVelocity > mMaxVelocity) { - mVelocity = mMaxVelocity; - } else if (mVelocity < mMaxVelocity) { - // See if it's time to add in some acceleration - if (currentTime - mStartTime > mStartAcceleratingDuration) { - mVelocity += (currentTime - previousTime) * mAcceleration / 1000; - } - } - - return (int) ((currentTime - previousTime) * mVelocity) / 1000; - } - - } - - /** - * Interface used to inform the client of zoom events that the user - * triggers. - */ - public interface OnZoomListener { - /** - * Called when the user begins dragging the thumb on the zoom ring. - */ - void onBeginDrag(); - - /** - * Called when the user drags the thumb and passes a tick causing a - * zoom. - * - * @param deltaZoomLevel The number of levels to be zoomed. Positive to - * zoom in, negative to zoom out. - * @param centerX The point about which to zoom. The zoom should pin - * this point, leaving it at the same coordinate. This is - * relative to the owner view's upper-left. - * @param centerY The point about which to zoom. The zoom should pin - * this point, leaving it at the same coordinate. This is - * relative to the owner view's upper-left. - * @param startAngle The angle where the user started dragging the thumb. - * @param curAngle The current angle of the thumb. - * @return Whether the owner was zoomed. - */ - boolean onDragZoom(int deltaZoomLevel, int centerX, int centerY, float startAngle, - float curAngle); - - /** - * Called when the user releases the thumb. - */ - void onEndDrag(); - - /** - * Called when the user zooms via some other mechanism, for example - * arrow keys or a trackball. - * - * @param zoomIn Whether to zoom in (true) or out (false). - * @param centerX See {@link #onDragZoom(int, int, int, float, float)}. - * @param centerY See {@link #onDragZoom(int, int, int, float, float)}. - */ - void onSimpleZoom(boolean zoomIn, int centerX, int centerY); - - /** - * Called when the user begins moving the zoom ring in order to pan the - * owner. - */ - void onBeginPan(); - - /** - * Called when the owner should pan as a result of the user moving the zoom ring. - * - * @param deltaX The amount to pan horizontally. - * @param deltaY The amount to pan vertically. - * @return Whether the owner was panned. - */ - boolean onPan(int deltaX, int deltaY); - - /** - * Called when the user releases the zoom ring. - */ - void onEndPan(); - - /** - * Called when the client should center the owner on the given point. - * - * @param x The x to center on, relative to the owner view's upper-left. - * @param y The y to center on, relative to the owner view's upper-left. - */ - void onCenter(int x, int y); - - /** - * Called when the zoom ring's visibility changes. - * - * @param visible Whether the zoom ring is visible (true) or not (false). - */ - void onVisibilityChanged(boolean visible); - } -} diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl index 9030a3e377c26..adec0a750ebc5 100644 --- a/core/java/com/android/internal/view/IInputMethodManager.aidl +++ b/core/java/com/android/internal/view/IInputMethodManager.aidl @@ -43,7 +43,7 @@ interface IInputMethodManager { in ResultReceiver resultReceiver); boolean hideSoftInput(in IInputMethodClient client, int flags, in ResultReceiver resultReceiver); - void windowGainedFocus(in IInputMethodClient client, + void windowGainedFocus(in IInputMethodClient client, in IBinder windowToken, boolean viewHasFocus, boolean isTextEditor, int softInputMode, boolean first, int windowFlags); diff --git a/core/jni/Android.mk b/core/jni/Android.mk index 6e5c4e07e2fe7..18f2878ad5ad1 100644 --- a/core/jni/Android.mk +++ b/core/jni/Android.mk @@ -27,6 +27,7 @@ LOCAL_SRC_FILES:= \ android_database_SQLiteProgram.cpp \ android_database_SQLiteQuery.cpp \ android_database_SQLiteStatement.cpp \ + android_emoji_EmojiFactory.cpp \ android_view_Display.cpp \ android_view_Surface.cpp \ android_view_ViewRoot.cpp \ @@ -132,6 +133,7 @@ LOCAL_C_INCLUDES += \ external/tremor/Tremor \ external/icu4c/i18n \ external/icu4c/common \ + frameworks/opt/emoji LOCAL_SHARED_LIBRARIES := \ libexpat \ @@ -156,12 +158,13 @@ LOCAL_SHARED_LIBRARIES := \ libicui18n \ libicudata \ libmedia \ - libwpa_client + libwpa_client \ + libemoji ifeq ($(BOARD_HAVE_BLUETOOTH),true) LOCAL_C_INCLUDES += \ external/dbus \ - external/bluez/libs/include + system/bluetooth/bluez-clean-headers LOCAL_CFLAGS += -DHAVE_BLUETOOTH LOCAL_SHARED_LIBRARIES += libbluedroid libdbus endif @@ -190,5 +193,4 @@ LOCAL_MODULE:= libandroid_runtime include $(BUILD_SHARED_LIBRARY) - include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp index 40dc2a1dc4d13..28c602b8dad34 100644 --- a/core/jni/AndroidRuntime.cpp +++ b/core/jni/AndroidRuntime.cpp @@ -92,6 +92,7 @@ extern int register_android_util_EventLog(JNIEnv* env); extern int register_android_util_Log(JNIEnv* env); extern int register_android_content_StringBlock(JNIEnv* env); extern int register_android_content_XmlBlock(JNIEnv* env); +extern int register_android_emoji_EmojiFactory(JNIEnv* env); extern int register_android_graphics_Canvas(JNIEnv* env); extern int register_android_graphics_ColorFilter(JNIEnv* env); extern int register_android_graphics_DrawFilter(JNIEnv* env); @@ -1026,6 +1027,7 @@ static const RegJNIRec gRegJNI[] = { REG_JNI(register_android_content_AssetManager), REG_JNI(register_android_content_StringBlock), REG_JNI(register_android_content_XmlBlock), + REG_JNI(register_android_emoji_EmojiFactory), REG_JNI(register_android_security_Md5MessageDigest), REG_JNI(register_android_text_AndroidCharacter), REG_JNI(register_android_text_KeyCharacterMap), diff --git a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp b/core/jni/android_bluetooth_BluetoothAudioGateway.cpp index 7f87d8028b5eb..bf2365094917f 100755 --- a/core/jni/android_bluetooth_BluetoothAudioGateway.cpp +++ b/core/jni/android_bluetooth_BluetoothAudioGateway.cpp @@ -49,8 +49,6 @@ #ifdef HAVE_BLUETOOTH #include -#include -#include #include #include #endif diff --git a/core/jni/android_emoji_EmojiFactory.cpp b/core/jni/android_emoji_EmojiFactory.cpp new file mode 100644 index 0000000000000..59f63a83cac54 --- /dev/null +++ b/core/jni/android_emoji_EmojiFactory.cpp @@ -0,0 +1,292 @@ +#include "SkTypes.h" +#include "SkImageDecoder.h" + +#define LOG_TAG "DoCoMoEmojiFactory_jni" +#include +#include + +#include "EmojiFactory.h" +#include + +#include +// #include + +namespace android { + +// Note: This class is originally developed so that libandroid_runtime does +// not have to depend on libemoji which is optional library. However, we +// cannot use this class, since current (2009-02-16) bionic libc does not allow +// dlopen()-ing inside dlopen(), while not only this class but also libemoji +// uses dlopen(). +class EmojiFactoryCaller { + public: + EmojiFactoryCaller(); + virtual ~EmojiFactoryCaller(); + EmojiFactory *TryCallGetImplementation(const char* name); + EmojiFactory *TryCallGetAvailableImplementation(); + private: + void *m_handle; + EmojiFactory *(*m_get_implementation)(const char*); + EmojiFactory *(*m_get_available_implementation)(); +}; + +EmojiFactoryCaller::EmojiFactoryCaller() { + m_handle = dlopen("libemoji.so", RTLD_LAZY | RTLD_LOCAL); + const char* error_str = dlerror(); + if (error_str) { + LOGI("Failed to load libemoji.so: %s", error_str); + return; + } + + m_get_implementation = + reinterpret_cast( + dlsym(m_handle, "GetImplementation")); + error_str = dlerror(); + if (error_str) { + LOGE("Failed to get symbol of GetImplementation: %s", error_str); + dlclose(m_handle); + m_handle = NULL; + return; + } + + m_get_available_implementation = + reinterpret_cast( + dlsym(m_handle,"GetAvailableImplementation")); + error_str = dlerror(); + if (error_str) { + LOGE("Failed to get symbol of GetAvailableImplementation: %s", error_str); + dlclose(m_handle); + m_handle = NULL; + return; + } +} + +EmojiFactoryCaller::~EmojiFactoryCaller() { + if (m_handle) { + dlclose(m_handle); + } +} + +EmojiFactory *EmojiFactoryCaller::TryCallGetImplementation( + const char* name) { + if (NULL == m_handle) { + return NULL; + } + return m_get_implementation(name); +} + +EmojiFactory *EmojiFactoryCaller::TryCallGetAvailableImplementation() { + if (NULL == m_handle) { + return NULL; + } + return m_get_available_implementation(); +} + +// Note: bionic libc's dlopen() does not allow recursive dlopen(). So currently +// we cannot use EmojiFactoryCaller here. +// static EmojiFactoryCaller* gCaller; +// static pthread_once_t g_once = PTHREAD_ONCE_INIT; + +static jclass gString_class; + +static jclass gBitmap_class; +static jmethodID gBitmap_constructorMethodID; + +static jclass gEmojiFactory_class; +static jmethodID gEmojiFactory_constructorMethodID; + +// static void InitializeCaller() { +// gCaller = new EmojiFactoryCaller(); +// } + +static jobject create_java_EmojiFactory( + JNIEnv* env, EmojiFactory* factory, jstring name) { + jobject obj = env->AllocObject(gEmojiFactory_class); + if (obj) { + env->CallVoidMethod(obj, gEmojiFactory_constructorMethodID, + (jint)factory, name); + if (env->ExceptionCheck() != 0) { + LOGE("*** Uncaught exception returned from Java call!\n"); + env->ExceptionDescribe(); + obj = NULL; + } + } + return obj; +} + +static jobject android_emoji_EmojiFactory_newInstance( + JNIEnv* env, jobject clazz, jstring name) { + // pthread_once(&g_once, InitializeCaller); + + if (NULL == name) { + return NULL; + } + + const jchar* jchars = env->GetStringChars(name, NULL); + jsize len = env->GetStringLength(name); + String8 str(String16(jchars, len)); + + // EmojiFactory *factory = gCaller->TryCallGetImplementation(str.string()); + EmojiFactory *factory = EmojiFactory::GetImplementation(str.string()); + + env->ReleaseStringChars(name, jchars); + + return create_java_EmojiFactory(env, factory, name); +} + +static jobject android_emoji_EmojiFactory_newAvailableInstance( + JNIEnv* env, jobject clazz) { + // pthread_once(&g_once, InitializeCaller); + + // EmojiFactory *factory = gCaller->TryCallGetAvailableImplementation(); + EmojiFactory *factory = EmojiFactory::GetAvailableImplementation(); + if (NULL == factory) { + return NULL; + } + String16 name_16(String8(factory->Name())); + jstring jname = env->NewString(name_16.string(), name_16.size()); + if (NULL == jname) { + return NULL; + } + + return create_java_EmojiFactory(env, factory, jname); +} + +static jobject android_emoji_EmojiFactory_getBitmapFromAndroidPua( + JNIEnv* env, jobject clazz, jint nativeEmojiFactory, jint pua) { + EmojiFactory *factory = reinterpret_cast(nativeEmojiFactory); + + int size; + const char *bytes = factory->GetImageBinaryFromAndroidPua(pua, &size); + if (bytes == NULL) { + return NULL; + } + + SkBitmap *bitmap = new SkBitmap; + if (!SkImageDecoder::DecodeMemory(bytes, size, bitmap)) { + LOGE("SkImageDecoder::DecodeMemory() failed."); + return NULL; + } + + jobject obj = env->AllocObject(gBitmap_class); + if (obj) { + env->CallVoidMethod(obj, gBitmap_constructorMethodID, + reinterpret_cast(bitmap), false, NULL); + if (env->ExceptionCheck() != 0) { + LOGE("*** Uncaught exception returned from Java call!\n"); + env->ExceptionDescribe(); + return NULL; + } + } + + return obj; +} + +static void android_emoji_EmojiFactory_destructor( + JNIEnv* env, jobject obj, jint nativeEmojiFactory) { + EmojiFactory *factory = reinterpret_cast(nativeEmojiFactory); + delete factory; +} + +static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis( + JNIEnv* env, jobject obj, jint nativeEmojiFactory, jchar sjis) { + EmojiFactory *factory = reinterpret_cast(nativeEmojiFactory); + return factory->GetAndroidPuaFromVendorSpecificSjis(sjis); +} + +static jint android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua( + JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint pua) { + EmojiFactory *factory = reinterpret_cast(nativeEmojiFactory); + return factory->GetVendorSpecificSjisFromAndroidPua(pua); +} + +static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua( + JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint vsu) { + EmojiFactory *factory = reinterpret_cast(nativeEmojiFactory); + return factory->GetAndroidPuaFromVendorSpecificPua(vsu); +} + +static jint android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua( + JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint pua) { + EmojiFactory *factory = reinterpret_cast(nativeEmojiFactory); + return factory->GetVendorSpecificPuaFromAndroidPua(pua); +} + +static jint android_emoji_EmojiFactory_getMaximumVendorSpecificPua( + JNIEnv* env, jobject obj, jint nativeEmojiFactory) { + EmojiFactory *factory = reinterpret_cast(nativeEmojiFactory); + return factory->GetMaximumVendorSpecificPua(); +} + +static jint android_emoji_EmojiFactory_getMinimumVendorSpecificPua( + JNIEnv* env, jobject obj, jint nativeEmojiFactory) { + EmojiFactory *factory = reinterpret_cast(nativeEmojiFactory); + return factory->GetMinimumVendorSpecificPua(); +} + +static jint android_emoji_EmojiFactory_getMaximumAndroidPua( + JNIEnv* env, jobject obj, jint nativeEmojiFactory) { + EmojiFactory *factory = reinterpret_cast(nativeEmojiFactory); + return factory->GetMaximumAndroidPua(); +} + +static jint android_emoji_EmojiFactory_getMinimumAndroidPua( + JNIEnv* env, jobject obj, jint nativeEmojiFactory) { + EmojiFactory *factory = reinterpret_cast(nativeEmojiFactory); + return factory->GetMinimumAndroidPua(); +} + +static JNINativeMethod gMethods[] = { + { "newInstance", "(Ljava/lang/String;)Landroid/emoji/EmojiFactory;", + (void*)android_emoji_EmojiFactory_newInstance}, + { "newAvailableInstance", "()Landroid/emoji/EmojiFactory;", + (void*)android_emoji_EmojiFactory_newAvailableInstance}, + { "nativeDestructor", "(I)V", + (void*)android_emoji_EmojiFactory_destructor}, + { "nativeGetBitmapFromAndroidPua", "(II)Landroid/graphics/Bitmap;", + (void*)android_emoji_EmojiFactory_getBitmapFromAndroidPua}, + { "nativeGetAndroidPuaFromVendorSpecificSjis", "(IC)I", + (void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis}, + { "nativeGetVendorSpecificSjisFromAndroidPua", "(II)I", + (void*)android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua}, + { "nativeGetAndroidPuaFromVendorSpecificPua", "(II)I", + (void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua}, + { "nativeGetVendorSpecificPuaFromAndroidPua", "(II)I", + (void*)android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua}, + { "nativeGetMaximumVendorSpecificPua", "(I)I", + (void*)android_emoji_EmojiFactory_getMaximumVendorSpecificPua}, + { "nativeGetMinimumVendorSpecificPua", "(I)I", + (void*)android_emoji_EmojiFactory_getMinimumVendorSpecificPua}, + { "nativeGetMaximumAndroidPua", "(I)I", + (void*)android_emoji_EmojiFactory_getMaximumAndroidPua}, + { "nativeGetMinimumAndroidPua", "(I)I", + (void*)android_emoji_EmojiFactory_getMinimumAndroidPua} +}; + +static jclass make_globalref(JNIEnv* env, const char classname[]) +{ + jclass c = env->FindClass(classname); + SkASSERT(c); + return (jclass)env->NewGlobalRef(c); +} + +static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz, + const char fieldname[], const char type[]) +{ + jfieldID id = env->GetFieldID(clazz, fieldname, type); + SkASSERT(id); + return id; +} + +int register_android_emoji_EmojiFactory(JNIEnv* env) { + gBitmap_class = make_globalref(env, "android/graphics/Bitmap"); + gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "", + "(IZ[B)V"); + gEmojiFactory_class = make_globalref(env, "android/emoji/EmojiFactory"); + gEmojiFactory_constructorMethodID = env->GetMethodID( + gEmojiFactory_class, "", "(ILjava/lang/String;)V"); + return jniRegisterNativeMethods(env, "android/emoji/EmojiFactory", + gMethods, NELEM(gMethods)); +} + +} // namespace android diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp index c98207a58b57f..fcab8130d4b3d 100644 --- a/core/jni/android_net_wifi_Wifi.cpp +++ b/core/jni/android_net_wifi_Wifi.cpp @@ -397,6 +397,16 @@ static jboolean android_net_wifi_setBluetoothCoexistenceModeCommand(JNIEnv* env, return (jboolean)!cmdTooLong && doBooleanCommand(cmdstr, "OK"); } +static jboolean android_net_wifi_setBluetoothCoexistenceScanModeCommand(JNIEnv* env, jobject clazz, jboolean setCoexScanMode) +{ + char cmdstr[256]; + + int numWritten = snprintf(cmdstr, sizeof(cmdstr), "DRIVER BTCOEXSCAN-%s", setCoexScanMode ? "START" : "STOP"); + int cmdTooLong = numWritten >= (int)sizeof(cmdstr); + + return (jboolean)!cmdTooLong && doBooleanCommand(cmdstr, "OK"); +} + static jboolean android_net_wifi_saveConfigCommand(JNIEnv* env, jobject clazz) { // Make sure we never write out a value for AP_SCAN other than 1 @@ -503,6 +513,8 @@ static JNINativeMethod gWifiMethods[] = { { "getNumAllowedChannelsCommand", "()I", (void*) android_net_wifi_getNumAllowedChannelsCommand }, { "setBluetoothCoexistenceModeCommand", "(I)Z", (void*) android_net_wifi_setBluetoothCoexistenceModeCommand }, + { "setBluetoothCoexistenceScanModeCommand", "(Z)Z", + (void*) android_net_wifi_setBluetoothCoexistenceScanModeCommand }, { "getRssiCommand", "()I", (void*) android_net_wifi_getRssiCommand }, { "getLinkSpeedCommand", "()I", (void*) android_net_wifi_getLinkSpeedCommand }, { "getMacAddressCommand", "()Ljava/lang/String;", (void*) android_net_wifi_getMacAddressCommand }, diff --git a/core/res/Android.mk b/core/res/Android.mk index 5fca5d011fc1b..cb5524a6dc30b 100644 --- a/core/res/Android.mk +++ b/core/res/Android.mk @@ -24,7 +24,7 @@ LOCAL_CERTIFICATE := platform # since these resources will be used by many apps. LOCAL_AAPT_FLAGS := -x -LOCAL_MODULE_TAGS := user development +LOCAL_MODULE_TAGS := user # Install this alongside the libraries. LOCAL_MODULE_PATH := $(TARGET_OUT_JAVA_LIBRARIES) diff --git a/core/res/res/anim/zoom_ring_enter.xml b/core/res/res/anim/zoom_ring_enter.xml deleted file mode 100644 index 13d89b2f229b2..0000000000000 --- a/core/res/res/anim/zoom_ring_enter.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - diff --git a/core/res/res/anim/zoom_ring_exit.xml b/core/res/res/anim/zoom_ring_exit.xml deleted file mode 100644 index 177a4c31697e3..0000000000000 --- a/core/res/res/anim/zoom_ring_exit.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - diff --git a/core/res/res/drawable-land/statusbar_background.png b/core/res/res/drawable-land/statusbar_background.png index 8ecc24c59add07d130920c12634cdfc79c8577f7..bafa5c5a5196b178444b7b4495c60252b92068a6 100644 GIT binary patch delta 2760 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 + + + + + + + + + + + diff --git a/core/res/res/drawable/btn_circle_disable.png b/core/res/res/drawable/btn_circle_disable.png new file mode 100644 index 0000000000000000000000000000000000000000..33b74a66c07f360cd4590aff32f83aaf3e1db888 GIT binary patch literal 938 zcmV;b16BNqP)Ch-*X{PkvQZF$g)4+z8j?#1k$eZtgP<&%n<7wHTycBK6`QjsyY$my%E1#l=M)S6~l^$KdB=mkUVI zlh(DkxcE_NDQeUw^-T=Ml3mAw)6>%*dU|@?YSk&~n;68BC5C@MGQoj?0k7Iclre&g z*>J?#XJ%&lEEY?v+G4~Y7BMBoU{2M%BODG3yrv$;>R{|AN6bAwJ|1v597bMZ#3Ck} zQJxfYpePuPs$(G%J7Q>>gfRs2qJgoB)W2^*YOO}WD>gsB`R4P5FEkz7s5wqd42j(fHqut$I z)klpnju=x`L5*!}Y#c=*5!D_9>YEtElD)KM*E_PjynGgoMinm~)F<^#jK}wu-0fR0 z(g=1mokK%Iip-%02M2f9d7a~M5A5TA+3X0url_tV4L+8R~%FH|AGyi(-d#iP*+ zBl^b1#$4Ef>HU7c!Rz(v+S=NFixvt6F`Z89lF8%)D!RD6y-lwIz9GIg8l|Si9_`Zo zw244?+3M5APG7TmkLuHRMDnTKw&G&k7iXH7CZ>sLVw#w8?Uw)p01hp0ZAtpRSO5S3 M07*qoM6N<$f@yNRPyhe` literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/btn_circle_disable_focused.png b/core/res/res/drawable/btn_circle_disable_focused.png new file mode 100644 index 0000000000000000000000000000000000000000..005ad8dcaeaeb6f245fe6090282ac10fbdc1c78d GIT binary patch literal 1436 zcmV;N1!MY&P)c(T!WGpB|q7gCE#i?;IF(fW7#z*uI7o#yVGg+3HEt@WT#06u50k<&z zkd4P8ZgIK}feDnBcU$^`zFWVq^fH`VU$n+QdXg_U_uSs^_q(U}-t(PH`Tc(Ke{57z zEGd>0i{>PX62pdpkV2$Dh#&;P!)^#CgdJiL!UhaSvG0FT#0hIAj1pOI$}RI6~P+nsaI!D@&TQ zgo}>|iBk~?z(qu+S(o%$Ti@;TE$62%LDx(qBN$c;q|#n_R9x}VbEOAVV&itc-zAIX zp7BsZtHzOj`QQ)3hfWPRZUA>7W-*XrziObL-cyTaQUpIJY1y zFj)n;Htd(VrGvky>x+EH2l#){DH>bgs`v$+gG&EFZsfk^BgJW5i-0 zmGa^Pr25G7?BNXmosk+(t?BwD_pRPo{>sOuj#d?#uk7UZ4HT`-&1LP6Q{ z@Jg_mrA2dz62sgm6@c>XdAJEBCKGz>>HgpeW{Jv_Ffqu@agd4ZP+}6=>tuYvSKFdw zd74Q?!`$46(S9f1_>xd!Jp3{BAJvYWn4kLh{eJh&?{ZV3Meb3SE>1CtlET~^2bqBi zDTLUPoun9Xmcn4H8bzYSFgM3RCbC0`nGBwk=@l`{SZ2b+AUDTBCbC0`8Ah!9ac(DT zrnfp#VyklpnTAkevnP8s18!Opu;+W0~Ph^=!yQxZVxREyu$=;Yx<^}N2}r`g}E?iU>yJqWFa$b z*#qX2$JL~L*u(zH^<__A*;z7tX7gI5FbC#ZDL#RLEM!Jfk6}}Pa6xy zaV;Z<=VFePrwno<16k27MhadpCwo7vmhWSHmb{hKkw9h~D{ku0DI+U~l)BF1qS4lR z?(YjMMtJhcPkSuKPN>PZz@La^`Bw5;IeF>8c6K-G)tCNboyeD1X0xh#tg@mx8>2EU zNtfqU3B1u6n?@nCj%8-e_EvLGAJ_CWJACM}{@h75IScIDYgzEBw&sx9&l;3_%7pqY ze4itxY0ASB+lE~1_4nI#r>{}CX zZpEKpcTe?y^9N~zE?k9&EvKUT+JmD9o3b4$vh|H8@+&rFc$Mo!j!Y@Br}39d7viBr zwndV%Fz*!4-7?U+<3DR}bZf{}I5ZS)l;ZIj3U6d3L@va-VD%~GO0D3$HxDs|RrLK< q+sQAANwK6@QYQH%r(U??EiYA{8) z$ZFdlH>I`K-gbN0?sj*M|3CB3?#!^WyDgCLu+x4!JLl~Azi<9?&OiS@TnNE#$3tSb z>5&zd6?Ur+#eBgz&vcvzFdHxnPz)#l%%r{vz$jn{FaYQS1T!&eju6TeZ)6T&K4N$C z>+5~K%8K%`*=5DW?pb+xGf*rW9}fqIhDHXib@z4q{THupZ+iDAG+!q4WJ<)%DpPo@ z5U>c~J8^91wk3-f_zFF_;3;FQJr?r#IS>pDojrHSzk1z{&!NE&_#F^P=dnzL-3_Qe zxc{}Ll`E?13i4fUrj1b@MA^kjXqb(TO^&p-b)IV6{9ZFOwgdjU5n&4fE6=pQ_2T0D z=lGb2kszTXKGeZu-1y)mP-f@O_xP9Azx@$3v;r6$wG@Lk(k2N z{xSqw#dUP`U+~qw^8qv*rnQ%`Fx+WRwEy_hj@l)q)tV@Pa9mSqmoj~FO&H?z+1`%& zhdH2;f+tD5h4Uj1l1d!N>2aq2O9vV6FHGP zmB&g-yv(C7_DS*>Ge!AK1f>zkO6QDJ{9XSHQ2qu@|Q~`Fhw=X?P&Lz4x>)qPdj4%^fAegm|zJ3F6+M&pWoRoq)3cGUV{78^Xvc8oOOx6Z7 zE>UJ6(J;MT|D9w5jbSpSI*GAbKQq|}F62b+RKon9?E157U{DQ7vce=3C`lS5+}fPZ z5<;?_&9L>E#>VYoJ8&Qua#GsuC=4^ouC|lI{W1zuWG2g!P9Ve6O*Wmc6D1|NmaSv( z4DFgt&9=gj3pwrCY_df0Q9#ob|Hg(QkI2#EnQD#vNngaINPD<7^5b+$vWpD|d1RjN za0@hI9dIaJqWBZw*Zqh3{*@IMQ(OS@oDNtaij)L0AxR&Oq48)7ZK7@DKrZ6UsC=sj zY(Mbz%FSz56weY`z>Qw_K%Y`-Z9KRo1-`o2@wTCXO;5G%hsNDhHD#3Z<0E1d;OXxV zZdkv(zOax9$~ItHg{2@#r^yIA`fg=hVJF)IfwhfCun_(daDb}!jH{#~EJy&4AN;0a z_4+lli_PNf)sj;h&1|BM9`74!e6r;PbbL#N$nbRPN_;o55%9>z@2}dhb<2EjiPz<_ zh)d?Zc)6Ak)jv2nxo7X?!53cn;RtkmN2S}qja1_3xuvvQmwmQtOI5?V1)jS~^K%l9 zBhyahrV1Q{{nI-ZX*qT&_{?*AvEcX_cOT%4*;CUMW~{kVtjeiysCmArq4I&+dAU_p zb7ssf_vVy%3$%owe{eMV_qD-DXJ=3Nm(y25pEkE(_46Cx6lJKr#+ter!ptvMFrmAT za`Xy78BMu|eiNiA>IPf|bO8Q9%}y^Y~0$^2iuv3@9`-)%RmO o`#L=R;sZopj1nGv5j7+lgpe3yMT#IF z#!?rgK-VqHZlTJD=a_rVFwV@*E<@wPPI59ccV_N6bMEKwmv(%7Z2LbRX(?eTVJTs} zNlP>PoeOvp$Of_iC*Tmz9s)5S0^A2eK-5g7C$uCeEEhNr6buXuTrVvxea7qc7G`B- z|T*w|Pr1U>I`I-fG* zLM#@$2Z2A-*Vp&s_7`A9&%s26YbaHxndZMwh@dMn> z0UM_g_B2p6H8s^yTwGjfMoc`BD=RC3nwpv(TuuYOB_pf=s0{=H?-UgkT~@xAs5oW4 zyk1>hov*B{d>^-yqW_r|#*y~Q3N5{x1 zHVV4J>~bVNDq#u^yOFSi-QC>>E|<&wD4J6C*=RKSfZRsH_Cldh1Vi{AVaj>T>dw!4 z*o-`rliWr#{~y6%FsyV+>6~m{HPmaP-aG16kk{lSw~?^l=jZ1`T4Y*_x89;|RIc?C zp`^`H6a{p)Mx#|a6%L2@5Swmwc6NS` z;#ilQtkg%{+sxu`lB`hT@CCs|xZvh4Xd{=#v_6N+a00000 LNkvXXu0mjfjPhEW literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/btn_circle_pressed.png b/core/res/res/drawable/btn_circle_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..8f40afdfcb30cf7e2f014bba7c03ff2372d539e2 GIT binary patch literal 1613 zcmV-T2D15yP)O9+s$JUDLZP5BfU(#pSbXq@2cJwxgAYVWFfk@Rm>3gDPIgERpe zO{!3+W=pBXluE%;yR==}?sjH(uIJ3&p|jJSooNdR4?D@1{kb#e`|i2to_o$v&N+D$ zFGe2GD|tMS;}1%y)93O5C4gdpACL?1im@nQ8ZZF}0mcAfCq|7K!oA3eJPxQp zw0+v#RQuG5veH$)HU9jp;+$+ZiY2p=Sa>2l7aF-Ub1OJ7KHU1jnNIk7NZ__pB5G8b z#$yG58bIy& zggpUhJpIk~{o5M~H~YLKkEn5y5Ty$v260q3rU}!)Tx2Fn?p^4aytwP_3tz$L?|^@n zBdiLrt+(U3cb~5E){=OP5H&V03dL|@;W7PF7Y9+}a+5y>qrv)?U%r6BF2LYYgkdZ- z_nqEyaDAD(io_M7c?zKka(I+!HmT+{4K9gX9gYpw?E38p44e_M=U5o-v{x^Ezwyw< zC*1)OQw*M3geappeQD8iZi!s}E7rg1wabTL^artnlZ092v1d;nt=_j`9Sv}KmZ(Yu zbj=CK;4}pwJA{&WMt>e`p-r@n9LQyx$HY|$*z!Vyr%nX}1dNk7#*>;Np6onFQ^Xwu z$0x!9Igkr*4e+;}u+8nqDqhKzqCPImgvVnRfzEBj(S@J-hKMslU2&2t#eK-N=fKca zJ7Fs^S2YG`r7A}V#unF712^R>o@Pg;*qKS<5};bl#z|v9!WF6&-2Yh#3w+dC{7j)& z&Qs+%!ZGO0N%a1A^MB@@XcR@0{}UU5!lVnmJP$cPZVUaKPT0D-O1eswql7Cc%(#qJ z;w;2Eo)yGcKp3{VXrZ zDnjmbF}7l59?4e~4j$te0=9yh8kuPUbz=J2w8%peRo zkvp9*H!eFDC(m+(5hubht0j1-S&LcN+~hQm`aLv{bkYN{|z|)0NiK zqZ54AxRdl0#zopn`ppg1j~P7uv&I8H!Kqcfmcqua-{$uSWAoeEDsZ@s2W`DACJ$U1 zXQBkR6n5jv^;np?T##n45`Znu=zN}JB=vVISlqAK)NJF?(f z=$ahW{CGs{2JG!TR?)PziWP807nev>+*pfoOGP5snU)q%6qP)rdr+NfIxvKd@NvK? z(Y-tFk_xdQ0km`+uGrC3@9}d*x$ikG=JcZ>Wj!VeLN@OyDoLcXSDt7&G;|(r=n##_ z(?KaR`1;8&40{KJp^}aQa5g>wQ%`h_x(G;<+GQf;eDTsV8hXkyAN>1 z=&7X&(_?NmcIDWt0P5a(qo}f>+LIk9ld?)nn5VdaX$3)ON{x+-sdE3YGS_oWj(mCI zE;bo|0xpUQbySb32O-S(as>;z_1GT($^dJ`lIM$i!eWVT0fqtn0PKRstzM=)2x0n_ zErj5EF`w|LB*qlskr`1jpwP%--;dGE>-3DUjIfNbjIf7u{V%`(GZqttrg%w600000 LNkvXXu0mjfZ21U! literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/btn_circle_selected.png b/core/res/res/drawable/btn_circle_selected.png new file mode 100644 index 0000000000000000000000000000000000000000..c74fac227a2381ea347e0ee4930b0f60cd00645e GIT binary patch literal 1645 zcmV-z29o)SP)r` z9p1gOv7)f7tkAXI<92$o9ikgASPDk`v;M&B==9=5&&c%X!Ojc6z}Lf|A<$T=j;Nl} zB4T-A~=MAO?_N*r}05+U(Wx@eIEQPaT@Q6zue3HCM}^?nK$Tms#^AFvA0bG;|( z-l;9JRgo}4NhCUaF@jhz?2*Vz$*%!#^6Fh;VjteLOO-?bzT+IQcD~!7*TF>)4ZL4wb#x{1~fdfn~yi z0m8yT!Xl^;D9i<)B@-F1!{4F}v;{WNHu^wcN!KxcRARF4suCJlU`34-4k6QWi5WB2 zBw{o^gp_|TLDZxO*;OSrpfAt>Us5c=wsjpW+Up|0Y!-~b-Ag>#bx=_l{fuO>0Q&Ka zLh^HxKq$buGNf$uweQqaUox;lPx;(5h`J+HIHfjKt?~vW-^TQvP&Rc<1JyC2c zmT?G!d?qqEZsg+LNfJ29Zzv{k0+?p-6(#7CZ*^D9z)H(=s7DTg5fGE$T~4rESuJ4+ zBNqFv{6qjK0Am1+KKVXunqvip4wAzVDh!HPL?_i&ftp1TULwE&82UutR$y+ojXLE3 zK!u1JvHJx|3WyOS3YgnTo#@*NOq3hSs z#w=w#Y1ta0mN4J$Ex70teOr~*{>de_j2AOSBwj@Kt{1zvImAf+n>eXUh~g7`TY*gt z`k0^Duo6%=T}wD>05JPMfep3V0Q(^H$;)t4u-o1VX@Q8a#@J9`M1vC^kSMo_wv`%9 zAc{}$Z3T9t^UCtTbVyjy;Iz9^jA_PgT>8&O8LtyGAT3fV6#7D+=-Vp!2eGQWJW6L? z*_>5I2yRR2CeDnTx3SXD&QTg)QRtR@WgbCAOYK1Hu#?L-r5Rqy4kl|xo(FXdzhBy( zOQj4sgcXJyU$ru`1&*4RKRnqfL`%pJ$vm@#DnA;-JretXv&q`G-$5;1|HxZjZ*rAU z0rpIY8pF+8PO%mtvg{ zp);A87mQYm7+vy)4I`bF|sfT@*&Lc2J8APPfxbu8f9(|H3MVeB=300malC1I1hAN11KhZ@_SsdDGbP@l1g z93581^n0lx$0)a_4Ij)v0Xn2#hx~J|e%6Dn+jqPX@!d~fxenA0+H>-?>fJ9l6?pO; zf}I&6#|#xLrLmF1WS<6@*!YDzsCjH^i#s0a4x4!rr*Q!5wPI(hOCRi<)mUCETK84K+KEvo}FRyHV zJSVeyLzbh|kxDYZmwr-Qn9zKM1>^nPiWn)&iy-nH literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/extract_edit_text.xml b/core/res/res/drawable/extract_edit_text.xml index 9c6c4ba860cdf..c7f66f6b199fe 100644 --- a/core/res/res/drawable/extract_edit_text.xml +++ b/core/res/res/drawable/extract_edit_text.xml @@ -15,7 +15,6 @@ --> - diff --git a/core/res/res/drawable/zoom_ring_thumb_minus_arrow_rotatable.xml b/core/res/res/drawable/ic_btn_round_more.xml similarity index 71% rename from core/res/res/drawable/zoom_ring_thumb_minus_arrow_rotatable.xml rename to core/res/res/drawable/ic_btn_round_more.xml index f2d495b8d4482..82b759337e8f8 100644 --- a/core/res/res/drawable/zoom_ring_thumb_minus_arrow_rotatable.xml +++ b/core/res/res/drawable/ic_btn_round_more.xml @@ -14,9 +14,9 @@ limitations under the License. --> - + + + + diff --git a/core/res/res/drawable/ic_btn_round_more_disabled.png b/core/res/res/drawable/ic_btn_round_more_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..1ab98c985e7ed7411f702e388fc5f83fcd5444cf GIT binary patch literal 421 zcmeAS@N?(olHy`uVBq!ia0vp^YCvqj!3HF2H*shHDajJoh?3y^w370~qErUQl>DSr z1<%~X^wgl##FWaylc_cg42!jIb2)> z?zfaR8>^JuyEcWj+~7^-@Bd}~(Mb|*&HZW;JqID^pNtQO-~r{=21f_M6tNu8SSZGHEobE)Yruq#;bwScef;pzG_FT13| zge2NNc%4|utoS@{%7mbUA&bO+Y;$82=H3u7W$J>+^}ZaP-2Ihbn_Rt5e=Bm?%VNHL zmvC2atrkn;A*NR*g-$-D8&{?(Op$U}dZVK^IX{_|!;NJ{#-!Q18&*~dtqu)8c`2;f zYGt&B%*vU{;$5qYIj`x79*r@4kiPL@R9HgqvhtNl9%=z6m!zLHy^(fa*^~3$$FHuN z6SunyeH3^fzG%Z)#dlw~9>3ka=zDnfzv)L3c#gr)vorUYco@vjT{QK0-O&aNcLq;a KKbLh*2~7ZJE3vHr literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/ic_btn_round_more_normal.png b/core/res/res/drawable/ic_btn_round_more_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..ebdc55c272de3cc483ad90984ef6cef7051b3beb GIT binary patch literal 968 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 diff --git a/core/res/res/drawable/stat_sys_phone_call_bluetooth.png b/core/res/res/drawable/stat_sys_phone_call_bluetooth.png new file mode 100644 index 0000000000000000000000000000000000000000..7abfd194fb800bd11d62b8646b5fd4b3133eccae GIT binary patch literal 815 zcmV+~1JL}5P)P000>X1^@s6#OZ}&0000PbVXQnQ*UN; zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!(Md!>RCwBA{Qv(y1FZoQ104VhjG-P; zYyautm9GDP|Cmu~C?hk=DL#3fvYRWK529GYC8fTCSHVDnTUwognVpMl3;zE6#_;v& zO|!qhzOMjsB~dKl6jzpDM#ex~fUIFn-1}T0vhHa_paPj?jJ~7m7f5Pzj=U;?*7;*CVFVObCC>CglaWXV{ z$iVqE+a57&y!;N#e*Eq`!}Oys7-CFB8Kxh3!LazuYZSfzkjz5(1Q;Lxk>Z4xgPCDo zqzWQpw?1T8f9WlXL6Z(W17ocD#mexX;WxB6Sa|#i!-1QS%=hlgFOn=^ zWoBgfja0M4EfL`7dn&}uD*X`X1DHkk-+U!Ge}F8I735%e$Hw#&!xAGoz7%zFp7}sU t5|q~QKu5l~`SME&yv`psO(K8*0{~U`t)sVGg*gBK002ovPDHLkV1n;9epCPe literal 0 HcmV?d00001 diff --git a/core/res/res/drawable/statusbar_background.png b/core/res/res/drawable/statusbar_background.png index 945ad92ad209b5066482eea63a121f9a45823c54..25a2344cd65da465d79ad4ea65233d6af032bedb 100644 GIT binary patch delta 3037 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 A6aWAK diff --git a/core/res/res/drawable/zoom_ring_arrows.png b/core/res/res/drawable/zoom_ring_arrows.png deleted file mode 100644 index e443de7bfe0b57534a0418c3e9f05d20a9a05985..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4187 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 B5uX46 diff --git a/core/res/res/drawable/zoom_ring_overview_tab.9.png b/core/res/res/drawable/zoom_ring_overview_tab.9.png deleted file mode 100644 index d2658d89cb286d0e5c85c325eefbf956bcece404..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1792 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 diff --git a/core/res/res/drawable/zoom_ring_thumb_minus.png b/core/res/res/drawable/zoom_ring_thumb_minus.png deleted file mode 100644 index faed6743854867983e3459af194b77a6db99cd1d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4NtU=qlmzFem6RtIr7}3C{r-Hu7PImy6>0X{ z@|vzIx!bqPtV?3#%y^OQk(rgv#mUKGXlUdZ^8f$$`Hj83y)(Nfzc%mS56j5P+vOY| w96xh*_w3Gzf~y2xEt$W+&Q2;Jo|#30p?2cWeKp00i_>zopr034=9RR910 diff --git a/core/res/res/drawable/zoom_ring_thumb_minus_arrow.png b/core/res/res/drawable/zoom_ring_thumb_minus_arrow.png deleted file mode 100644 index abe1b8a5de5a65f6414019ddf22d5185300670b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1941 zcmds2`&ZK07AGxZ@@=M$V=o^hmL@qNsbMOlAfe(!N#g@wU7;~w`AT#0=JiooqA2C7 ztD>V0S{a#|HeMO|368Z8f8 z%eD8`I%=?xgi82CU`LSMQ&-+Di;K6#?NZMbzFw1Sw7?AB986qYw+Z1NeYTMCp|)mu z6k)atQ1$<`oKNH)xxBENnRfSASZmC`qw{kdOx z#Po(;4?=~(xF;Z(Q!)39qwc+s`~WrGXTnR&kI)M6>Xd93u~UagJwKI+b?e!wOKElX zv?E{+NdjT~V!Z6JB+n*SxpE7HTR!BelNggAY@woi9Sm_kSB;;Gp)S&3v9RKq3>Ld# zdO0Tui!nvhM&x%Qw6vdgbgXpGAf);O2_HzuYD>-!IdD>vlX^Ow|ySrW3r{@QMgLLh6pNE(TZ($l_7SLtazFm4^%TLIA$55cm>(N z+rWGf;HxBC^jV?>uLytsb{ogMVmD9}A^QyuhlicwX1RlNMRoSW$C)VV*@rwL7GuSu z4Mi)BasQ4=|NKc%aSztMs@}fNP4uY2U#aEn7$^|M_DmGiuD-thHE;K!CK3yIm9?Eo zvu)q%(`+J&n{CACkFgCb$*k3^wRh_tc3dLJeY#5y`K z8)pz^%<+E`NuGdx9&bz8?9)&>*4lb;b91x#d#7Xaq!6dj?r+OP_6PUh#4-tCC_afA z4#FHQID2?-B37u~pCh0NX>(=~TWL4Eu~K2i~GRMMHx4#UONdKn(_*y!)eGqtfU z6^aAy78sX6sf#Nl#oT>Zn=lhaU9`nmlN7zZJgy!{!MCRoa*w%@b3wV6r z4TX?Z8+68P)`c}4pR?qt{Y+DSsKmVmglzL)Q)f4e6a)u)bar;=3tI^*MJaC8Tn>k0Xl`akbP9X@DHxV}##DzrFZhcRAFou4+QT)+=+=zgD^Q(N)i2?e`pv}F=UrV;vc*nDX6BY} z=XGhHe;#-?&~p6H3|V`U!j4W(4hE)(v+|n1v9Tc!Zo+SW9;P4HZ}D-SX9PeW0+VgD z`yFtPO7*9(AE(z`N()_APEAcQ>2$iu#iNXrQ5z*=p3+9ZW=Si6{z)W~=N%n3y{lsM$ z<_T6j;@BiWX@f{nDBL>P^}Vupetupm?Mj||a1YVX0lCL^ix@S9_h&Bu%h^=A&J-yy zO~03<_Bd|e@`Q8C&inf2Brm*wCdCH?XreMQHnq<`j*$I$&}A`eK6~rz(Rs)1S~oAF zf+h94rS zmoyxf6R>D5BNATe7}GJS8XWYCOG;ARLe^>|W0kIHUyo@Fk)bL*x161<%$;$!;$VLC zDH(#l_YtnKbST<#^4d#Tx6(#*!!@aEO8Nf%<*3NWy2RB#Ckh1G|I^p<_qCJpE;#NJ RazWsi_ZT!D)#e?M`(OWyLB9Y1 diff --git a/core/res/res/drawable/zoom_ring_thumb_plus.png b/core/res/res/drawable/zoom_ring_thumb_plus.png deleted file mode 100644 index ba7aff2318347f12ccbf88208055097635cd02ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 317 zcmV-D0mA-?P){*Q&>7A3wvXkcXScUr|T#y1at?VIUW-kO^HOzX1P#IXO9&=Z~MWA&WDD+$gUq zzmwrVg9;Zn*DrA?@y|-?O79;(c+B_e`72&=S@Cnb*6fM{TkYuW_}0{k(zjq1p3vvnz3NHrQb`hxg z9oTM=)yO!jH0$oV9qS&f-?`owSscSNS~^;ffu=oWVP^S=;Td88K!5=N92aG}4l7Kp P00000NkvXXu0mjfq+g1$ diff --git a/core/res/res/drawable/zoom_ring_thumb_plus_arrow.png b/core/res/res/drawable/zoom_ring_thumb_plus_arrow.png deleted file mode 100644 index d01ccb4342ab31915ada8ac91568e028b5b85071..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2272 zcmb`JeK-^B9><-IYDGzV5LUDmle|x!WqEtBXykPfBQNvPls1kf8&8^3BP*xUXr+=- zjI`LJ7fQ7eW5syP%baAy=$UzmF=zhLzvo=%y6(??fB(Bb*Y9`V*L_p{e39F>8f;Zl zQ`_cs)IC78O4a~uQq6BqFTPYQ`l%ivse#FHsl+G(R?RgwIT~y1btWnv8-R_9O~047OD)PEyey;vCF{h(~L44U@Fc$2G_ZcKAN3dp`4n~bN*J!dz? zMB7?Q9_kGpr0*I_jX+rzUe!RpvhHJY-|x_CftkeZ+PD2^p+&F=>?iu|fuHvSr{mxD zUS|H`76zIcyRl5TAi5U_9cz;-N|eWsK_HNgf5~h+Ick(G0N~H;FaZG9F-Gk$S;vKL zj9TY+YghU@e~ZetUS~tIdel!)wlu4+^S^Frj1q77S!XS;>#XH>a-YI&ulWt&MTtD!xKiJM;RN#FP{^l1)wjo+nUh z2g<1v!{82<_81Pocrtv@FuCbg0eX^cl_|i2_>@sJQ5pg(Pk<-mvcc_%sdE!TS}P?~C!w0vz-J}> zW5j7Fx4+2@MS+vU`e?GSzSg8H2=`&Qr5*-@alDX`L4?6zpb*a4!AmR_YmW~g6fMG5~7krm38)K71wz(2&a5*jbEaMm|h4w z$8Wur5eS)`fKkbX#qvnRt!*wdqge|Z&7);thEfm37JKR$8Fd=&`a3uzfAC?VPj z)ne{aFlpRDX74#OBJ2+@0Jl@$N&g@%5r zKJ8>cTqK3Bu4Hf2h`0uIt{9S_!E-5o6nI=h!gwT)w%eR$G<&l_f?&2yg@ZqB3_Y=EhDeZaR4*#DtiZ?vkv(ebw#D6rRgGRpw=$wyr;S| zl{)W@5?IACY>t>)-Mcr_+v<{H%Ucm5uWKP6Y4NZ`_odsKFm$7fqC^(|<2V*~#Q(nV zK`xrkMiYrd|H#NyzC~EQ6w^S!`f_-X&qmucHA$u;;V)7X3*r}0NQSU~0Ku{XV|Keb z-8J8E#Aq_Ms^k2scx2`%iNBCLS+fed0=O)f;EPNtP{MX7e=ci`teDq1R(Mc=RtI;?&~PfBiz5koK`16$(X@(G9k} zSS%1&8?+8??QUzOz)gK--*i%M0&Qtlo1+aC0U)BXn$4Ey5E_<)P@N)dTcJ;z9mlxc zk$zNP{3N)N;N57%yBC>fF?|CMS|X`0W}ZXm}5+RV5S))(f}N!kFVIf$=JO*z`Q z61lny4HAi@Z1Jm~Qg>FfTit_BT-;?@V!@Am0=hWwep6MSNL5dqd%L>iv8Ya+#o7rM zAJvh$1Z1D&q9Y@nm%=oob2E4NXFB#&;+Gfm>5n>L_V#sO)iJNm%f=~u`o>)A_;b-T zEm+B2evIIXZ19SFkp8fSfk>aJ)E@7kGfG;v6q`c7>bo;lj&G^(2<4yqI5ql-INW5d zs!4j_&yhFVM&rTVHN5WSa8%F!#kLoO+_*>SCIv^eC7P&qYAmCHpU;vuJT+||0A9>A zV~+n;TaSEH(rH>i$d!yq&<>`FT#FzIJRg_>Zg|bN%ORLMT3i2>hWf;T2u8;`OIA}) zoaikz^<|tt_%PfEnCj~L$y=bG=-c(tEInF>X&vvvy#=%#!QpU@z=C^JuO;6qBhN<* z3-j|%J9(vAp1BK;v;aha!xg4|h$D|vO>Vf9Cipmo;dkjDz zgh(vTf`Q4hFCX&ww=FSC(i{!F`uDLIXItB6mS>+iJ$&ixR@LT`QY`tXcwFUO0qC-k zz$%to_V?!Mn9pEOk+mn@0%lLCpM3u$PgsmgNPw2E#JVdU|412fKp+MTRtpa1*O8>0 zJym(wqzo@&Eato#QFZ->7|)G!~jxF}zh@7Bw#qU-xRaQ`!FkT|Fcq diff --git a/core/res/res/drawable/zoom_ring_thumb_plus_arrow_rotatable.xml b/core/res/res/drawable/zoom_ring_thumb_plus_arrow_rotatable.xml deleted file mode 100644 index b77eaa4090c18..0000000000000 --- a/core/res/res/drawable/zoom_ring_thumb_plus_arrow_rotatable.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - diff --git a/core/res/res/drawable/zoom_ring_track.png b/core/res/res/drawable/zoom_ring_track.png deleted file mode 100644 index 1d5a44cd8bcc6ee852c652bdb3327c5aeffc61b8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17749 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 SHNYc<7(8A5T-G@yGywn=GTfg4 diff --git a/core/res/res/drawable/zoom_ring_trail.xml b/core/res/res/drawable/zoom_ring_trail.xml deleted file mode 100644 index 08931ac5aafc1..0000000000000 --- a/core/res/res/drawable/zoom_ring_trail.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - diff --git a/core/res/res/layout/preferences.xml b/core/res/res/layout/preferences.xml index e6876ff862ef2..f0c253543c175 100644 --- a/core/res/res/layout/preferences.xml +++ b/core/res/res/layout/preferences.xml @@ -19,7 +19,8 @@ + android:background="@drawable/btn_circle" + android:src="@drawable/ic_btn_round_more" /> diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml index 18a13554dc74d..81fd87d0d4713 100644 --- a/core/res/res/values/arrays.xml +++ b/core/res/res/values/arrays.xml @@ -65,13 +65,6 @@ @drawable/spinner_dropdown_background @drawable/title_bar @drawable/title_bar_shadow - @drawable/zoom_ring_arrows - @drawable/zoom_ring_overview_tab - @drawable/zoom_ring_thumb - @drawable/zoom_ring_thumb_minus_arrow_rotatable - @drawable/zoom_ring_thumb_plus_arrow_rotatable - @drawable/zoom_ring_track - @drawable/zoom_ring_track_absolute @drawable/indicator_code_lock_drag_direction_green_up @drawable/indicator_code_lock_drag_direction_red_up diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 30b26fa09c3a4..5fa5f8d8b4095 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -371,8 +371,6 @@ - - @@ -585,29 +583,34 @@ - + + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index 9f4d82e22372c..54eba629a58a5 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -144,11 +144,6 @@ @anim/search_bar_exit - - - - diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml index bde6b2acde55c..01c46de1e5dc2 100644 --- a/core/res/res/values/themes.xml +++ b/core/res/res/values/themes.xml @@ -162,7 +162,6 @@ @android:style/Widget.TextView.SpinnerItem @android:style/TextAppearance.Widget.DropDownHint @android:style/Widget.KeyboardView - @android:style/Widget.ZoomRing @android:style/Preference.PreferenceScreen diff --git a/data/etc/Android.mk b/data/etc/Android.mk index 4b5464f5e26dc..a32d8ea8db36b 100644 --- a/data/etc/Android.mk +++ b/data/etc/Android.mk @@ -21,7 +21,7 @@ include $(CLEAR_VARS) LOCAL_MODULE := platform.xml -LOCAL_MODULE_TAGS := user development +LOCAL_MODULE_TAGS := user LOCAL_MODULE_CLASS := ETC diff --git a/data/sounds/Android.mk b/data/sounds/Android.mk deleted file mode 100644 index 9e3697f258483..0000000000000 --- a/data/sounds/Android.mk +++ /dev/null @@ -1,240 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -# don't understand what's wrong here... bs -# -#copy_from := $(wildcard $(LOCAL_PATH)/*.mp3) -#copy_to := $(addprefix $(TARGET_OUT)/sounds/,$(patsubst $(LOCAL_PATH)/%,%,$(copy_from))) -# -#$(copy_to) : PRIVATE_MODULE := sounds -#$(copy_to) : $(TARGET_OUT)/sounds/% : $(LOCAL_PATH)/% | $(ACP) -# $(transform-prebuilt-to-target) -# -#ALL_PREBUILT += $(copy_to) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/notifications/F1_MissedCall.ogg -$(TARGET_OUT)/media/audio/notifications/F1_MissedCall.ogg : $(LOCAL_PATH)/F1_MissedCall.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/notifications/F1_New_MMS.ogg -$(TARGET_OUT)/media/audio/notifications/F1_New_MMS.ogg : $(LOCAL_PATH)/F1_New_MMS.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/notifications/F1_New_SMS.ogg -$(TARGET_OUT)/media/audio/notifications/F1_New_SMS.ogg : $(LOCAL_PATH)/F1_New_SMS.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/alarms/Alarm_Buzzer.ogg -$(TARGET_OUT)/media/audio/alarms/Alarm_Buzzer.ogg : $(LOCAL_PATH)/Alarm_Buzzer.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/alarms/Alarm_Beep_01.ogg -$(TARGET_OUT)/media/audio/alarms/Alarm_Beep_01.ogg : $(LOCAL_PATH)/Alarm_Beep_01.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/alarms/Alarm_Beep_02.ogg -$(TARGET_OUT)/media/audio/alarms/Alarm_Beep_02.ogg : $(LOCAL_PATH)/Alarm_Beep_02.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/alarms/Alarm_Classic.ogg -$(TARGET_OUT)/media/audio/alarms/Alarm_Classic.ogg : $(LOCAL_PATH)/Alarm_Classic.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/alarms/Alarm_Beep_03.ogg -$(TARGET_OUT)/media/audio/alarms/Alarm_Beep_03.ogg : $(LOCAL_PATH)/Alarm_Beep_03.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/alarms/Alarm_Rooster_02.ogg -$(TARGET_OUT)/media/audio/alarms/Alarm_Rooster_02.ogg : $(LOCAL_PATH)/Alarm_Rooster_02.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/Ring_Classic_02.ogg -$(TARGET_OUT)/media/audio/ringtones/Ring_Classic_02.ogg : $(LOCAL_PATH)/Ring_Classic_02.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/Ring_Digital_02.ogg -$(TARGET_OUT)/media/audio/ringtones/Ring_Digital_02.ogg : $(LOCAL_PATH)/Ring_Digital_02.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/Ring_Synth_04.ogg -$(TARGET_OUT)/media/audio/ringtones/Ring_Synth_04.ogg : $(LOCAL_PATH)/Ring_Synth_04.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/Ring_Synth_02.ogg -$(TARGET_OUT)/media/audio/ringtones/Ring_Synth_02.ogg : $(LOCAL_PATH)/Ring_Synth_02.ogg | $(ACP) - $(transform-prebuilt-to-target) - -# -# --- New Wave Labs ringtones -# -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/BeatPlucker.ogg -$(TARGET_OUT)/media/audio/ringtones/BeatPlucker.ogg : $(LOCAL_PATH)/newwavelabs/BeatPlucker.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/BentleyDubs.ogg -$(TARGET_OUT)/media/audio/ringtones/BentleyDubs.ogg : $(LOCAL_PATH)/newwavelabs/BentleyDubs.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/BirdLoop.ogg -$(TARGET_OUT)/media/audio/ringtones/BirdLoop.ogg : $(LOCAL_PATH)/newwavelabs/BirdLoop.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/CaribbeanIce.ogg -$(TARGET_OUT)/media/audio/ringtones/CaribbeanIce.ogg : $(LOCAL_PATH)/newwavelabs/CaribbeanIce.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/CurveBall.ogg -$(TARGET_OUT)/media/audio/ringtones/CurveBall.ogg : $(LOCAL_PATH)/newwavelabs/CurveBall.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/EtherShake.ogg -$(TARGET_OUT)/media/audio/ringtones/EtherShake.ogg : $(LOCAL_PATH)/newwavelabs/EtherShake.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/FriendlyGhost.ogg -$(TARGET_OUT)/media/audio/ringtones/FriendlyGhost.ogg : $(LOCAL_PATH)/newwavelabs/FriendlyGhost.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/GameOverGuitar.ogg -$(TARGET_OUT)/media/audio/ringtones/GameOverGuitar.ogg : $(LOCAL_PATH)/newwavelabs/GameOverGuitar.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/Growl.ogg -$(TARGET_OUT)/media/audio/ringtones/Growl.ogg : $(LOCAL_PATH)/newwavelabs/Growl.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/InsertCoin.ogg -$(TARGET_OUT)/media/audio/ringtones/InsertCoin.ogg : $(LOCAL_PATH)/newwavelabs/InsertCoin.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/LoopyLounge.ogg -$(TARGET_OUT)/media/audio/ringtones/LoopyLounge.ogg : $(LOCAL_PATH)/newwavelabs/LoopyLounge.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/LoveFlute.ogg -$(TARGET_OUT)/media/audio/ringtones/LoveFlute.ogg : $(LOCAL_PATH)/newwavelabs/LoveFlute.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/MidEvilJaunt.ogg -$(TARGET_OUT)/media/audio/ringtones/MidEvilJaunt.ogg : $(LOCAL_PATH)/newwavelabs/MidEvilJaunt.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/MildlyAlarming.ogg -$(TARGET_OUT)/media/audio/ringtones/MildlyAlarming.ogg : $(LOCAL_PATH)/newwavelabs/MildlyAlarming.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/NewPlayer.ogg -$(TARGET_OUT)/media/audio/ringtones/NewPlayer.ogg : $(LOCAL_PATH)/newwavelabs/NewPlayer.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/Noises1.ogg -$(TARGET_OUT)/media/audio/ringtones/Noises1.ogg : $(LOCAL_PATH)/newwavelabs/Noises1.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/Noises2.ogg -$(TARGET_OUT)/media/audio/ringtones/Noises2.ogg : $(LOCAL_PATH)/newwavelabs/Noises2.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/Noises3.ogg -$(TARGET_OUT)/media/audio/ringtones/Noises3.ogg : $(LOCAL_PATH)/newwavelabs/Noises3.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/OrganDub.ogg -$(TARGET_OUT)/media/audio/ringtones/OrganDub.ogg : $(LOCAL_PATH)/newwavelabs/OrganDub.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/RomancingTheTone.ogg -$(TARGET_OUT)/media/audio/ringtones/RomancingTheTone.ogg : $(LOCAL_PATH)/newwavelabs/RomancingTheTone.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/SitarVsSitar.ogg -$(TARGET_OUT)/media/audio/ringtones/SitarVsSitar.ogg : $(LOCAL_PATH)/newwavelabs/SitarVsSitar.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/SpringyJalopy.ogg -$(TARGET_OUT)/media/audio/ringtones/SpringyJalopy.ogg : $(LOCAL_PATH)/newwavelabs/SpringyJalopy.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/Terminated.ogg -$(TARGET_OUT)/media/audio/ringtones/Terminated.ogg : $(LOCAL_PATH)/newwavelabs/Terminated.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/TwirlAway.ogg -$(TARGET_OUT)/media/audio/ringtones/TwirlAway.ogg : $(LOCAL_PATH)/newwavelabs/TwirlAway.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/VeryAlarmed.ogg -$(TARGET_OUT)/media/audio/ringtones/VeryAlarmed.ogg : $(LOCAL_PATH)/newwavelabs/VeryAlarmed.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ringtones/World.ogg -$(TARGET_OUT)/media/audio/ringtones/World.ogg : $(LOCAL_PATH)/newwavelabs/World.ogg | $(ACP) - $(transform-prebuilt-to-target) -# -# --- New Wave Labs notifications -# -ALL_PREBUILT += $(TARGET_OUT)/media/audio/notifications/CaffeineSnake.ogg -$(TARGET_OUT)/media/audio/notifications/CaffeineSnake.ogg : $(LOCAL_PATH)/newwavelabs/CaffeineSnake.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/notifications/DearDeer.ogg -$(TARGET_OUT)/media/audio/notifications/DearDeer.ogg : $(LOCAL_PATH)/newwavelabs/DearDeer.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/notifications/DontPanic.ogg -$(TARGET_OUT)/media/audio/notifications/DontPanic.ogg : $(LOCAL_PATH)/newwavelabs/DontPanic.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/notifications/Highwire.ogg -$(TARGET_OUT)/media/audio/notifications/Highwire.ogg : $(LOCAL_PATH)/newwavelabs/Highwire.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/notifications/KzurbSonar.ogg -$(TARGET_OUT)/media/audio/notifications/KzurbSonar.ogg : $(LOCAL_PATH)/newwavelabs/KzurbSonar.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/notifications/OnTheHunt.ogg -$(TARGET_OUT)/media/audio/notifications/OnTheHunt.ogg : $(LOCAL_PATH)/newwavelabs/OnTheHunt.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/notifications/Voila.ogg -$(TARGET_OUT)/media/audio/notifications/Voila.ogg : $(LOCAL_PATH)/newwavelabs/Voila.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/notifications/Beat_Box_Android.ogg -$(TARGET_OUT)/media/audio/notifications/Beat_Box_Android.ogg : $(LOCAL_PATH)/notifications/Beat_Box_Android.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/notifications/Heaven.ogg -$(TARGET_OUT)/media/audio/notifications/Heaven.ogg : $(LOCAL_PATH)/notifications/Heaven.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/notifications/TaDa.ogg -$(TARGET_OUT)/media/audio/notifications/TaDa.ogg : $(LOCAL_PATH)/notifications/TaDa.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/notifications/Tinkerbell.ogg -$(TARGET_OUT)/media/audio/notifications/Tinkerbell.ogg : $(LOCAL_PATH)/notifications/Tinkerbell.ogg | $(ACP) - $(transform-prebuilt-to-target) - -# UI effects -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ui/Effect_Tick.ogg -$(TARGET_OUT)/media/audio/ui/Effect_Tick.ogg : $(LOCAL_PATH)/effects/Effect_Tick.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ui/KeypressStandard.ogg -$(TARGET_OUT)/media/audio/ui/KeypressStandard.ogg : $(LOCAL_PATH)/effects/KeypressStandard.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ui/KeypressSpacebar.ogg -$(TARGET_OUT)/media/audio/ui/KeypressSpacebar.ogg : $(LOCAL_PATH)/effects/KeypressSpacebar.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ui/KeypressDelete.ogg -$(TARGET_OUT)/media/audio/ui/KeypressDelete.ogg : $(LOCAL_PATH)/effects/KeypressDelete.ogg | $(ACP) - $(transform-prebuilt-to-target) - -ALL_PREBUILT += $(TARGET_OUT)/media/audio/ui/KeypressReturn.ogg -$(TARGET_OUT)/media/audio/ui/KeypressReturn.ogg : $(LOCAL_PATH)/effects/KeypressReturn.ogg | $(ACP) - $(transform-prebuilt-to-target) - diff --git a/data/sounds/OriginalAudio.mk b/data/sounds/OriginalAudio.mk new file mode 100644 index 0000000000000..87229838253a6 --- /dev/null +++ b/data/sounds/OriginalAudio.mk @@ -0,0 +1,68 @@ +# +# Original audio package that shipped on G1 +# +# This file is included from core.mk so that all devices will have these sounds +# +# TODO: Clean up for future releases +# + +LOCAL_PATH:= frameworks/base/data/sounds + +PRODUCT_COPY_FILES += \ + $(LOCAL_PATH)/F1_MissedCall.ogg:system/media/audio/notifications/F1_MissedCall.ogg \ + $(LOCAL_PATH)/F1_New_MMS.ogg:system/media/audio/notifications/F1_New_MMS.ogg \ + $(LOCAL_PATH)/F1_New_SMS.ogg:system/media/audio/notifications/F1_New_SMS.ogg \ + $(LOCAL_PATH)/Alarm_Buzzer.ogg:system/media/audio/alarms/Alarm_Buzzer.ogg \ + $(LOCAL_PATH)/Alarm_Beep_01.ogg:system/media/audio/alarms/Alarm_Beep_01.ogg \ + $(LOCAL_PATH)/Alarm_Beep_02.ogg:system/media/audio/alarms/Alarm_Beep_02.ogg \ + $(LOCAL_PATH)/Alarm_Classic.ogg:system/media/audio/alarms/Alarm_Classic.ogg \ + $(LOCAL_PATH)/Alarm_Beep_03.ogg:system/media/audio/alarms/Alarm_Beep_03.ogg \ + $(LOCAL_PATH)/Alarm_Rooster_02.ogg:system/media/audio/alarms/Alarm_Rooster_02.ogg \ + $(LOCAL_PATH)/Ring_Classic_02.ogg:system/media/audio/ringtones/Ring_Classic_02.ogg \ + $(LOCAL_PATH)/Ring_Digital_02.ogg:system/media/audio/ringtones/Ring_Digital_02.ogg \ + $(LOCAL_PATH)/Ring_Synth_04.ogg:system/media/audio/ringtones/Ring_Synth_04.ogg \ + $(LOCAL_PATH)/Ring_Synth_02.ogg:system/media/audio/ringtones/Ring_Synth_02.ogg \ + $(LOCAL_PATH)/newwavelabs/BeatPlucker.ogg:system/media/audio/ringtones/BeatPlucker.ogg \ + $(LOCAL_PATH)/newwavelabs/BentleyDubs.ogg:system/media/audio/ringtones/BentleyDubs.ogg \ + $(LOCAL_PATH)/newwavelabs/BirdLoop.ogg:system/media/audio/ringtones/BirdLoop.ogg \ + $(LOCAL_PATH)/newwavelabs/CaribbeanIce.ogg:system/media/audio/ringtones/CaribbeanIce.ogg \ + $(LOCAL_PATH)/newwavelabs/CurveBall.ogg:system/media/audio/ringtones/CurveBall.ogg \ + $(LOCAL_PATH)/newwavelabs/EtherShake.ogg:system/media/audio/ringtones/EtherShake.ogg \ + $(LOCAL_PATH)/newwavelabs/FriendlyGhost.ogg:system/media/audio/ringtones/FriendlyGhost.ogg \ + $(LOCAL_PATH)/newwavelabs/GameOverGuitar.ogg:system/media/audio/ringtones/GameOverGuitar.ogg \ + $(LOCAL_PATH)/newwavelabs/Growl.ogg:system/media/audio/ringtones/Growl.ogg \ + $(LOCAL_PATH)/newwavelabs/InsertCoin.ogg:system/media/audio/ringtones/InsertCoin.ogg \ + $(LOCAL_PATH)/newwavelabs/LoopyLounge.ogg:system/media/audio/ringtones/LoopyLounge.ogg \ + $(LOCAL_PATH)/newwavelabs/LoveFlute.ogg:system/media/audio/ringtones/LoveFlute.ogg \ + $(LOCAL_PATH)/newwavelabs/MidEvilJaunt.ogg:system/media/audio/ringtones/MidEvilJaunt.ogg \ + $(LOCAL_PATH)/newwavelabs/MildlyAlarming.ogg:system/media/audio/ringtones/MildlyAlarming.ogg \ + $(LOCAL_PATH)/newwavelabs/NewPlayer.ogg:system/media/audio/ringtones/NewPlayer.ogg \ + $(LOCAL_PATH)/newwavelabs/Noises1.ogg:system/media/audio/ringtones/Noises1.ogg \ + $(LOCAL_PATH)/newwavelabs/Noises2.ogg:system/media/audio/ringtones/Noises2.ogg \ + $(LOCAL_PATH)/newwavelabs/Noises3.ogg:system/media/audio/ringtones/Noises3.ogg \ + $(LOCAL_PATH)/newwavelabs/OrganDub.ogg:system/media/audio/ringtones/OrganDub.ogg \ + $(LOCAL_PATH)/newwavelabs/RomancingTheTone.ogg:system/media/audio/ringtones/RomancingTheTone.ogg \ + $(LOCAL_PATH)/newwavelabs/SitarVsSitar.ogg:system/media/audio/ringtones/SitarVsSitar.ogg \ + $(LOCAL_PATH)/newwavelabs/SpringyJalopy.ogg:system/media/audio/ringtones/SpringyJalopy.ogg \ + $(LOCAL_PATH)/newwavelabs/Terminated.ogg:system/media/audio/ringtones/Terminated.ogg \ + $(LOCAL_PATH)/newwavelabs/TwirlAway.ogg:system/media/audio/ringtones/TwirlAway.ogg \ + $(LOCAL_PATH)/newwavelabs/VeryAlarmed.ogg:system/media/audio/ringtones/VeryAlarmed.ogg \ + $(LOCAL_PATH)/newwavelabs/World.ogg:system/media/audio/ringtones/World.ogg \ + $(LOCAL_PATH)/newwavelabs/CaffeineSnake.ogg:system/media/audio/notifications/CaffeineSnake.ogg \ + $(LOCAL_PATH)/newwavelabs/DearDeer.ogg:system/media/audio/notifications/DearDeer.ogg \ + $(LOCAL_PATH)/newwavelabs/DontPanic.ogg:system/media/audio/notifications/DontPanic.ogg \ + $(LOCAL_PATH)/newwavelabs/Highwire.ogg:system/media/audio/notifications/Highwire.ogg \ + $(LOCAL_PATH)/newwavelabs/KzurbSonar.ogg:system/media/audio/notifications/KzurbSonar.ogg \ + $(LOCAL_PATH)/newwavelabs/OnTheHunt.ogg:system/media/audio/notifications/OnTheHunt.ogg \ + $(LOCAL_PATH)/newwavelabs/Voila.ogg:system/media/audio/notifications/Voila.ogg \ + $(LOCAL_PATH)/notifications/Beat_Box_Android.ogg:system/media/audio/notifications/Beat_Box_Android.ogg \ + $(LOCAL_PATH)/notifications/Heaven.ogg:system/media/audio/notifications/Heaven.ogg \ + $(LOCAL_PATH)/notifications/TaDa.ogg:system/media/audio/notifications/TaDa.ogg \ + $(LOCAL_PATH)/notifications/Tinkerbell.ogg:system/media/audio/notifications/Tinkerbell.ogg \ + $(LOCAL_PATH)/effects/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg \ + $(LOCAL_PATH)/effects/KeypressStandard.ogg:system/media/audio/ui/KeypressStandard.ogg \ + $(LOCAL_PATH)/effects/KeypressSpacebar.ogg:system/media/audio/ui/KeypressSpacebar.ogg \ + $(LOCAL_PATH)/effects/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg \ + $(LOCAL_PATH)/effects/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg \ + $(LOCAL_PATH)/newwavelabs/CrazyDream.ogg:system/media/audio/ringtones/CrazyDream.ogg \ + $(LOCAL_PATH)/newwavelabs/DreamTheme.ogg:system/media/audio/ringtones/DreamTheme.ogg diff --git a/data/sounds/effects/KeypressDelete.ogg b/data/sounds/effects/KeypressDelete.ogg index b35ea65b17a7b3812275e4c644b7010856544cc3..738f6aea72f713cafb4decbdecb32fb55da418e4 100644 GIT binary patch delta 2345 zcmV+^3D)-JGqEsMPiJRS00IC200000001VHf_ne}004%vz)Arg0d{Y4Vrg>#00002 zM63V+000000CxcZ00000xB*XRXHx(G0000000000CY6GF0RR91rI47<5Mq&5Hy8l` z001!n003cfbZK*RJwtDBd2(rIXmqi+qz(ZLlUxrS0RWSF4>^Ao9RL6T0000cm4bT$ z0002lrh5VvL_a+`Dm6n!{{k>RK|}u-@b1>1C!|WVOXR&(wgh6_+jNWoHHz%Hdd|4GL}9+*Y@-C^Z)<t8S^*N0why^7i_Rg zyG^3N2N(h)zEyt!D+a8dR#+T}zr4Np*bMuzcE@<+lY1u1T_5>!p5NrQ#W6A*qoVIW zn|oYH11#GKIP7BBPKCr3K0xRP;T&*6_t?E`U>?>c+m53(CEkup&&!u|+o<^Ug*Hh- z_o}a*cA&p{#ZyT)WeptNG5{ujZdV+bd;wxIWv3E&`ICRZf}V9oWr_Ux2J;wI&aTIJ zS+3Hx{*rcVAn%E-Bnlc}@EIdb)0>$e);O8Uek5Qk4Dq?8H|6Erc?5FT}e|ydhv#1P8~GziUkje z=2#O9VD(Bo1e#$%2{QnJ$PWNurZodg<1x(S<4B(V(Pnd}B_Y7K$;7`GOz(GAlu8fe z4LPsBXwfrYwP>*|J+Y=JR6VOxUS>)68O$eG$uJs@R&-&th;-2P-kEqkG71&l7l;~2 zkCT6PJkTZ$ut++R&0?P9K5a6O>AY0Nq|pi2fZ?P~BO1ua?DDK7A@)@VM+(HAcG_A3<2!Cg&CPUFn@A3XRHH-rIb4ylsj?%+`iL6tp zaT*RNfLlw5G>YyS=sg=Pov1#u_A|ceHI{#3ztvP=$J3-+-*~2?#Yb%gm;h8?4>_1> z>)DRX0|3E7r^^5jFO-$j_7tNGN7HYA@|uR5No@YB+SS&&btI>p`xsPTUpeWt^>+vR z0U8hoI9&#qUVn>#FI{!aFqu@xW;q#_hmPx^hUo7`dP9;nGV?tw8!xi2Z7S6?^s2DND`Dt|gk9iXTefNE?PAJ0*Z?ANYHBZmk z!RQ~2xbz?O-+Dfx4=sP%5b`sT zkB0Ecz<2*Eo*~WCWtq#cTmG9&V?&gEd!IH+(DXP-$%>S)TQnPyB1D6sX7G^)HDzUq zxzk}0iL^<^B(FpB>O9cJqAp3`w`rY+0vcomGQ_#(K=pMA!|Meb^vfF4Q`U>Gx|Y1U(bX##^F^J*C(l?rTs3-;4VlSa}Y)9fqDRZ^kPiKUuxXwEb=q@*3X zH23~06$do;YVWuPG#yUS;LUsQ@^0BcNt!`XFD(F2i{Q|=o!WfFocuFFH{=3>_qOb| zjfA&%GQ8dU^4$Yi%PfBrkND+14jhDJ)`qqz0Q?7m06zNkeO67(#yosSZlmER{(P-3d{a zjiww&NHZ>Lkg68BF-;7`c_3D^K^t9EfK-aq8I9ev?PVeDZppsUq}jCCe~-{;_R24f?QnvC;XA3Gh!iFq@o5z?XQ zvMx{sq|43FW*iuYLlkMC8JFfvrD+hFrbmGkZ*eEQ^h|$%6wP=v#hIp{X>2lH+-CP? z969b`YM{erGNyQkhhkm{;{kCGOltGiy&3n$36Mazr~jjRh^jW}G;dFkq3KdXSMxrAF5^&A^fbFy=E>PiJRS00IC200000002ltYY+ec004sWRN(<00d{Y4Vrg>#00002 zM63V+00000K$Zaj00000xB*XRXHx(G0000000000NJMK80RR918;4ky5Ok4NH!1=E z000yK004ApbZlikOJ#X*a%FRKL}hGcbY&|5003cfbZK*RJt$)-v8ALA0S%K%4;=x3 zlV}e)e~2Ie0000007yh@5CQ-I0O-%4p|93yvYmAf<$Mt_iw(76R)E_gYK10+yLI9jdFLwn2I+Z@{ ze+nWteZW-#@XfD2`r+e$y7>6ZE^KUy${o7>_IUq@B)Ffxi>y2v*9DZslz@{sjot!` z1uVOJYL~ z2mx!(n1vWsp!U(B^Jh;xKfR{iC;5?Ff0_LJ`Z))E9oGJaThKby!A0(V0MtT#hl!Y| zE7D_LB_elf23epy+q%T`wcR?d=Xf_Brn6VO&eQa}KS$>2&zPaj--d7Lz3OkPUT9hU ze=uVB*E0HIXLCZ7+jpZ5|;e@gSy zK8{TWZ_)0myoed`O9^uHCgte^>Y#&J9nDB^1dC0D?nM87Aqzx;*wof-2B`Vl}3k zjYBphD#j^m;P0iHnJ$5pIC=GGV2$dFB@lmb<+T6>+>cDY&Jp8L(*YChTa^Rs)t?{3i{d7bgTFU5a~ z)&u27m+7f`^q$xkQpseUf1+b@6EcQd`NX5dlWlIjgj%7`dx6uLlk1a{MU%pAUT^eT zm`zjVNtnhH!db=tShx-;BsXZdnD#M87gb^FFs4%D)p(KQS%?$*tjx|cvOb9;$`0Sv&&8R)I{fVhYuLC?$it*LR?VcQg% zBE_aR3r&&I4(*~2e+YJ-di(PXQB9yB4VJn9`2fUZMuDca0B3c7wqbN1Es^6SWoXZ) zMHX|4A#Ux(=O`bU=Urt!JMu7l&iKS==(cx;{X!5s+a*ZA7F?pJxpH@3I)2k1JHk~)pGQmbLN#V zT9cZ_d7ak#bw0=VGVQ`{esP#*`1s#Ydq!%HPYg+#pS?M+OHKf~D6|tm73sDbj%t`( zawCblSWf*g?prO%=l#Wh&ATzP4=2}Gi;FQ+9=|-oe@;Iv!Am&7lj6*O>~NhodS_$T z82tz9;AY=@@MxpkTJ6?~sp|FZ;V2)AXvTb&Hd#~V_L<)9WK>bzBSUTbs!0Vj z9S>(i3JojSkn)TM3xzV85S>TOr0KJ9i821>*M zESK-zc%3OBp*Hc*%2*ySO{rF%rQE$AO{HB{sq7cT-}E~J6TJVDS>=7QiA(eW-nfL5 z3k4N4+pO?kD)lO>DAp`OnN}r|-`QROQ&u9Oe`Q4oe{}3{r0?Z$I;HU{W#tYnayVxD zP9ctx@qG^(uAU87avvX#A|giHy+>+3up5S3TEzhe{(95a|q! z17ib285qdY*P%#*YKTbFoLaWKBh^Yn4jHB~&RQjnVnf&bn>3^`FC_rg|B+>;2Zqoc ze_OHJ43qWEN%GmBhEb%Nj4`qv@mUyvE#ZyY{Cs-7)b-ph5`l+C(nu;+6W7efK_ArJ{Axpb; zI1T4u)uHQRLMjE)G@aH+p>m23sH7pEXgZ7w($F+bQ=x0Xd9RiXbAaF5CUYQ(e98_vq9_EQ zOq*wdz#{-2*WB)X(;;E{2^Ewz=VglL3F8~EOqCNnN5skW2>vh#0QvD4WIHcQD%)uF zP-eEZB9^0Vvi`iXWN(a*?X&HTf5-Q9YDbmzm+oH)t1h!_Hp9j+U9T2&3u_QH zZQ>j{FHL!GwIU|~4QZM)sziX4lrAeWuA3@{eJy9s)U+;@CW)K3ziC=SBQTAu>7J=m z8wx>k#`Mt+(@CYVdhedE>d>nvj>)Fu@mAB>H?NgJK>+9~>v_<>0z^_}e*l-5;C5>F zFYtz_Gt-I_2h)542pGH!2mpT8{5?xP$3k;^t>WDWm}bFpz*l4)83XDJTFL8Xy1;i-j<( diff --git a/data/sounds/effects/KeypressDelete.wav b/data/sounds/effects/KeypressDelete.wav index 5903f7f165d317cddf372c08c9117f3a2c76da5b..0a2f3cc5ec0bba925344bfc82c5e53396f6cfd70 100644 GIT binary patch literal 29892 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 z zH@6!4c@6Nw(PqRS9CCoBHqf;aSf`>e15s$30`w;b&MBZ5c_5h?!K)D97XsUo6!Mb@ zZwVQFpr`0FnB{x;j0t|H1#dzj3n7rLG|=@_z&{4)5E%D4{GJHR_DRgaag4nmvT+oj z=Wy)|{EsW(=Ue?Rp0uzD^N*?>JfC3|Jm3{LYsdK$n#l^vus-Un5L-ieavFC9{a}jmt_YoU^jl7*_O2TJM>n_@V0zO}H|1+MF@g0~t;GF<=-_=u`)ZE3d+u;69+`aPW^O<^%`TBzS z@OBcfFk_c+{W@mhCGdF(NDn~coj+82<6iUXZNc$}XnPH?uH$I|@6`uo>-dPjX2RYl z9XzuH`Ugh-f;$0V5&%YTF#Zd)jlw&YehYaq(8GpwxtRA48098L!P6*EY5WDPKH;i^ zzf^!&4%sdBp?BpVttlXtM929*&7FH}o>dvZx4||i!$Bk{f`2T*OH2@9UZx-!1ZGSS zBxr~M{DWISQL}Lq7#bKL7>6+$k*Lvl4>)3i40nT#b=}r&-F@Aq8{O7!YrD4Vb-irV z-|u~T^1l7{F*d}ozIncLd+z6)=bZOzdk!OKG~c|wkNijAbPn%Z9~eA~cZ?4+md~V4 zZ9YhD%-~^k8^i3FI5-K~OVDpBGvqSj`-d3Md(mtuva9e;5BxsP+wRvm*XeHNrOy;k3u4Hz7k$H9%|F1d)8E112MH}9&rjO?H zxr4J3v~?sLCeR+TFGBix%(1c5j|0wUK7NL|JPG}-WJX`Y{Qoo-e3{x$P}hYo4D^YTLGIPb)iYnVel%$MdjN0NRN+t15-;$zTH#n#WG;rVFyS$Iz58Ao~+IHU2- z{x?SqwxeMOHnrf@QTUTTN}zl$IFooopFH>}th*The-d5z+e;`fKtDCRf+%w>aph7< z%JEy_>q##mLVN+47vlMgSx+yg^&(P7$mP&YrR`#R>vO;q`srHw?M|fJK}`E5T3<)) z6<}O|*Cs(X1|O zWEpB_a2n2c(C8L?@C~?Li5D(K_9S{{GP;WYYu1i`aIVpBi0x0&vroe5aeDPJ;{8ml zdWeYm1Nh&EoO{st+t_qt*7sKsm#?P&CaBfz`|L38Wp&_tZ{qX~(0mI&-Gm2j!%z29 zo{qdbp?w&=X0h*h8Xcd&mM7417MOovRQ(yO=cs!Yp0m(n1~O;D?-x+c9K0D_u4k>d z8NH{m>Oao<^eCTqv5MV_4nJgtdz5wJVe&ubt@LSDr)OBRp25Z$tjKq;Q@IfvzlxTV zk@O`rzKl2gtB`d&--thg4iAyuhd=H`hX>H-NqGE}x(ASXH}%t5$?gGvIy(J`_3aU! zJLsRA!MY3n53;`fgthH)_B%6JA)jI${S`cZiTt0jE=^;8UBl-!)ZETGIE|gi{d~_o z4Ow?%&x6RF3FqnH-HN0;vE^ZQ63?<%nay76uY3#t9O+*M7n1)wynly`-$G{}{+?3@ z{sr!0a4OLFWn})1-kgo5bFl7DaGM3cXYtRA9GM;)KAH4wXJUA=>OPyZ6 z7Wj^2r#TuJ%kFa=r|u2lW6#s9L(i?~vyoCQd+|2j2Ryma^LTrZu?viC*zpGK4eXVh z@Z|yQZsT`Pee9J_f#(?B);ztGKj^@7o}qdeFLZ#{4jjs$DNB3dKR}D;RC?m=SakAR zC(jf1)G?oaBn-gk5YoGlDvwTRdU?9Z9YE`SXtf)C>+o?sy6?k=Hgr6KhdurERK95( z0dzu9kIww14o?Hzny705uLGYQVlVGWxyovW?{3=b;V#s{b4LcPl(lCt)2SOdU2sra zPv7mQ+yO>CBcldCu7YYM^45~BMZ@*vw;;O~346eAfubGxZRps6{O*i*CwjM{UklKR z)JAZ%uO2Qfl)90rG|vxhL6=6fZQ!x*lu?Il$8j&M1GIO;rHAwgpPp^25BFz2tI2e$ zV=UG)t{U)P9rQc!VJ+qDz*b-rbsN#YhLKc9O(Wx=4Gx|Rd>DKC(4#fewjR1|;8p`w zDUOzdL(T}2j{>B=G;twd%Ou!1twL@UPz~m0sCVNfeY_8@JCV5&t>m|uShRrH^D2?7 z0^Z_pK@aEuE~LMKu3M{oz!$XAnv8O(>5oL=WylG(D9{#gcx71*{KScA{}E_x;Wv}Ywf zwK@aktfFN#pX+%xU~x5{o))_zYgq{=dwCJE<|1ABN?%Bw@+xUv1-;ZYc)up&RKe$K zw7d%SVz@1V-!d?&>9GxrfK7}9VSUyEF$&bS5^%Jc4~@2fS4*Gn0M`*Ejpd#2aYWa` zc`NA_IPau&FQ3i80VtX&HzI8xX+zd#>g?T_%~7M35x$kNVA=#UlW(MbA7jMGYE)}s zbftD@&OX4@*=Kt@xy}rlnbR%ILZgZ26E`s@rQeH;{p9z97peJ!a1z>qXfq0W8gWF4 zL$oIFgy4wMt<3Z`_>0rZ%x}xUsA4=h1P9}Bf`0PGTjOCjnsfl|fag3Lx5P7Q3=Dx$ zMBIq->Td)zN;Fb?fN}?IJ>d5e#XN(&2j~Vm0PQv^>W>4Yt?)LgcC#||5>Rz<;v7c2mp9Rjy2i^_v=_iS;&mB`cBM<7F4+9AlRA70@%BY7|FeXK;i z;Cj}3K+t-=eFr#6pU^%0CylatNwvrGu*Flyc3L_!8U6U!6SV`B?YM9ib_KRCV?}Sn zo`aM;gWB`f^^xb0_ho+QguWBr>g_m@hhr+rjxBliWIne4nrM}8DFZ0yV60Ob~F4i4eFEAagDZaCO)j=h5!n3qQa`CBK?CUUN$@`}8vd|P;0v$VNT zZiS1`2Ce%P?e9j{ZuAtoGEjHxdNQ5FYDb=rmURuKQR>WisJk=?I)`Xo>$|}42|jX= zGL^Kp9qRUsB4*ejyxxcR;xX5UUTUa^q?IQ0Nb*xj{p6+RlNNf_yw+)zHcKC~+?lS& z^)SD^%G#8Z^bTG1e)L2Kw7DpK>&d+2&QnMpv>&BXT9J1T_+s@l(m6Vg=P=IzWvSh##fT6~ zj{FN$hWRG5k1rvBppm|hyf+NEcjkBY{KO3&r;?sxk=?y5-bE2$jV<%a z>VDdL6}*STJ1yMlbJ{t-jrFF9@%+~Hbkfs##`D`xZ@%!JhOrrpCmj#&>C{gkcLtbe z@_8mD^U?-*SHo$P0^~P=nlm!I30Yn|Whi$%GK7$2-a84TwJqrosW)c?o^7XPpq|!i z$2fGYUFqZ&t{`QQ{06!-z=`Bhpdq zY!aMd;v{?YYxvhX>0-2{8IneO8iBSaNb+)-j@INSQ+*ZvU|&RkXh--U#!MPJrK$Jd zl!CVrB}i?l9I5Z`3A}aYSm3QXf^X-(^(U|#VB7F^@39HIXp7sByk$!8j+&rNyo$KN za{&5&BB+tJ7j8u`0{3TN6duf=e+XY1!TQia-ISk0sXa#WfW)^njds_LeErbI;UJHY zIlR6U&+-xU6I@#okmbkwk6bYV!hgvY`GyXW2A`nMX%cO*-aCxEHOke>n~jVMrcuu0 zRXJVMr}QW3d2}kTfQWrbX2ika_+fFmx}=9|sn77A@KMm^{>y2KbwMAieysbh{pl%s zGtcwyBaDcE+|xxplB|4{&w1y3^47E$FwLLftu8rDQC^N&K9|#lJ?>fp+`$wdcRKO7 zS4vN+b0?HzzZH+&Pwt{g?G%PFmKXHp&_ z!lWoLJUyBw?Z?XVIvT$mUhL~)ul9C%cV)w$Tt>3AXkW1|@&GF#m*rmBd zT}(@HqFlr%=4~yO-#VX<19QWp^xKz*Qy;5T)F;O~QF$kVpG%3{iO?P!w>WcCzPztW zb+CLQyi21~NP9aTrR_<_NK1L1csY+@{~K-aNl`sYr4hO)t2AGVo64nlrR9WInjSA+ zDc#9g9^UKktaRf2`~UOBJG0=uqZ&R7%SD3YuPa8+lP6z(O*(e%TdzbXk6pQrc@G)2 Z-|e4cuLQ%#PdVI^NuPIHm-mX_e*x2>Rx1Di diff --git a/data/sounds/effects/KeypressReturn.ogg b/data/sounds/effects/KeypressReturn.ogg index 1b0fd566cce001f1aa01eefcc70ddcd57c1b22f0..6c807b0114ffebec1205dc772f71ca055ca2b5c2 100644 GIT binary patch delta 4123 zcmV+$5ajRZIix;TPiJRS00IC200000005AcQhopc000@fT#00002 zM63V+000000CxcZ00000xB*XRXHx(G0000000000kd;z?0RR91-Z(775Mq&5Hy8l` z001!n003cfbZK*RJwtDBd2(rIXmqi+qz(ZLlUxrS0RWSF4>^CdJ^%m!0001xl~R5J z0002R67OpxKR7KbJT*8vJv;q8JUS~oK|DPF0^aQGJU#mL`Q+D|f=3(#OP>}UuM#oD zet-s?5x#l1!3LY3H%68C^MAPxXO5ruOP0pYFVkVL4a?UtkNs;Kn{oXr@t~){4pq`S z#t|&dQ37m^j01lH??1V9kmQ6>GnytjrfGN%pRLZ0GHr)r4Z}9AdXiiYj7gf9G8r^^ z^ZBQuZ)Y4#*>M+4G|z!U1m*((GwWIe=wGnMjCxRrV=CS27QGE&`dW6qj_^HO2)PIV zOy5B!18uH814jJ-z^c<_fCB3Agc_XEbg!Mimb3hp;Sql^S{v)@;ErksMB70o2Ti74 z5}_Yp5HmMd!0KwM1X8JB$#AzhU(Q@a2kZSX?2j3aiR>e_44*wzJ?l1%GRNM$)T{Ra zOw%k*wMmaWYt(SgigL9Ng$Ej+z zjLnd-ZFA<#_lSCbeEWUN&RE|4b^|ommOUj;cIeGRe1HUo%5?$kST#q9pk`dXm~j}o zrjc&b$>F#wKZE`oqpT(pXiloHn)m*(k~0#e0#Yj$pB02XAa1B{Hq5>%Aa4+Fl%bGx zegJ;}tyZhmYN6zD72^vv>t7D85(ywgqwTUg9`Hpo{Yffa9!|CxI6ik~hqsigjov&~ z>x#pWrkOq0F@|w@X!RMfb~rt~Om}+*A%_laY?|nNwN`CT&`y!bmC8htm=9Y4DoIQ< zS%pTUJ1fvOqEyz%S}SM9C1Y?h9Hh;ts zdpZ=|nDKK&l}foHvy#4ju{_OeTVPv7WYpq6pZXf8vs^C(^?oE=6J=Jh#GNhw5*c;^Z;=1T@19WAvh{`N2CE+XJuvuqvB!ysiC;LBh(R^iZh}UM{bifJt z0Any06X3_UGzL*aGM(%*b{xhox;TGjY0~9>$aUH8`BIl`vKf-LKQc+j%sl1?Y+q`O z5oTdp1WkPaP%2iR1o`hj5s;b2=@{_6E8ol~oHq0SEkv_{@LmFJW8@Ib#;76q6EKj3 zVFQ`qj|ZWksL5)&9dgKJX0DDIWSB8{UgNXNIyt7T9+^EA0a_J?MwBp)n*x7?=Yb#< zmPxb<@dC6C)9OetL5tmoWpJ|e`1-@jo?Yx;@4NpvW{d}V(|R&AH0Gd4Ro7^y=4>z$f!SFeKOjxUj0|!!?ca+VI zYZhfu7G+TuWv|!k^l9_BQr3jb*&syfuoMwnArx+TEggYoi2ycHh-OS*O^B?mQ zSH-pM=AP%CUbkkpF<6{i2(2b*fb29mhcQyAoGQ{p8f3OE_EjTZ%}9s&;uxQ68N(Q+ z*&MbODcz)K5D~8z_p9mbAPw5(X;=j!g(+4z^cJFV*hPitXs*=Q!rQAq$MektK=xa} zZX^}ki8hQ#_;IufAx(eV-mj4yiGvbiT<>_Zuz20y|Lq<%_(?F9WQ<)&HRd=bAt> zgP|#Ba!x%<6K!^H{I4q1{9E(9XMbTH-n>3HZHox#xfiJoBkr>L{OP4O^c)ukT+gFu zj7$Jb!4r(l$y`d~is)a=@5TtCK?IlJ%*e&r-Vf)P_r1|FfQBbt5~Ub6Lf^Br*N#%nya?!LE30eRHKsXb&6I5$0^m* zaO@&M)+vn79lOe*msnLl8nB^vtb0ZtUlQ zPTG5$?Dv)@)G2?O!a)cHhlT)w00wDD_BuFzt@i}x*}gf9C!F9q-bCqmFwTD4dv zn!%Z7QDP42v@(~LxpF|;gQh7lK-nlip>7g66xD#mt!5?KMU?2Z$@}$mUWNU9NuwIh zUR|NFK2}YEY!r7csSIy;-GAGyb@t+@501ugNsHW0dRgkEGCWOXlL;B)$b!lIWLsxV zQDD3%s+)i0dt60Rvc!qZgaKAN*3S;TFE9&uv0eSD&}PS?74ZB30Q&uYzu!mG7>FE^ zUuIDH;PhFKOcF_E*=S*fO=?ByWP{$CZFypScbOg0xzQSxUB%TsdTz;j$YQxabGcd? z&&IIqW;r%??T}ITnxjgyrxOfX%L?F|M^YeK)Ifhp%HkGf&?b}ca zEs9N7Q=G|g#6Eo)(v}r#Diw72VU#+P>s1m#IuX%2&t|@{VCXI%)pv_iIyNdXG^(%; zs}eELC+<;KH4xqSv&G6GQ^QUHU^qw=t>ZK$g!MW{3`u8yHF)X#MNGb-ROAC}XXwH3 zHKu<86o5X!L|NE45?p#Ado|6MkvjXWUmB~t_JB8}{IP%D`oS=w{cQUDCa0$O-nW0L-58T;WRyjD zI9Y7B+oz5;OpR5rNdmjfAS0sFzeBsPF-0Teog{Bsv^#xkFaBTt+@9?2Hl*d~go#8?HOYY`?I{! z0HUSdssHzx)%8Cs1q6_S^{Kz!Fnc1ur-et4GW9Z!`Ry zP+~RZh~De!DNYYQxxL$Lvd?Z$_G>rZjP42f`ShXrsxuGGv$_1vWySgBhYsWX&VENO z4(W1{c_^g;(&H(rG>04^9XeFbK`Nt&)v`ZCc zY0jZiiQS{VhQJJ&m!=P-6sB3)JO*ZqLPOR7K>-rcpixcMu1P}y5`G^obd+c3XKhbt zWdX(5f=*Oul2{pw;;X*s25opzLvRX+;0R!+Y;o=h81{{GamF~OJe*txeww{)z971O zo>qDR6*=$I>+SD?o_c-TOTK@=_9`0I1YpTzRS32q#G^QuMo&NDL1-eV=sD>)?eMxz zyK8GKN4u-N9~-T|*!Fla@7%qW(fzC$QdiIPX6=}d*k=vz7LCh*v{{~V*q=1pCZoJ$ zFF(RM=|SI}K%J=2L08eNDo*p^ZoM&y_DEG0hsK~JJCfJ>iAncTf4zUoq9wWw5xaJ~ zPY;bSPGcZqsSk0)<@Vi0k8ET~qo7VOXrx&MZ{Jzh{?HxHwJ$6I$Y?w@C!bEPe+atE z27HTTdcBDibq5Yd1&HK!KucNQA+Z(|B^Z!jtN_QWhHnjCSv~$N6AFEi9+-CJ^!z(v z(a%BpKoWjl`TVp4o#lUEvUvfyED)WJ=+PiM-%*nHGM075KUzL4z3{oi&mCTP=pLDO zkKeRAoViHWABc$?J6q@WR?F7s*TphB&}a;Xm$vJSq{m+Oil)llyjnwb9#L4cr!-`2 zkx>sR_q5mE2vgI@X3(MFSCarhI3TC-kb-ap|2!KrRU7~b*iC6owBec$##upXYLuNMIuUe<W*3YatLL^&4WUaT)f|Pc zf#{0A><9!DJ2YNJs!`|WL5K_(NcpA`o2Qc!0 zgC6%hk4x&!2zFh0FW#pl_h?RO0PJ`k%p@$O3|fBc-gkdZ3*z8lng<2QkeH{<*X^E7 zzV5Eo4(530jRu^@6aii+eZOz}S>g>QFerVzZu|bICqmvRqD!r^Wla5tgD?O9z*#E> zOJWp}S93WG5TMeq;y!R5F||$2PW5>+JG)9JGY1XQ9KsywQN#+!8h{=|4`s;dc(B~0 zQtYXmgff3L%{p}E?TR(*IPY13oAH_b6|=0B(~J1{0iHjYa?f delta 3561 zcmXX}c{J1y^!<#j_>C=;Wt4r(I%YCs&%Ov0V=%4c+{yY9U|0?&}vTJzo=?)qSe?$5IG#-Z!^wzQT zz8Mnc9UhMM#z%w&o&UpogyC`FcpW*c{EMu4^=zr>O=--$v zmE|J|fn#nJs1{ORU-y_(%fRrMd+qBnlZv_;6nfD>_n3LUO)q)q-uN4nr%A1OQi93C$)+4y8&k+3>N+6>kwLomylBm*?xw}tWI$>wm?Z~ zAk5}bqm=pgprCZs%Ju1??Sbjy{F*J1+;*>JV)eSBc?SO;(aZlQTk_8>tSSVP`4D1` zzBVJ#S1Y9i-JAV<{JW+Y`mAl~>A*<=qc`en% zr<12aeUhJmLjx7i2bnrGe?9%=3jKGzfNXzsU1wd*jUM?)1Qm@GE6FRN z)JB(WYUT%Z1N^;FR1Y4ho(5~Hw3?%8nxW=&8UY_XBVO<0MPDs?vmBg$ z^8rKZlxXX`<&zcVb94pw1m9Pmf zJ*;4H)PUchJuX4eX8pZ=899Y3P(g79T++OhTl6j_F3asClfGz&!KcNCc5E+)Gzo6z zd)u1`EMsXmx?WZ6Nzt^=LS$OWi+4X8<(yxyFB~<0OJw7})QvpIZ?<3AV5Sn^h5#XC zmZOrrdl-2~odr1gY!o8p>FABM>G9S3JcQ%OE!XR`_9NO=@_fX~`&Nfv_9WoY1T)*6 z7ML#b3t%tB1H*{8nkb&snL7}aHOW^Nzv}*E+}bHyY47Uj4!-tFLAs^sRxaW=AphO_ zJ{U8Ab`}VLNI`k6%jHu0hx`XEH4iBU>^ifU3lqTrv&TSI5G{1`>K>vLhOl& zBB{<=jM+2hTYF`{-dH=w?vVUX(>tq5Y?BCtIi=RMyMn!b-*+~3&3jGwdZFZNpNz1h zA|>?eUUMaPMyQut@MTD?LjUx>{LS~F=8`Qo61>d^Pdqm=&l(Twk-1Zdk~SLFydL&mU5%{HG|vYqyVgS zA>IGdibh~%NajagH69Z4A+J{L&$0bq(POt8n2r;q8CypqU7=>wN{J~lw)^)Q5M>&zz0KV^RRz!P~Zu7^o(8L&!3_I6w0dRR? zNK!bU#Xk zRAtWR(}_vC?a;6qR3~oLopmzZ;?YJ7Lg%$h#cA)Hvc4;W*|bxN;)zp~CAS{L310{f z9S4WA5~mE+r&$Q_x+7Q3^mVfOV~be|0`I`c=^HV65cKqM62;4WLh0N_{(O9ivpU6B zkbJ6az!`Vfei%kCJH75Hu$m#PNPCEDG4p;|Gj=JLzqFWw;g09US9k{&WZE8w{*UCC z3JjN4ET>NyRB00;aFAlI1!4oyo)D<3g#(><>*?1GH4fEwJuQoU`2v#!VNFrk^nXo) zqcYfGlU=U2?D6tL@Vi_^k|*6|b3vp$U#%U38I3QDFSMk%52sD&w)h*U)|$6|!&LPz zP-;2~0FLfoR*}zA1sjQ-ZoO&=_V5P~zd?^AFtteK&pg#;dWIaTq$%Rc&ZAI;z;0qv z*QeNS&;A5c9M~HtwU`{b;Jlcz;pR)LsK&ji<<(TY(h}i6gyI`$OEko+hAh4Ox*=e@ zaO*S74nXbrIVC7eu^RGexq2w=`rkkC4pwCe`g8o;75K7-g-kYg1~gmOxjheR>|ur? zz7l4sd6exTR!J_sTd86wD77ounn+G1U+i5GylM^W{`l#JKucct8?7@@XhSHxaL30b zQgWF;pySd!nSC1r#i_L_By~^K@BbNu zk&JI0vGeXJ;>{g(ICV-wc)vsVQ73HT$6F5`Ww|{X?PY|uTd+qtOmQL63;Y4npaSnN z6e4(725cjs7x&AsY0{a*;nE!+YF|DOyp?yOXJ~{8YH@?$$AU17TM1dUq~^p3*7Z|& zj#>dT=Er_18A3p#-1wveI0Xf<+AyxTIp!1SS;^th918$S`Rp5AOqCsW;wKwXPRX%G z9%2d^VyqvVv8U5M-Wh!rJzd$ZO~{B+KIQupJ*Sv~Y+xGX=_f+^jmrb{ghJ`z$gqYr zHTtG@Yj8z?{L4HFc~D5P*W8fIMNi#_IGr~{Q+z9pTnp;4mZuleQxA|0<6bZ3reBvb zs+jq&r5eqAz^76Qogr1WN|Y)#p8E*Q3$gDk~@Uo=fS$_>0;XFrIHYa}gjZdrh0d z+eBG*{t9k@q6h@htRGGq-`sCYn4VHHt*;+jOOolGs+VZry7z3J+suiR!6fDQ&G^bC z0VP(MV^FTtU2vSU6axL^OsQ)A@7k%z`h$_K3!^Zk^`=YY2o($M6H_sGozW?MU~-3& z2EXuX)(+sei6e;=i-oT;TaEOB^cR6fVs&l+stXS(SL|J)(&SB6pQ|T#<-$_RQ3UO6 zw=tpfLkh*;9J1S^f+xsDn}Jw>#dt-mFuwehtyt>`_mhu6fClTZX~S!yb@7R9!QG{~ zF>&7nLu+5_1LH?w8oPCEjjL)gJM`-4o9Bo$VD-%%2Q^fK4B0AlB zK&DT?Rd@s;SCp{$K1RgZ7)C73$++6xRIadE+b<_zrev&ug{8>&@)(4_&4pc4;3VQO z{w~3Mqp(LHW$t0TC|(r>y)GAQ;7b2ZxZIVUY>peN4ZA6u!X}eyQp~<9xg9i{im_`e zWIxHYVaoih3?B{eb(HJa)-AZE04qd}!fSxoN$qMic@*c(!))Ik;%mlkRy^;37%fsi zC13JpzH^7&*Th~Yanpgs+vnmzh2e|li)RnHif@m2etW}TvjCCC;WrAMl$E2ibP5)F zuZ%lE3cU5K{gI+BF9(!04wiSR3%EGw;9JaAj=uS=%$SBQSRksx-$G!-uAU8sZ+1RY zs>VCKcsFk~lq++D_**)q{At%$f`0){Gp~H5NL#&Tkhgkmia<=zFawmW6*!?oxjMC= z`>T86!1p!^)Ig4BWo&t2sOySP46(+FKhL9JsjU|~0@g0Li2T$c1RPBqwktA^ab6gn zIBcOXJBp06Srt@qh$D8-v3Urx0f1RJg|J2;JXhn1@FQL?&u^Ia4VxoSQfsOMthROD zm9|!1zB2l;cDV)lB_uj*uCLEoS*pJ~M}jQ_e>1mf&AT_cs_a^Z6?*#cM8l*RA| z73J=!LB1SxZ4l=(io6%M48w1NCtJ>tnTCfa6d&8{xQotNy*6H)opE);ScO0SSR@#o zbz5yk-3Ihwz_K(n2W-WOfOvI)gkmRVqm?3a0j`G=hmk75e}L-J-4Cij+`k{^|As2} c9@jFjDZl`I{jy*U4ARa6Gy=q(A;1d!F94E-wg3PC diff --git a/data/sounds/effects/KeypressReturn.wav b/data/sounds/effects/KeypressReturn.wav index 9558fcf0c4ac36622c128fc5fa7b8bcefdae7939..59ff13af4df4e7f68d93cdf2b367bd14f5419035 100644 GIT binary patch literal 64320 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 OUtRb9W&h9j!2be#A1$*0 literal 46756 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%0A7mEYKdye`;ss{Mvju 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 diff --git a/data/sounds/effects/KeypressSpacebar.ogg b/data/sounds/effects/KeypressSpacebar.ogg index 5299337f4d91c7ea8c91ad035d2aa399a375d0b1..b59c8ce4904da7d9123a9090006c140c6864c860 100644 GIT binary patch delta 3538 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 delta 3281 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⋙)1=bSB$e5N0^v!$yFUbJus7DFQG@oL>79l& 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�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

{{RfnCB5v9sFuPWZ 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 diff --git a/data/sounds/effects/KeypressStandard.ogg b/data/sounds/effects/KeypressStandard.ogg index 8a152d11fc3de74629306d95a804ba45ec7c124e..a465cf8f9aa735e0502fe3f720707f2f8addaff2 100644 GIT binary patch delta 1323 zcmV+`1=RYFE6ONVPiJRS00IC200000007|EN`C+V005xhZ@mE?0d{Y4Vrg>#00002 zM63V+000000CxcZ00000xB*XRXHx(G0000000000;MYoj0RR918H26K5Mq&5Hy8l` z001!n003cfbZK*RJwtDBd2(rIXmqi;qz(ZLlU@%U0RWSH4>^B!5dZ)H0002s*Ghi^ z0001@R9u7$L_#(_KmP;eyNV?gZ6S{(7&gUP%!f%IU?GsLCu6tJ>qfJi9aE>LT)epZ zHRsFSy$2U*X6DK3xJVrJ4q8fOlGbqMcVr%R|79{nZA1YaX;}kK!Eshagmzwlz5}~& za)6@U9UWXYM2~;_EO%?i#Bwp*z5V89bKpD+On)y=oCY;aQ_ z6%raUMN|dAll=)GP8$|Lf6EzQKLh|AYk!KWufaIwOe0-X`#GkWp(2;*(4lrZO^rAJ z9A8YL86;c2Oq&m|LJy|p3rO(4txX%~;kl>P2&FNOo6UdbB(pRm$Ft7<^o_r?=TA$vr+(#ncmynC;V6=@g!wZ}dI9>l*j=C}nDEDIHI-qlnP9OUo+TPF%r;w`>)Mq? z1-FrJT&qRTbM{oI#L+*#e=IHZ02+#ApCmSI8*Op!>4*|SU+9+pAu!`O(cAZS6rtY_ z0HED&x50muRdP)_G!QJKS@+J3Kv) zYtA3T3F9J@;kZS{$=RU;vXEBBINW#8-M(aH!ZR+-KDNScC@Dx&tm$mcO%zc`lk*s( zgNACl?0#M{4%Oi_WRni#UXRm(0yRFbyw#dbbB2GImoc>Z{HB+*$zj5C^hmrcDv4`0 z&4wT?`X4Fx>`R;tBn_ITq5D%RW5#7oNuvd;_jf2r-gyJwJZ5dCmG_7PguDdoW_$BZ z)1k?DX69s-_QYdA03h(r+dJI52fjFU-?15o>)_nU76zg0qqO;EI(UCsgL5DNlPwEQ zi)DXAxFQTMgRgDciuNVMmYCz#>O-x~CS67>Yf&BBC-(!x@feJah~e_Ab3;Qm(cy5r zY-pESc4*joz%wp;m@JknB07|juT(P*DNrEGsY1#z4w}BR=@E3fnRT~ps>9i1 zfdCU8)BIbl4y4C8RGK!GbfT>}pQUMHO&kIP3R zJk0wzEvS>8x6AUa**-b9A}~!=7MO}Cnht`)0002VK4a(BwKC24q>iO_Ye>OipD}-# zEq9X+3}*%_WVzgBA?a{RQ;WcO9Fu0%6xiKqk!CaKFg00;C|vJZgZ0Hl>9c1Hd={8sL9u0A443U5;;C3WjZlIq7S=zpE6{J+>{#s>~Kb z8uAB05Qae*0002c{dC=-86gz_YaTUMy4BF%a1ThmQJR_XqrFA8|*Gyo?cTqCJ1`Hnr00IYO hP{06WXaG0>UMKzUEMK|+ZlF&3-&wwN0o;=j1`~0~MqmH{ delta 1665 zcmV-{27dXvPiJRS00IC200000001dRUTpvX0028;1RVh$0d{Y4Vrg>#00002 zM63V+00000K$Zaj00000xB*XRXHx(G0000000000DMwyy0RR91q6;Td5O$GPH!K1G z000&M004ApbZlikOJ#X*a%FRKQ*>c&WMOh-D*ylhVRCe7b96l@V=1wvqz(ZMlS&UA z0f3We4>^C46aWAK0000fM_z3L0001E7VC`rbea5q)vK`DgfYT zo3q(A443r@pSRnW2lV>R4{K~X_H{>6AJ?l2Rdjy{qiz zKK~;Py80sy^rIymGG80%-B#!Ha)&LHM&AZn@zLmel9(n^0pQ}o--g9AudDZEFWAKo zxb{<~y-mmJ&#PrEOty*oBc=wFMrsYlgpWk(9!(cgRDoFj@;_ql1HIgKcWYwuX+Bv| zDCmFNteVe%%cB=1m39LGj7ZN$0*^+|0rCB&Wk#SbW8+_Zc;@2r@WZ!b3(miv*LXbV z)^7s7)qtWv8_n$XeEXIFvR3g6mr(ZujYiPQ=FRMmWTb&XAnl>I8 z2HeoJ#M&jMPT6`GN_)IGt#mRMItsMyc&VE(jZ@W634vqW8i^JLD zbmpms$z&ZZSH)*+%%^We1^imEUJQd9JCzj353mpgSU|4{eB^zwePvWYpX;taeWib0 z-ahm|mY6S(-KH6B^Ux2`9?$hMr!<_W0dOqY={S1XhesFj#m?%@3+7mRD!LA z+-#SL=RK{dN&Nr-dZ+i>15;HsPJ^74LE}vMAW|G|79#;ho4p;fu}@w+8+uue%)CDD z^rE2^dmCNcN0yF+XC6EH=(@MBy|#b9qs=`NoS89OiI_=-j+2U;cCllvhb;Cb)kv2L z(8Wgf9msx_rfHg{A-bd~CyU)Sg`|ZLCxbI>f|RT#%Cge^Cd1M=P=`rYhoQP{4)HuB zImz+<)Zv6>Uj+b4^whhUXgcY>TQ=KAwdsv2Cu$LPKlngY~>8jXK3!^xmw z%+T5Ej2$WpkI!-`2+1qP0eU){tR<`jS{j2*yBg+d(`trsoMa4rWTiUx3ji-9j&9{y zi^8UdsqM!B9@va0ZSu`UXWU62>%voC(_LwMvAJMBgGnNAa=vr|>}vt55NwqYhbWBa z!h?r_PhX!u&u|PdMKdx-!#IC^l0MKEakI&Mr(HMWtb9I($LwormR~H_uO0T&NLWZS z_xK#+(g5IsXOuAk!+7jaG|**@9&Hy5NJBNGN7GcsVNEnOrJX{bH;wMw$(W{MoYtYC zwjSejNrM~T3^ZlikEZW$-J4#X*A^*89(|^zo|pSufg<4@x|^oMVQ7CkOosyAJdfYf zqbX<_U^C8!S(xpbhv^M!s{+8IX0z{k^LF>EBJR4?&6a@^-r_DZyLyiUUe>I~lC(|m z{{A2!t=TSn%uwi^=hw-CX$pnF6dZ@pe;5P+K*l;3klCQIkeMat@sxCRTOKxp<=C0i z6R*E6zuw6iX|l{{=Bj^XZYkqYlhv}wxNLh0K*pnhrgE5!sY(IN%s)09dm{ynebbx= zn)EXskm}MDAgj4#I;nK2`xgLEX_|33hZO>>OVdC>D2x5(QPr=8uC3l7Jp4i&0p8`k zyZlz$Y-M2Dm#f*XT(eK0Wsa?@9|A61!o7R#-rwgVA3Gap(5`>R?EJ+60p8a9y`6qS zC>Cr*aMt`j#=Eo%oGlqNgHQ!YaNLK3g8%>k09|TiGpyLp59u&&gdZ02swM>@Hyu@#yg|GvFZ+udBj8B;3NG$}Jb6WQ=ym~$Rv z_&0^y@6%Fung9*}000030000000000 L00000000~SL{$YS diff --git a/data/sounds/effects/KeypressStandard.wav b/data/sounds/effects/KeypressStandard.wav index 0c9aa2a383977d76a9d4c5da7a15f1263bdc7e52..56a791155a396e6c63ba8a59167a4043335da2a0 100644 GIT binary patch literal 17992 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 Yhkx^x^K(+pe*YWwe+~VWT~6Qs1MuR|qW}N^ literal 21172 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

This animation runs for just three frames. By setting the android:oneshot attribute of the list to true, it will cycle just once then stop and hold on the last frame. If it is set false then -the animation will loop. With this XML saved as rocket_thrust.xml

in the res/anim/ directory +the animation will loop. With this XML saved as rocket_thrust.xml in the res/anim/ directory of the project, it can be added as the background image to a View and then called to play. Here's an example Activity, in which the animation is added to an {@link android.widget.ImageView} and then animated when the screen is touched:

diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp
index eb00f8cc9a6c9..2974e32ee179e 100644
--- a/libs/audioflinger/A2dpAudioInterface.cpp
+++ b/libs/audioflinger/A2dpAudioInterface.cpp
@@ -48,7 +48,6 @@ AudioStreamOut* A2dpAudioInterface::openOutputStream(
         int format, int channelCount, uint32_t sampleRate, status_t *status)
 {
     LOGD("A2dpAudioInterface::openOutputStream %d, %d, %d\n", format, channelCount, sampleRate);
-    Mutex::Autolock lock(mLock);
     status_t err = 0;
 
     // only one output stream allowed
@@ -134,7 +133,8 @@ A2dpAudioInterface::A2dpAudioStreamOut::A2dpAudioStreamOut() :
     mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL)
 {
     // use any address by default
-    strncpy(mA2dpAddress, "00:00:00:00:00:00", sizeof(mA2dpAddress));
+    strcpy(mA2dpAddress, "00:00:00:00:00:00");
+    init();
 }
 
 status_t A2dpAudioInterface::A2dpAudioStreamOut::set(
@@ -163,18 +163,12 @@ A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut()
 
 ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes)
 {    
-    status_t status = NO_INIT;
-    size_t remaining = bytes;
+    Mutex::Autolock lock(mLock);
 
-    if (!mData) {
-        status = a2dp_init(44100, 2, &mData);
-        if (status < 0) {
-            LOGE("a2dp_init failed err: %d\n", status);
-            mData = NULL;
-            goto Error;
-        }
-        a2dp_set_sink(mData, mA2dpAddress);
-    }
+    size_t remaining = bytes;
+    status_t status = init();
+    if (status < 0)
+        goto Error;
     
     while (remaining > 0) {
         status = a2dp_write(mData, buffer, remaining);
@@ -197,10 +191,27 @@ Error:
     return status;
 }
 
+status_t A2dpAudioInterface::A2dpAudioStreamOut::init()
+{
+    if (!mData) {
+        status_t status = a2dp_init(44100, 2, &mData);
+        if (status < 0) {
+            LOGE("a2dp_init failed err: %d\n", status);
+            mData = NULL;
+            return status;
+        }
+        a2dp_set_sink(mData, mA2dpAddress);
+    }
+
+    return 0;
+}
+
 status_t A2dpAudioInterface::A2dpAudioStreamOut::standby()
 {
     int result = 0;
 
+    Mutex::Autolock lock(mLock);
+
     if (!mStandby) {
         result = a2dp_stop(mData);
         if (result == 0)
@@ -212,15 +223,15 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::standby()
 
 status_t A2dpAudioInterface::A2dpAudioStreamOut::setAddress(const char* address)
 {
-    if (strlen(address) < sizeof(mA2dpAddress))
+    Mutex::Autolock lock(mLock);
+
+    if (strlen(address) != strlen("00:00:00:00:00:00"))
         return -EINVAL;
 
-    if (strcmp(address, mA2dpAddress)) {
-        strcpy(mA2dpAddress, address);
-        if (mData)
-            a2dp_set_sink(mData, mA2dpAddress);
-    }
-    
+    strcpy(mA2dpAddress, address);
+    if (mData)
+        a2dp_set_sink(mData, mA2dpAddress);
+
     return NO_ERROR;
 }
 
diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h
index a56e8a0cdd32b..99614dc108739 100644
--- a/libs/audioflinger/A2dpAudioInterface.h
+++ b/libs/audioflinger/A2dpAudioInterface.h
@@ -82,11 +82,12 @@ private:
         virtual status_t    setVolume(float volume) { return INVALID_OPERATION; }
         virtual ssize_t     write(const void* buffer, size_t bytes);
                 status_t    standby();
-                status_t    close();
         virtual status_t    dump(int fd, const Vector& args);
 
     private:
         friend class A2dpAudioInterface;
+                status_t    init();
+                status_t    close();
         status_t            setAddress(const char* address);
 
     private:
@@ -96,9 +97,9 @@ private:
                 int         mRetryCount;
                 char        mA2dpAddress[20];
                 void*       mData;
+                Mutex       mLock;
     };
 
-    Mutex                   mLock;
     A2dpAudioStreamOut*     mOutput;
 };
 
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 92c40e90dcd50..440778ddc27ba 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -71,6 +71,9 @@ static const int8_t kMaxTrackStartupRetries = 50;
 static const int kStartSleepTime = 30000;
 static const int kStopSleepTime = 30000;
 
+static const int kDumpLockRetries = 50;
+static const int kDumpLockSleep = 20000;
+
 // Maximum number of pending buffers allocated by OutputTrack::write()
 static const uint8_t kMaxOutputTrackBuffers = 5;
 
@@ -115,8 +118,7 @@ static bool settingsAllowed() {
 
 AudioFlinger::AudioFlinger()
     : BnAudioFlinger(),
-        mAudioHardware(0), mA2dpAudioInterface(0),
-        mA2dpEnabled(false), mA2dpEnabledReq(false),
+        mAudioHardware(0), mA2dpAudioInterface(0), mA2dpEnabled(false), mNotifyA2dpChange(false),
         mForcedSpeakerCount(0), mForcedRoute(0), mRouteRestoreTime(0), mMusicMuteSaved(false)
 {
     mHardwareStatus = AUDIO_HW_IDLE;
@@ -190,13 +192,44 @@ AudioFlinger::~AudioFlinger()
 
 
 #ifdef WITH_A2DP
-void AudioFlinger::setA2dpEnabled(bool enable)
+// setA2dpEnabled_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::setA2dpEnabled_l(bool enable)
 {
+    SortedVector < sp > tracks;
+    SortedVector < wp > activeTracks;
+    
     LOGV_IF(enable, "set output to A2DP\n");
     LOGV_IF(!enable, "set output to hardware audio\n");
 
-    mA2dpEnabledReq = enable;
-    mA2dpMixerThread->wakeUp();
+    // Transfer tracks playing on MUSIC stream from one mixer to the other
+    if (enable) {
+        mHardwareMixerThread->getTracks_l(tracks, activeTracks);
+        mA2dpMixerThread->putTracks_l(tracks, activeTracks);
+    } else {
+        mA2dpMixerThread->getTracks_l(tracks, activeTracks);
+        mHardwareMixerThread->putTracks_l(tracks, activeTracks);
+    }
+    mA2dpEnabled = enable;
+    mNotifyA2dpChange = true;
+    mWaitWorkCV.broadcast();
+}
+
+// checkA2dpEnabledChange_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::checkA2dpEnabledChange_l()
+{
+    if (mNotifyA2dpChange) {
+        // Notify AudioSystem of the A2DP activation/deactivation
+        size_t size = mNotificationClients.size();
+        for (size_t i = 0; i < size; i++) {
+            sp binder = mNotificationClients.itemAt(i).promote();
+            if (binder != NULL) {
+                LOGV("Notifying output change to client %p", binder.get());
+                sp client = interface_cast (binder);
+                client->a2dpEnabledChanged(mA2dpEnabled);
+            }
+        }
+        mNotifyA2dpChange = false;
+    }
 }
 #endif // WITH_A2DP
 
@@ -236,8 +269,12 @@ status_t AudioFlinger::dumpInternals(int fd, const Vector& args)
     const size_t SIZE = 256;
     char buffer[SIZE];
     String8 result;
-
-    snprintf(buffer, SIZE, "Hardware status: %d\n", mHardwareStatus);
+    int hardwareStatus = mHardwareStatus;
+    
+    if (hardwareStatus == AUDIO_HW_IDLE && mHardwareMixerThread->mStandby) {
+        hardwareStatus = AUDIO_HW_STANDBY;
+    }
+    snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
     result.append(buffer);
     write(fd, result.string(), result.size());
     return NO_ERROR;
@@ -262,7 +299,14 @@ status_t AudioFlinger::dump(int fd, const Vector& args)
     if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
         dumpPermissionDenial(fd, args);
     } else {
-        AutoMutex lock(&mLock);
+        bool locked = false;
+        for (int i = 0; i < kDumpLockRetries; ++i) {
+            if (mLock.tryLock() == NO_ERROR) {
+                locked = true;
+                break;
+            }
+            usleep(kDumpLockSleep);
+        }
 
         dumpClients(fd, args);
         dumpInternals(fd, args);
@@ -277,6 +321,7 @@ status_t AudioFlinger::dump(int fd, const Vector& args)
         if (mAudioHardware) {
             mAudioHardware->dumpState(fd, args);
         }
+        if (locked) mLock.unlock();
     }
     return NO_ERROR;
 }
@@ -320,18 +365,19 @@ sp AudioFlinger::createTrack(
         }
 #ifdef WITH_A2DP
         if (isA2dpEnabled() && AudioSystem::routedToA2dpOutput(streamType)) {
-            track = mA2dpMixerThread->createTrack(client, streamType, sampleRate, format,
+            track = mA2dpMixerThread->createTrack_l(client, streamType, sampleRate, format,
                     channelCount, frameCount, sharedBuffer, &lStatus);            
         } else 
 #endif
         {
-            track = mHardwareMixerThread->createTrack(client, streamType, sampleRate, format,
+            track = mHardwareMixerThread->createTrack_l(client, streamType, sampleRate, format,
                     channelCount, frameCount, sharedBuffer, &lStatus);            
         }
-        if (track != NULL) {
-            trackHandle = new TrackHandle(track);
-            lStatus = NO_ERROR;            
-        }
+    }
+    if (lStatus == NO_ERROR) {
+        trackHandle = new TrackHandle(track);
+    } else {
+        track.clear();
     }
 
 Exit:
@@ -409,7 +455,7 @@ status_t AudioFlinger::setMasterVolume(float value)
 #ifdef WITH_A2DP
     mA2dpMixerThread->setMasterVolume(value);
 #endif
-    
+
     return NO_ERROR;
 }
 
@@ -436,7 +482,7 @@ status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask)
         if (routes & AudioSystem::ROUTE_BLUETOOTH_A2DP) {
             enableA2dp = true;
         }
-        setA2dpEnabled(enableA2dp);
+        setA2dpEnabled_l(enableA2dp);
         LOGV("setOutput done\n");
     }
 #endif
@@ -704,46 +750,6 @@ void AudioFlinger::binderDied(const wp& who) {
     }
 }
 
-void AudioFlinger::handleOutputSwitch()
-{
-    if (mA2dpEnabled != mA2dpEnabledReq)
-    {
-        Mutex::Autolock _l(mLock);
-
-        if (mA2dpEnabled != mA2dpEnabledReq)
-        {
-            mA2dpEnabled = mA2dpEnabledReq;
-            SortedVector < sp > tracks;
-            SortedVector < wp > activeTracks;
-            
-            // We hold mA2dpMixerThread mLock already 
-            Mutex::Autolock _l(mHardwareMixerThread->mLock);
-            
-            // Transfer tracks playing on MUSIC stream from one mixer to the other
-            if (mA2dpEnabled) {
-                mHardwareMixerThread->getTracks(tracks, activeTracks);
-                mA2dpMixerThread->putTracks(tracks, activeTracks);
-            } else {
-                mA2dpMixerThread->getTracks(tracks, activeTracks);
-                mHardwareMixerThread->putTracks(tracks, activeTracks);
-            }            
-            
-            // Notify AudioSystem of the A2DP activation/deactivation
-            size_t size = mNotificationClients.size();
-            for (size_t i = 0; i < size; i++) {
-                sp binder = mNotificationClients.itemAt(i).promote();
-                if (binder != NULL) {
-                    LOGV("Notifying output change to client %p", binder.get());
-                    sp client = interface_cast (binder);
-                    client->a2dpEnabledChanged(mA2dpEnabled);
-                }
-            }
-
-            mHardwareMixerThread->wakeUp();
-        }
-    }
-}
-
 void AudioFlinger::removeClient(pid_t pid)
 {
     LOGV("removeClient() pid %d, tid %d, calling tid %d", pid, gettid(), IPCThreadState::self()->getCallingPid());
@@ -751,17 +757,9 @@ void AudioFlinger::removeClient(pid_t pid)
     mClients.removeItem(pid);
 }
 
-void AudioFlinger::wakeUp()
-{
-    mHardwareMixerThread->wakeUp();
-#ifdef WITH_A2DP
-    mA2dpMixerThread->wakeUp();
-#endif // WITH_A2DP
-}
-
 bool AudioFlinger::isA2dpEnabled() const
 {
-    return mA2dpEnabledReq;
+    return mA2dpEnabled;
 }
 
 void AudioFlinger::handleForcedSpeakerRoute(int command)
@@ -803,7 +801,7 @@ void AudioFlinger::handleForcedSpeakerRoute(int command)
                 LOGV("mForcedSpeakerCount decremented to %d", mForcedSpeakerCount);            
             } else {
                 LOGE("mForcedSpeakerCount is already zero");            
-            }            
+            }
         }
         break;
     case CHECK_ROUTE_RESTORE_TIME:
@@ -946,20 +944,20 @@ bool AudioFlinger::MixerThread::threadLoop()
 
     do {
         enabledTracks = 0;
-        { // scope for the mLock
+        { // scope for the AudioFlinger::mLock
         
-            Mutex::Autolock _l(mLock);
+            Mutex::Autolock _l(mAudioFlinger->mLock);
 
 #ifdef WITH_A2DP
-            if (mOutputType == AudioSystem::AUDIO_OUTPUT_A2DP) {
-                mAudioFlinger->handleOutputSwitch();
-            }
             if (mOutputTrack != NULL && !mAudioFlinger->isA2dpEnabled()) {
                 if (outputTrackActive) {
+                    mAudioFlinger->mLock.unlock();
                     mOutputTrack->stop();
+                    mAudioFlinger->mLock.lock();
                     outputTrackActive = false;
                 }
             }
+            mAudioFlinger->checkA2dpEnabledChange_l();
 #endif
 
             const SortedVector< wp >& activeTracks = mActiveTracks;
@@ -968,7 +966,6 @@ bool AudioFlinger::MixerThread::threadLoop()
             if UNLIKELY(!activeTracks.size() && systemTime() > standbyTime) {
                 // wait until we have something to do...
                 LOGV("Audio hardware entering standby, output %d\n", mOutputType);
-//                mAudioFlinger->mHardwareStatus = AUDIO_HW_STANDBY;
                 if (!mStandby) {
                     mOutput->standby();
                     mStandby = true;
@@ -976,17 +973,18 @@ bool AudioFlinger::MixerThread::threadLoop()
                 
 #ifdef WITH_A2DP
                 if (outputTrackActive) {
+                    mAudioFlinger->mLock.unlock();
                     mOutputTrack->stop();
+                    mAudioFlinger->mLock.lock();
                     outputTrackActive = false;
                 }
 #endif
                 if (mOutputType == AudioSystem::AUDIO_OUTPUT_HARDWARE) {
                     mAudioFlinger->handleForcedSpeakerRoute(FORCE_ROUTE_RESTORE);
                 }                
-//                mHardwareStatus = AUDIO_HW_IDLE;
                 // we're about to wait, flush the binder command buffer
                 IPCThreadState::self()->flushCommands();
-                mWaitWorkCV.wait(mLock);
+                mAudioFlinger->mWaitWorkCV.wait(mAudioFlinger->mLock);
                 LOGV("Audio hardware exiting standby, output %d\n", mOutputType);
                 
                 if (mMasterMute == false) {
@@ -1104,13 +1102,13 @@ bool AudioFlinger::MixerThread::threadLoop()
             if (UNLIKELY(count)) {
                 for (size_t i=0 ; i& track = tracksToRemove[i];
-                    removeActiveTrack(track);
+                    removeActiveTrack_l(track);
                     if (track->isTerminated()) {
                         mTracks.remove(track);
-                        deleteTrackName(track->mName);
+                        deleteTrackName_l(track->mName);
                     }
                 }
-            }  
+            }
        }
         
         if (LIKELY(enabledTracks)) {
@@ -1197,8 +1195,8 @@ void AudioFlinger::MixerThread::onFirstRef()
     run(buffer, ANDROID_PRIORITY_URGENT_AUDIO);
 }
 
-
-sp  AudioFlinger::MixerThread::createTrack(
+// MixerThread::createTrack_l() must be called with AudioFlinger::mLock held
+sp  AudioFlinger::MixerThread::createTrack_l(
         const sp& client,
         int streamType,
         uint32_t sampleRate,
@@ -1218,26 +1216,22 @@ sp  AudioFlinger::MixerThread::createTrack(
         goto Exit;
     }
 
-    {
-        Mutex::Autolock _l(mLock);
 
-        if (mSampleRate == 0) {
-            LOGE("Audio driver not initialized.");
-            lStatus = NO_INIT;
-            goto Exit;
-        }
-
-        track = new Track(this, client, streamType, sampleRate, format,
-                channelCount, frameCount, sharedBuffer);
-        if (track->getCblk() == NULL) {
-            track.clear();
-            lStatus = NO_MEMORY;
-            goto Exit;
-        }
-        mTracks.add(track);
-        lStatus = NO_ERROR;
+    if (mSampleRate == 0) {
+        LOGE("Audio driver not initialized.");
+        lStatus = NO_INIT;
+        goto Exit;
     }
 
+    track = new Track(this, client, streamType, sampleRate, format,
+            channelCount, frameCount, sharedBuffer);
+    if (track->getCblk() == NULL) {
+        lStatus = NO_MEMORY;
+        goto Exit;
+    }
+    mTracks.add(track);
+    lStatus = NO_ERROR;
+
 Exit:
     if(status) {
         *status = lStatus;
@@ -1245,12 +1239,13 @@ Exit:
     return track;
 }
 
-void AudioFlinger::MixerThread::getTracks(
+// getTracks_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::MixerThread::getTracks_l(
         SortedVector < sp >& tracks,
         SortedVector < wp >& activeTracks)
 {
     size_t size = mTracks.size();
-    LOGV ("MixerThread::getTracks() for output %d, mTracks.size %d, mActiveTracks.size %d", mOutputType,  mTracks.size(), mActiveTracks.size());
+    LOGV ("MixerThread::getTracks_l() for output %d, mTracks.size %d, mActiveTracks.size %d", mOutputType,  mTracks.size(), mActiveTracks.size());
     for (size_t i = 0; i < size; i++) {
         sp t = mTracks[i];
         if (AudioSystem::routedToA2dpOutput(t->mStreamType)) {
@@ -1267,28 +1262,29 @@ void AudioFlinger::MixerThread::getTracks(
 
     size = activeTracks.size();
     for (size_t i = 0; i < size; i++) {
-        removeActiveTrack(activeTracks[i]);
+        removeActiveTrack_l(activeTracks[i]);
     }
     
     size = tracks.size();
     for (size_t i = 0; i < size; i++) {
         sp t = tracks[i];
         mTracks.remove(t);
-        deleteTrackName(t->name());
+        deleteTrackName_l(t->name());
     }
 }
 
-void AudioFlinger::MixerThread::putTracks(
+// putTracks_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::MixerThread::putTracks_l(
         SortedVector < sp >& tracks,
         SortedVector < wp >& activeTracks)
 {
 
-    LOGV ("MixerThread::putTracks() for output %d, tracks.size %d, activeTracks.size %d", mOutputType,  tracks.size(), activeTracks.size());
+    LOGV ("MixerThread::putTracks_l() for output %d, tracks.size %d, activeTracks.size %d", mOutputType,  tracks.size(), activeTracks.size());
 
     size_t size = tracks.size();
     for (size_t i = 0; i < size ; i++) {
         sp t = tracks[i];
-        int name = getTrackName();
+        int name = getTrackName_l();
 
         if (name < 0) return;
         
@@ -1298,7 +1294,7 @@ void AudioFlinger::MixerThread::putTracks(
 
         int j = activeTracks.indexOf(t);
         if (j >= 0) {
-            addActiveTrack(t);
+            addActiveTrack_l(t);
         }            
     }
 }
@@ -1390,10 +1386,10 @@ bool AudioFlinger::MixerThread::isMusicActive() const
     return false;
 }
 
-status_t AudioFlinger::MixerThread::addTrack(const sp& track)
+// addTrack_l() must be called with AudioFlinger::mLock held
+status_t AudioFlinger::MixerThread::addTrack_l(const sp& track)
 {
     status_t status = ALREADY_EXISTS;
-    Mutex::Autolock _l(mLock);
 
     // here the track could be either new, or restarted
     // in both cases "unstop" the track
@@ -1412,55 +1408,41 @@ status_t AudioFlinger::MixerThread::addTrack(const sp& track)
         // effectively get the latency it requested.
         track->mFillingUpStatus = Track::FS_FILLING;
         track->mResetDone = false;
-        addActiveTrack(track);
+        addActiveTrack_l(track);
         status = NO_ERROR;
     }
     
     LOGV("mWaitWorkCV.broadcast");
-    mWaitWorkCV.broadcast();
+    mAudioFlinger->mWaitWorkCV.broadcast();
 
     return status;
 }
 
-void AudioFlinger::MixerThread::removeTrack(wp track, int name)
+// removeTrack_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::MixerThread::removeTrack_l(wp track, int name)
 {
-    Mutex::Autolock _l(mLock);
     sp t = track.promote();
     if (t!=NULL && (t->mState <= TrackBase::STOPPED)) {
-        remove_track_l(track, name);
-    }
-}
-
-void AudioFlinger::MixerThread::remove_track_l(wp track, int name)
-{
-    sp t = track.promote();
-    if (t!=NULL) {
         t->reset();
+        deleteTrackName_l(name);
+        removeActiveTrack_l(track);
+        mAudioFlinger->mWaitWorkCV.broadcast();
     }
-    deleteTrackName(name);
-    removeActiveTrack(track);
-    mWaitWorkCV.broadcast();
 }
 
-void AudioFlinger::MixerThread::destroyTrack(const sp& track)
+// destroyTrack_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::MixerThread::destroyTrack_l(const sp& track)
 {
-    // NOTE: We're acquiring a strong reference on the track before
-    // acquiring the lock, this is to make sure removing it from
-    // mTracks won't cause the destructor to be called while the lock is
-    // held (note that technically, 'track' could be a reference to an item
-    // in mTracks, which is why we need to do this).
-    sp keep(track);
-    Mutex::Autolock _l(mLock);
     track->mState = TrackBase::TERMINATED;
     if (mActiveTracks.indexOf(track) < 0) {
         LOGV("remove track (%d) and delete from mixer", track->name());
         mTracks.remove(track);
-        deleteTrackName(keep->name());
+        deleteTrackName_l(track->name());
     }
 }
 
-
-void AudioFlinger::MixerThread::addActiveTrack(const wp& t)
+// addActiveTrack_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::MixerThread::addActiveTrack_l(const wp& t)
 {
     mActiveTracks.add(t);
 
@@ -1476,7 +1458,8 @@ void AudioFlinger::MixerThread::addActiveTrack(const wp& t)
     }
 }
 
-void AudioFlinger::MixerThread::removeActiveTrack(const wp& t)
+// removeActiveTrack_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::MixerThread::removeActiveTrack_l(const wp& t)
 {
     mActiveTracks.remove(t);
 
@@ -1492,12 +1475,14 @@ void AudioFlinger::MixerThread::removeActiveTrack(const wp& t)
     }
 }
 
-int AudioFlinger::MixerThread::getTrackName()
+// getTrackName_l() must be called with AudioFlinger::mLock held
+int AudioFlinger::MixerThread::getTrackName_l()
 {
     return mAudioMixer->getTrackName();
 }
 
-void AudioFlinger::MixerThread::deleteTrackName(int name)
+// deleteTrackName_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::MixerThread::deleteTrackName_l(int name)
 {
     mAudioMixer->deleteTrackName(name);
 }
@@ -1509,6 +1494,7 @@ size_t AudioFlinger::MixerThread::getOutputFrameCount()
 
 // ----------------------------------------------------------------------------
 
+// TrackBase constructor must be called with AudioFlinger::mLock held
 AudioFlinger::MixerThread::TrackBase::TrackBase(
             const sp& mixerThread,
             const sp& client,
@@ -1529,7 +1515,7 @@ AudioFlinger::MixerThread::TrackBase::TrackBase(
         mFormat(format),
         mFlags(flags & ~SYSTEM_FLAGS_MASK)
 {
-    mName = mixerThread->getTrackName();
+    mName = mixerThread->getTrackName_l();
     LOGV("TrackBase contructor name %d, calling thread %d", mName, IPCThreadState::self()->getCallingPid());
     if (mName < 0) {
         LOGE("no more track names availlable");
@@ -1661,6 +1647,7 @@ void* AudioFlinger::MixerThread::TrackBase::getBuffer(uint32_t offset, uint32_t
 
 // ----------------------------------------------------------------------------
 
+// Track constructor must be called with AudioFlinger::mLock held
 AudioFlinger::MixerThread::Track::Track(
             const sp& mixerThread,
             const sp& client,
@@ -1681,13 +1668,26 @@ AudioFlinger::MixerThread::Track::Track(
 AudioFlinger::MixerThread::Track::~Track()
 {
     wp weak(this); // never create a strong ref from the dtor
+    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
     mState = TERMINATED;
-    mMixerThread->removeTrack(weak, mName);
+    mMixerThread->removeTrack_l(weak, mName);
 }
 
 void AudioFlinger::MixerThread::Track::destroy()
 {
-    mMixerThread->destroyTrack(this);
+    // NOTE: destroyTrack_l() can remove a strong reference to this Track 
+    // by removing it from mTracks vector, so there is a risk that this Tracks's
+    // desctructor is called. As the destructor needs to lock AudioFlinger::mLock,
+    // we must acquire a strong reference on this Track before locking AudioFlinger::mLock
+    // here so that the destructor is called only when exiting this function.
+    // On the other hand, as long as Track::destroy() is only called by 
+    // TrackHandle destructor, the TrackHandle still holds a strong ref on 
+    // this Track with its member mTrack.
+    sp keep(this);
+    { // scope for AudioFlinger::mLock
+        Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
+        mMixerThread->destroyTrack_l(this);
+    }
 }
 
 void AudioFlinger::MixerThread::Track::dump(char* buffer, size_t size)
@@ -1765,14 +1765,15 @@ bool AudioFlinger::MixerThread::Track::isReady() const {
 status_t AudioFlinger::MixerThread::Track::start()
 {
     LOGV("start(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType);
-    mMixerThread->addTrack(this);
+    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
+    mMixerThread->addTrack_l(this);
     return NO_ERROR;
 }
 
 void AudioFlinger::MixerThread::Track::stop()
 {
     LOGV("stop(%d), calling thread %d for output %d", mName, IPCThreadState::self()->getCallingPid(), mMixerThread->mOutputType);
-    Mutex::Autolock _l(mMixerThread->mLock);
+    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
     if (mState > STOPPED) {
         mState = STOPPED;
         // If the track is not active (PAUSED and buffers full), flush buffers
@@ -1786,7 +1787,7 @@ void AudioFlinger::MixerThread::Track::stop()
 void AudioFlinger::MixerThread::Track::pause()
 {
     LOGV("pause(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid());
-    Mutex::Autolock _l(mMixerThread->mLock);
+    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
     if (mState == ACTIVE || mState == RESUMING) {
         mState = PAUSING;
         LOGV("ACTIVE/RESUMING => PAUSING (%d)", mName);
@@ -1796,7 +1797,7 @@ void AudioFlinger::MixerThread::Track::pause()
 void AudioFlinger::MixerThread::Track::flush()
 {
     LOGV("flush(%d)", mName);
-    Mutex::Autolock _l(mMixerThread->mLock);
+    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
     if (mState != STOPPED && mState != PAUSED && mState != PAUSING) {
         return;
     }
@@ -1840,6 +1841,7 @@ void AudioFlinger::MixerThread::Track::setVolume(float left, float right)
 
 // ----------------------------------------------------------------------------
 
+// RecordTrack constructor must be called with AudioFlinger::mLock held
 AudioFlinger::MixerThread::RecordTrack::RecordTrack(
             const sp& mixerThread,
             const sp& client,
@@ -1857,7 +1859,8 @@ AudioFlinger::MixerThread::RecordTrack::RecordTrack(
 
 AudioFlinger::MixerThread::RecordTrack::~RecordTrack()
 {
-    mMixerThread->deleteTrackName(mName);
+    Mutex::Autolock _l(mMixerThread->mAudioFlinger->mLock);
+    mMixerThread->deleteTrackName_l(mName);
 }
 
 status_t AudioFlinger::MixerThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
@@ -2183,7 +2186,6 @@ sp AudioFlinger::openRecord(
         uint32_t flags,
         status_t *status)
 {
-    sp thread;
     sp recordTrack;
     sp recordHandle;
     sp client;
@@ -2227,7 +2229,7 @@ sp AudioFlinger::openRecord(
     }
 
     // add client to list
-    {
+    { // scope for mLock
         Mutex::Autolock _l(mLock);
         wclient = mClients.valueFor(pid);
         if (wclient != NULL) {
@@ -2236,15 +2238,15 @@ sp AudioFlinger::openRecord(
             client = new Client(this, pid);
             mClients.add(pid, client);
         }
+
+        // frameCount must be a multiple of input buffer size
+        inFrameCount = inputBufferSize/channelCount/sizeof(short);
+        frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
+    
+        // create new record track. The record track uses one track in mHardwareMixerThread by convention.
+        recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, streamType, sampleRate,
+                                                   format, channelCount, frameCount, flags);
     }
-
-    // frameCount must be a multiple of input buffer size
-    inFrameCount = inputBufferSize/channelCount/sizeof(short);
-    frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
-
-    // create new record track and pass to record thread
-    recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, streamType, sampleRate,
-                                               format, channelCount, frameCount, flags);
     if (recordTrack->getCblk() == NULL) {
         recordTrack.clear();
         lStatus = NO_MEMORY;
@@ -2369,7 +2371,8 @@ bool AudioFlinger::AudioRecordThread::threadLoop()
         } else if (mRecordTrack != 0) {
 
             buffer.frameCount = inFrameCount;
-            if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR)) {
+            if (LIKELY(mRecordTrack->getNextBuffer(&buffer) == NO_ERROR &&
+                       (int)buffer.frameCount == inFrameCount)) {
                 LOGV("AudioRecordThread read: %d frames", buffer.frameCount);
                 ssize_t bytesRead = input->read(buffer.raw, inBufferSize);
                 if (bytesRead < 0) {
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index 77f064b237416..c505336c0ebb9 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -112,7 +112,7 @@ public:
     
     virtual     size_t      getInputBufferSize(uint32_t sampleRate, int format, int channelCount);
     
-    virtual     void        wakeUp();
+    virtual     void        wakeUp()    { mWaitWorkCV.broadcast(); }
     
     // IBinder::DeathRecipient
     virtual     void        binderDied(const wp& who);
@@ -161,7 +161,8 @@ private:
     void                    doSetOutput(int outputType);
 
 #ifdef WITH_A2DP
-    void                    setA2dpEnabled(bool enable);
+    void                    setA2dpEnabled_l(bool enable);
+    void                    checkA2dpEnabledChange_l();
 #endif
     static bool             streamForcedToSpeaker(int streamType);
     
@@ -459,7 +460,7 @@ private:
                     bool        isMusicActive() const;
         
                     
-        sp createTrack(
+                    sp   createTrack_l(
                                     const sp& client,
                                     int streamType,
                                     uint32_t sampleRate,
@@ -468,12 +469,10 @@ private:
                                     int frameCount,
                                     const sp& sharedBuffer,
                                     status_t *status);
-
-                    void        wakeUp() { mWaitWorkCV.broadcast(); }
                     
-                    void        getTracks(SortedVector < sp >& tracks,
+                    void        getTracks_l(SortedVector < sp >& tracks,
                                           SortedVector < wp >& activeTracks);
-                    void        putTracks(SortedVector < sp >& tracks,
+                    void        putTracks_l(SortedVector < sp >& tracks,
                                           SortedVector < wp >& activeTracks);
                     void        setOuputTrack(OutputTrack *track) { mOutputTrack = track; }
                     
@@ -498,22 +497,19 @@ private:
         MixerThread(const Client&);
         MixerThread& operator = (const MixerThread&);
   
-        status_t    addTrack(const sp& track);
-        void        removeTrack(wp track, int name);
-        void        remove_track_l(wp track, int name);
-        void        destroyTrack(const sp& track);
-        int         getTrackName();
-        void        deleteTrackName(int name);
-        void        addActiveTrack(const wp& t);
-        void        removeActiveTrack(const wp& t);
+        status_t    addTrack_l(const sp& track);
+        void        removeTrack_l(wp track, int name);
+        void        destroyTrack_l(const sp& track);
+        int         getTrackName_l();
+        void        deleteTrackName_l(int name);
+        void        addActiveTrack_l(const wp& t);
+        void        removeActiveTrack_l(const wp& t);
         size_t      getOutputFrameCount();
 
         status_t    dumpInternals(int fd, const Vector& args);
         status_t    dumpTracks(int fd, const Vector& args);
         
         sp                mAudioFlinger;       
-        mutable     Mutex               mLock;
-        mutable     Condition           mWaitWorkCV;
         SortedVector< wp >       mActiveTracks;
         SortedVector< sp >       mTracks;
         stream_type_t                   mStreamTypes[AudioSystem::NUM_STREAM_TYPES];
@@ -607,11 +603,11 @@ private:
 
                 status_t    startRecord(MixerThread::RecordTrack* recordTrack);
                 void        stopRecord(MixerThread::RecordTrack* recordTrack);
-                
-                void        handleOutputSwitch();
 
-    mutable     Mutex                                       mHardwareLock;
-    mutable     Mutex                                       mLock;
+    mutable     Mutex                               mHardwareLock;
+    mutable     Mutex                               mLock;
+    mutable     Condition                           mWaitWorkCV;
+
                 DefaultKeyedVector< pid_t, wp >     mClients;
 
                 sp                     mA2dpMixerThread;
@@ -620,7 +616,7 @@ private:
                 AudioHardwareInterface*             mA2dpAudioInterface;
                 sp               mAudioRecordThread;
                 bool                                mA2dpEnabled;
-                bool                                mA2dpEnabledReq;
+                bool                                mNotifyA2dpChange;
     mutable     int                                 mHardwareStatus;
                 SortedVector< wp >         mNotificationClients;
                 int                                 mForcedSpeakerCount;
diff --git a/location/data/Android.mk b/location/data/Android.mk
index befd79299a472..794e6c7bf0d8d 100644
--- a/location/data/Android.mk
+++ b/location/data/Android.mk
@@ -13,7 +13,7 @@ include $(CLEAR_VARS)
 
 LOCAL_MODULE := nmea
 
-LOCAL_MODULE_TAGS := development
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE_PATH := $(local_target_dir)/gps
@@ -27,7 +27,7 @@ include $(CLEAR_VARS)
 
 LOCAL_MODULE := location
 
-LOCAL_MODULE_TAGS := development
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE_PATH := $(local_target_dir)/gps
@@ -41,7 +41,7 @@ include $(CLEAR_VARS)
 
 LOCAL_MODULE := properties
 
-LOCAL_MODULE_TAGS := development
+LOCAL_MODULE_TAGS := tests
 
 LOCAL_MODULE_CLASS := ETC
 LOCAL_MODULE_PATH := $(local_target_dir)/gps
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 5416629b8e10a..856059328e4b5 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -182,8 +182,9 @@ bool ToneGenerator::startTone(int toneType) {
             mLock.lock();
             if (mState == TONE_STARTING) {
                 LOGV("Wait for start callback");
-                if (mWaitCbkCond.waitRelative(mLock, seconds(1)) != NO_ERROR) {
-                    LOGE("--- Immediate start timed out");
+                status_t lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1));
+                if (lStatus != NO_ERROR) {
+                    LOGE("--- Immediate start timed out, status %d", lStatus);
                     mState = TONE_IDLE;
                     lResult = false;
                 }
@@ -195,13 +196,14 @@ bool ToneGenerator::startTone(int toneType) {
         LOGV("Delayed start\n");
 
         mState = TONE_RESTARTING;
-        if (mWaitCbkCond.waitRelative(mLock, seconds(1)) == NO_ERROR) {
+        status_t lStatus = mWaitCbkCond.waitRelative(mLock, seconds(1));
+        if (lStatus == NO_ERROR) {
             if (mState != TONE_IDLE) {
                 lResult = true;
             }
             LOGV("cond received");
         } else {
-            LOGE("--- Delayed start timed out");
+            LOGE("--- Delayed start timed out, status %d", lStatus);
             mState = TONE_IDLE;
         }
     }
@@ -368,6 +370,8 @@ void ToneGenerator::audioCallback(int event, void* user, void *info) {
             break;
         default:
             LOGV("Extra Cbk");
+            // Force loop exit
+            lNumSmp = 0;
             goto audioCallback_EndLoop;
         }
         
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
index 5e9c4882fb104..07b43bb34f107 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
@@ -494,4 +494,18 @@ public class MediaNames {
     "/sdcard/media_api/video_stress/h263/mpeg4_QVGA.3gp",
     "/sdcard/media_api/video_stress/h263/mpeg4_SQVGA.mp4"
   };
+  
+  //Streaming test files
+  public static final String STREAM_H264_480_360_1411k = 
+      "http://sridharg.googlejunta.com/yslau/stress_media/h264_regular.mp4"; 
+  public static final String STREAM_WMV = 
+      "http://sridharg.googlejunta.com/yslau/stress_media/bugs.wmv"; 
+  public static final String STREAM_H263_176x144_325k = 
+      "http://sridharg.googlejunta.com/yslau/stress_media/h263_regular.3gp";
+  public static final String STREAM_H264_352x288_1536k = 
+      "http://sridharg.googlejunta.com/yslau/stress_media/h264_highBitRate.mp4";
+  public static final String STREAM_MP3= 
+      "http://sridharg.googlejunta.com/yslau/stress_media/mp3_regular.mp3";
+  public static final String STREAM_MPEG4_QVGA_128k = 
+      "http://sridharg.googlejunta.com/yslau/stress_media/mpeg4_qvga_24fps.3gp";
 }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
index 0e88719de6bf3..caba47c58c388 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CodecTest.java
@@ -28,6 +28,7 @@ import android.graphics.BitmapFactory;
 import android.media.MediaMetadataRetriever;
 import android.media.MediaPlayer;
 import android.media.MediaRecorder;
+import android.os.Looper;
 import android.os.SystemClock;
 import android.util.Log;
 
@@ -39,6 +40,16 @@ import java.io.InputStream;
  */  
 public class CodecTest {    
     private static String TAG = "MediaPlayerApiTest";
+    private static MediaPlayer mMediaPlayer;
+    private MediaPlayer.OnPreparedListener mOnPreparedListener;
+    
+    private static int WAIT_FOR_COMMAND_TO_COMPLETE = 10000;  //10 seconds max.
+    private static boolean mInitialized = false;
+    private static Looper mLooper = null;
+    private static final Object lock = new Object();
+    private static final Object prepareDone = new Object();
+    private static boolean onPrepareSuccess = false;
+    
 
     public static String printCpuInfo(){      
         String cm = "dumpsys cpuinfo";
@@ -573,5 +584,89 @@ public class CodecTest {
 
         return true;
     }
+    
+    /*
+     * Initializes the message looper so that the mediaPlayer object can 
+     * receive the callback messages.
+     */
+    private static void initializeMessageLooper() {
+        Log.v(TAG, "start looper");
+        new Thread() {
+            @Override
+            public void run() {
+                // Set up a looper to be used by camera.
+                Looper.prepare();
+                Log.v(TAG, "start loopRun");
+                // Save the looper so that we can terminate this thread 
+                // after we are done with it.
+                mLooper = Looper.myLooper();                
+                mMediaPlayer = new MediaPlayer();                                
+                synchronized (lock) {
+                    mInitialized = true;
+                    lock.notify();
+                }
+                Looper.loop();  // Blocks forever until Looper.quit() is called.
+                Log.v(TAG, "initializeMessageLooper: quit.");
+            }
+        }.start();
+    }
+    
+    /*
+     * Terminates the message looper thread.
+     */
+    private static void terminateMessageLooper() {
+        mLooper.quit();
+        mMediaPlayer.release();
+    }
+    
+    static MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener() {
+        public void onPrepared(MediaPlayer mp) {
+            synchronized (prepareDone) {
+                Log.v(TAG, "notify the prepare callback");
+                prepareDone.notify();
+                onPrepareSuccess = true;
+            }
+        }
+    };
+   
+    public static boolean prepareAsyncCallback(String filePath) throws Exception {
+        int videoWidth = 0;
+        int videoHeight = 0;
+        boolean checkVideoDimension = false;
+        
+        initializeMessageLooper();
+        synchronized (lock) {
+            try {
+                lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+            } catch(Exception e) {
+                Log.v(TAG, "looper was interrupted.");
+                return false;
+            }
+        }
+        try{
+            mMediaPlayer.setOnPreparedListener(mPreparedListener);
+            mMediaPlayer.setDataSource(filePath);
+            mMediaPlayer.setDisplay(MediaFrameworkTest.mSurfaceView.getHolder());
+            mMediaPlayer.prepareAsync(); 
+            synchronized (prepareDone) {
+                try {
+                    prepareDone.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+                    Log.v(TAG, "setPreview done");
+                } catch (Exception e) {
+                    Log.v(TAG, "wait was interrupted.");
+                }
+            }
+            videoWidth = mMediaPlayer.getVideoWidth();
+            videoHeight = mMediaPlayer.getVideoHeight();
+            
+            terminateMessageLooper();
+        }catch (Exception e){
+            Log.v(TAG,e.getMessage());
+        }      
+       return onPrepareSuccess;
+    }
+    
+    
+    
 }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java
index dd94164d95ce4..ee6a727dadb73 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaPlayerApiTest.java
@@ -52,7 +52,8 @@ public class MediaPlayerApiTest extends ActivityInstrumentationTestCase connected = mBluetoothA2dp.listConnectedSinks();
+
+        for (String address : connected) {
+            if (mBluetoothA2dp.getSinkState(address) == BluetoothA2dp.STATE_PLAYING) {
+                isBluetoothPlaying = true;
+                break;
+            }
+        }
+        setBluetoothScanMode(isBluetoothPlaying);
+    }
+
     @Override
     public void releaseWakeLock() {
         if (mReleaseWakeLockCallback != null) {
@@ -682,9 +711,13 @@ public class WifiStateTracker extends NetworkStateTracker {
                  * are going to end up being thrown away. Obviously, if we
                  * ever want to support multicast, this will have to change.
                  */
+                if (mBluetoothA2dp == null) {
+                    mBluetoothA2dp = new BluetoothA2dp(mContext);
+                }
                 synchronized (this) {
                     WifiNative.startPacketFiltering();
                 }
+                checkIsBluetoothPlaying();
                 break;
 
             case EVENT_SUPPLICANT_DISCONNECT: