summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.xml346
-rw-r--r--cmds/dumpstate/dumpstate.c14
-rw-r--r--cmds/installd/commands.c6
-rwxr-xr-xcore/java/android/animation/ValueAnimator.java14
-rw-r--r--core/java/android/app/ActivityManager.java8
-rw-r--r--core/java/android/app/NativeActivity.java23
-rw-r--r--core/java/android/bluetooth/BluetoothA2dp.java28
-rw-r--r--core/java/android/bluetooth/BluetoothDeviceProfileState.java2
-rw-r--r--core/java/android/bluetooth/BluetoothHeadset.java31
-rw-r--r--core/java/android/bluetooth/BluetoothInputDevice.java16
-rw-r--r--core/java/android/bluetooth/BluetoothPan.java20
-rw-r--r--core/java/android/bluetooth/BluetoothProfile.java13
-rw-r--r--core/java/android/bluetooth/IBluetooth.aidl4
-rw-r--r--core/java/android/bluetooth/IBluetoothA2dp.aidl5
-rw-r--r--core/java/android/bluetooth/IBluetoothHeadset.aidl5
-rw-r--r--core/java/android/content/pm/PackageParser.java10
-rw-r--r--core/java/android/hardware/Camera.java6
-rw-r--r--core/java/android/net/http/CertificateChainValidator.java53
-rw-r--r--core/java/android/nfc/NdefMessage.java8
-rw-r--r--core/java/android/nfc/NdefRecord.java3
-rw-r--r--core/java/android/nfc/NdefTag.java207
-rw-r--r--core/java/android/nfc/NdefTagConnection.java10
-rw-r--r--core/java/android/nfc/NfcAdapter.java12
-rw-r--r--core/java/android/nfc/RawTagConnection.java6
-rw-r--r--core/java/android/nfc/Tag.java305
-rw-r--r--core/java/android/os/Build.java10
-rw-r--r--core/java/android/os/StrictMode.java12
-rw-r--r--core/java/android/server/BluetoothA2dpService.java22
-rw-r--r--core/java/android/server/BluetoothEventLoop.java9
-rw-r--r--core/java/android/server/BluetoothService.java44
-rw-r--r--core/java/android/util/DisplayMetrics.java5
-rw-r--r--core/java/android/webkit/CookieManager.java22
-rw-r--r--core/java/android/webkit/WebView.java7
-rw-r--r--core/java/android/webkit/WebViewCore.java7
-rw-r--r--core/java/android/webkit/ZoomManager.java4
-rw-r--r--core/java/android/widget/AbsListView.java11
-rw-r--r--core/java/android/widget/AdapterViewAnimator.java65
-rw-r--r--core/java/android/widget/SearchView.java4
-rw-r--r--core/java/android/widget/StackView.java64
-rw-r--r--core/java/android/widget/TextView.java3
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java453
-rw-r--r--core/java/com/android/internal/view/StandaloneActionMode.java1
-rw-r--r--core/java/com/android/internal/widget/ActionBarContextView.java2
-rw-r--r--core/jni/android/graphics/Bitmap.cpp8
-rw-r--r--core/jni/android/graphics/BitmapRegionDecoder.cpp13
-rw-r--r--core/jni/android/graphics/Matrix.cpp4
-rw-r--r--core/jni/android/graphics/Paint.cpp4
-rw-r--r--core/jni/android_app_NativeActivity.cpp10
-rw-r--r--core/jni/android_nfc_NdefMessage.cpp2
-rw-r--r--core/jni/android_nfc_NdefRecord.cpp2
-rw-r--r--core/res/res/color/primary_text_holo_dark.xml12
-rw-r--r--core/res/res/color/primary_text_holo_light.xml12
-rw-r--r--core/res/res/color/secondary_text_holo_dark.xml18
-rw-r--r--core/res/res/color/secondary_text_holo_light.xml18
-rw-r--r--core/res/res/color/tertiary_text_holo_dark.xml2
-rw-r--r--core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.pngbin686 -> 666 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.pngbin701 -> 639 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.pngbin617 -> 407 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.pngbin592 -> 395 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.pngbin783 -> 822 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.pngbin734 -> 741 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.pngbin778 -> 839 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.pngbin707 -> 661 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.pngbin766 -> 803 bytes
-rw-r--r--core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.pngbin913 -> 970 bytes
-rw-r--r--core/res/res/drawable-hdpi/list_activated_holo.9.pngbin0 -> 206 bytes
-rw-r--r--core/res/res/drawable-hdpi/list_divider_holo_dark.9.pngbin0 -> 122 bytes
-rw-r--r--core/res/res/drawable-hdpi/list_divider_holo_light.9.pngbin0 -> 123 bytes
-rw-r--r--core/res/res/drawable-hdpi/list_focused_holo.9.pngbin0 -> 216 bytes
-rw-r--r--core/res/res/drawable-hdpi/list_longpressed_holo.9.pngbin0 -> 178 bytes
-rw-r--r--core/res/res/drawable-hdpi/list_pressed_holo_dark.9.pngbin0 -> 179 bytes
-rw-r--r--core/res/res/drawable-hdpi/list_pressed_holo_light.9.pngbin0 -> 178 bytes
-rw-r--r--core/res/res/drawable-hdpi/list_section_divider_holo_dark.9.pngbin0 -> 217 bytes
-rw-r--r--core/res/res/drawable-hdpi/list_section_divider_holo_light.9.pngbin0 -> 216 bytes
-rw-r--r--core/res/res/drawable-hdpi/list_selected_holo_dark.9.pngbin0 -> 202 bytes
-rw-r--r--core/res/res/drawable-hdpi/list_selected_holo_light.9.pngbin0 -> 193 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.pngbin520 -> 461 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.pngbin553 -> 465 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.pngbin470 -> 301 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.pngbin452 -> 306 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.pngbin590 -> 520 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.pngbin571 -> 512 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.pngbin557 -> 541 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.pngbin528 -> 432 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.pngbin584 -> 489 bytes
-rw-r--r--core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.pngbin635 -> 590 bytes
-rw-r--r--core/res/res/drawable-mdpi/list_activated_holo.9.pngbin0 -> 188 bytes
-rw-r--r--core/res/res/drawable-mdpi/list_divider_holo_dark.9.pngbin0 -> 122 bytes
-rw-r--r--core/res/res/drawable-mdpi/list_divider_holo_light.9.pngbin0 -> 123 bytes
-rw-r--r--core/res/res/drawable-mdpi/list_focused_holo.9.pngbin0 -> 202 bytes
-rw-r--r--core/res/res/drawable-mdpi/list_longpressed_holo.9.pngbin0 -> 167 bytes
-rw-r--r--core/res/res/drawable-mdpi/list_pressed_holo_dark.9.pngbin0 -> 168 bytes
-rw-r--r--core/res/res/drawable-mdpi/list_pressed_holo_light.9.pngbin0 -> 167 bytes
-rw-r--r--core/res/res/drawable-mdpi/list_section_divider_holo_dark.9.pngbin0 -> 205 bytes
-rw-r--r--core/res/res/drawable-mdpi/list_section_divider_holo_light.9.pngbin0 -> 205 bytes
-rw-r--r--core/res/res/drawable-mdpi/list_selected_holo_dark.9.pngbin0 -> 188 bytes
-rw-r--r--core/res/res/drawable-mdpi/list_selected_holo_light.9.pngbin0 -> 188 bytes
-rw-r--r--core/res/res/drawable/activated_background_holo_dark.xml2
-rw-r--r--core/res/res/drawable/activated_background_holo_light.xml2
-rw-r--r--core/res/res/drawable/btn_default_holo_light.xml32
-rw-r--r--core/res/res/drawable/list_selector_background_transition_holo_dark.xml20
-rw-r--r--core/res/res/drawable/list_selector_background_transition_holo_light.xml20
-rw-r--r--core/res/res/drawable/list_selector_holo_dark.xml6
-rw-r--r--core/res/res/drawable/list_selector_holo_light.xml6
-rw-r--r--core/res/res/values-zh-rCN/donottranslate-cldr.xml4
-rw-r--r--core/res/res/values/attrs_manifest.xml32
-rw-r--r--core/res/res/values/public.xml2
-rw-r--r--core/res/res/values/styles.xml14
-rw-r--r--core/res/res/values/themes.xml9
-rw-r--r--core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java2
-rw-r--r--data/sounds/AllAudio.mk20
-rw-r--r--include/camera/Camera.h12
-rw-r--r--include/media/IOMX.h3
-rw-r--r--include/media/stagefright/HardwareAPI.h26
-rw-r--r--include/ui/InputReader.h28
-rw-r--r--libs/hwui/Android.mk1
-rw-r--r--libs/hwui/Caches.cpp77
-rw-r--r--libs/hwui/Caches.h49
-rw-r--r--libs/hwui/OpenGLRenderer.cpp38
-rw-r--r--libs/hwui/Rect.h8
-rw-r--r--libs/rs/Android.mk10
-rw-r--r--libs/rs/rsScriptC.cpp6
-rw-r--r--libs/rs/rslib.bcbin0 -> 716 bytes
-rw-r--r--libs/ui/EventHub.cpp3
-rw-r--r--libs/ui/InputDispatcher.cpp11
-rw-r--r--libs/ui/InputReader.cpp71
-rw-r--r--libs/ui/tests/Android.mk1
-rw-r--r--libs/ui/tests/InputDispatcher_test.cpp214
-rw-r--r--libs/ui/tests/InputReader_test.cpp3381
-rw-r--r--libs/utils/ZipFileRO.cpp10
-rw-r--r--media/java/android/media/AudioService.java11
-rw-r--r--media/jni/audioeffect/android_media_Visualizer.cpp1
-rw-r--r--media/libmedia/IOMX.cpp28
-rw-r--r--media/libstagefright/include/OMX.h3
-rw-r--r--media/libstagefright/include/OMXNodeInstance.h1
-rw-r--r--media/libstagefright/omx/OMX.cpp5
-rw-r--r--media/libstagefright/omx/OMXNodeInstance.cpp31
-rw-r--r--native/copy-to-ndk.sh10
-rw-r--r--native/include/android/input.h2
-rw-r--r--native/include/android/native_activity.h32
-rw-r--r--packages/SystemUI/res/anim/notification_dnd_off.xml23
-rw-r--r--packages/SystemUI/res/anim/notification_dnd_on.xml23
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.pngbin636 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_avail.pngbin0 -> 247 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_avail_open.pngbin0 -> 503 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_dnd.pngbin0 -> 393 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_none.pngbin0 -> 185 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_none_open.pngbin0 -> 393 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/status_bar_back_default.pngbin398 -> 48936 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/status_bar_back_pressed.pngbin3215 -> 49157 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/status_bar_home_default.pngbin376 -> 646 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/status_bar_home_pressed.pngbin3373 -> 646 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/status_bar_recent_default.pngbin350 -> 331 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/status_bar_recent_pressed.pngbin3060 -> 331 bytes
-rw-r--r--packages/SystemUI/res/layout-xlarge/status_bar.xml131
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml32
-rw-r--r--packages/SystemUI/res/values-da/strings.xml32
-rw-r--r--packages/SystemUI/res/values-de/strings.xml32
-rw-r--r--packages/SystemUI/res/values-el/strings.xml32
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml32
-rw-r--r--packages/SystemUI/res/values-es/strings.xml32
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml32
-rw-r--r--packages/SystemUI/res/values-it/strings.xml32
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml32
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml32
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml32
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml32
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml32
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml32
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml32
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml32
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml32
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml32
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml32
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java46
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java27
-rw-r--r--services/camera/libcameraservice/CameraService.cpp61
-rw-r--r--services/camera/libcameraservice/CameraService.h4
-rw-r--r--services/java/com/android/server/PackageManagerService.java4
-rw-r--r--services/java/com/android/server/PowerManagerService.java18
-rw-r--r--services/java/com/android/server/TelephonyRegistry.java1
-rw-r--r--services/java/com/android/server/WindowManagerService.java13
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java28
-rwxr-xr-xservices/java/com/android/server/location/GpsLocationProvider.java21
-rw-r--r--tests/DpiTest/AndroidManifest.xml6
-rw-r--r--tools/aapt/Command.cpp59
-rw-r--r--tools/layoutlib/bridge/.classpath2
-rw-r--r--tools/layoutlib/bridge/Android.mk2
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java12
-rw-r--r--tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java41
-rw-r--r--wifi/java/android/net/wifi/WifiStateMachine.java5
193 files changed, 6214 insertions, 1204 deletions
diff --git a/api/current.xml b/api/current.xml
index 22a105a..e3fcfcf 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -1773,7 +1773,7 @@
type="int"
transient="false"
volatile="false"
- value="16843511"
+ value="16843513"
static="true"
final="true"
deprecated="not deprecated"
@@ -1784,7 +1784,7 @@
type="int"
transient="false"
volatile="false"
- value="16843480"
+ value="16843482"
static="true"
final="true"
deprecated="not deprecated"
@@ -1795,7 +1795,7 @@
type="int"
transient="false"
volatile="false"
- value="16843520"
+ value="16843522"
static="true"
final="true"
deprecated="not deprecated"
@@ -1806,7 +1806,7 @@
type="int"
transient="false"
volatile="false"
- value="16843519"
+ value="16843521"
static="true"
final="true"
deprecated="not deprecated"
@@ -1817,7 +1817,7 @@
type="int"
transient="false"
volatile="false"
- value="16843521"
+ value="16843523"
static="true"
final="true"
deprecated="not deprecated"
@@ -1828,7 +1828,7 @@
type="int"
transient="false"
volatile="false"
- value="16843490"
+ value="16843492"
static="true"
final="true"
deprecated="not deprecated"
@@ -1839,7 +1839,7 @@
type="int"
transient="false"
volatile="false"
- value="16843489"
+ value="16843491"
static="true"
final="true"
deprecated="not deprecated"
@@ -1850,7 +1850,7 @@
type="int"
transient="false"
volatile="false"
- value="16843527"
+ value="16843529"
static="true"
final="true"
deprecated="not deprecated"
@@ -1861,7 +1861,7 @@
type="int"
transient="false"
volatile="false"
- value="16843493"
+ value="16843495"
static="true"
final="true"
deprecated="not deprecated"
@@ -1872,7 +1872,7 @@
type="int"
transient="false"
volatile="false"
- value="16843523"
+ value="16843525"
static="true"
final="true"
deprecated="not deprecated"
@@ -1883,7 +1883,7 @@
type="int"
transient="false"
volatile="false"
- value="16843494"
+ value="16843496"
static="true"
final="true"
deprecated="not deprecated"
@@ -1894,7 +1894,7 @@
type="int"
transient="false"
volatile="false"
- value="16843547"
+ value="16843549"
static="true"
final="true"
deprecated="not deprecated"
@@ -1905,7 +1905,7 @@
type="int"
transient="false"
volatile="false"
- value="16843546"
+ value="16843548"
static="true"
final="true"
deprecated="not deprecated"
@@ -1916,7 +1916,7 @@
type="int"
transient="false"
volatile="false"
- value="16843548"
+ value="16843550"
static="true"
final="true"
deprecated="not deprecated"
@@ -1927,7 +1927,7 @@
type="int"
transient="false"
volatile="false"
- value="16843522"
+ value="16843524"
static="true"
final="true"
deprecated="not deprecated"
@@ -1938,7 +1938,7 @@
type="int"
transient="false"
volatile="false"
- value="16843528"
+ value="16843530"
static="true"
final="true"
deprecated="not deprecated"
@@ -1949,7 +1949,7 @@
type="int"
transient="false"
volatile="false"
- value="16843529"
+ value="16843531"
static="true"
final="true"
deprecated="not deprecated"
@@ -2004,7 +2004,7 @@
type="int"
transient="false"
volatile="false"
- value="16843466"
+ value="16843468"
static="true"
final="true"
deprecated="not deprecated"
@@ -2037,7 +2037,7 @@
type="int"
transient="false"
volatile="false"
- value="16843545"
+ value="16843547"
static="true"
final="true"
deprecated="not deprecated"
@@ -2059,7 +2059,7 @@
type="int"
transient="false"
volatile="false"
- value="16843541"
+ value="16843543"
static="true"
final="true"
deprecated="not deprecated"
@@ -2070,7 +2070,7 @@
type="int"
transient="false"
volatile="false"
- value="16843478"
+ value="16843480"
static="true"
final="true"
deprecated="not deprecated"
@@ -2169,7 +2169,7 @@
type="int"
transient="false"
volatile="false"
- value="16843487"
+ value="16843489"
static="true"
final="true"
deprecated="not deprecated"
@@ -2180,7 +2180,7 @@
type="int"
transient="false"
volatile="false"
- value="16843518"
+ value="16843520"
static="true"
final="true"
deprecated="not deprecated"
@@ -2279,7 +2279,7 @@
type="int"
transient="false"
volatile="false"
- value="16843472"
+ value="16843474"
static="true"
final="true"
deprecated="not deprecated"
@@ -2521,7 +2521,7 @@
type="int"
transient="false"
volatile="false"
- value="16843536"
+ value="16843538"
static="true"
final="true"
deprecated="not deprecated"
@@ -2532,7 +2532,7 @@
type="int"
transient="false"
volatile="false"
- value="16843535"
+ value="16843537"
static="true"
final="true"
deprecated="not deprecated"
@@ -2565,7 +2565,7 @@
type="int"
transient="false"
volatile="false"
- value="16843544"
+ value="16843546"
static="true"
final="true"
deprecated="not deprecated"
@@ -2983,7 +2983,7 @@
type="int"
transient="false"
volatile="false"
- value="16843475"
+ value="16843477"
static="true"
final="true"
deprecated="not deprecated"
@@ -3137,7 +3137,7 @@
type="int"
transient="false"
volatile="false"
- value="16843484"
+ value="16843486"
static="true"
final="true"
deprecated="not deprecated"
@@ -3346,7 +3346,7 @@
type="int"
transient="false"
volatile="false"
- value="16843540"
+ value="16843542"
static="true"
final="true"
deprecated="not deprecated"
@@ -3423,7 +3423,7 @@
type="int"
transient="false"
volatile="false"
- value="16843482"
+ value="16843484"
static="true"
final="true"
deprecated="not deprecated"
@@ -3467,7 +3467,7 @@
type="int"
transient="false"
volatile="false"
- value="16843543"
+ value="16843545"
static="true"
final="true"
deprecated="not deprecated"
@@ -3643,7 +3643,7 @@
type="int"
transient="false"
volatile="false"
- value="16843488"
+ value="16843490"
static="true"
final="true"
deprecated="not deprecated"
@@ -4215,7 +4215,7 @@
type="int"
transient="false"
volatile="false"
- value="16843501"
+ value="16843503"
static="true"
final="true"
deprecated="not deprecated"
@@ -4226,7 +4226,7 @@
type="int"
transient="false"
volatile="false"
- value="16843505"
+ value="16843507"
static="true"
final="true"
deprecated="not deprecated"
@@ -4237,7 +4237,7 @@
type="int"
transient="false"
volatile="false"
- value="16843506"
+ value="16843508"
static="true"
final="true"
deprecated="not deprecated"
@@ -4248,7 +4248,7 @@
type="int"
transient="false"
volatile="false"
- value="16843507"
+ value="16843509"
static="true"
final="true"
deprecated="not deprecated"
@@ -4259,7 +4259,7 @@
type="int"
transient="false"
volatile="false"
- value="16843508"
+ value="16843510"
static="true"
final="true"
deprecated="not deprecated"
@@ -4270,7 +4270,7 @@
type="int"
transient="false"
volatile="false"
- value="16843503"
+ value="16843505"
static="true"
final="true"
deprecated="not deprecated"
@@ -4281,7 +4281,7 @@
type="int"
transient="false"
volatile="false"
- value="16843504"
+ value="16843506"
static="true"
final="true"
deprecated="not deprecated"
@@ -4292,7 +4292,7 @@
type="int"
transient="false"
volatile="false"
- value="16843509"
+ value="16843511"
static="true"
final="true"
deprecated="not deprecated"
@@ -4303,7 +4303,7 @@
type="int"
transient="false"
volatile="false"
- value="16843510"
+ value="16843512"
static="true"
final="true"
deprecated="not deprecated"
@@ -4325,7 +4325,7 @@
type="int"
transient="false"
volatile="false"
- value="16843470"
+ value="16843472"
static="true"
final="true"
deprecated="not deprecated"
@@ -4358,7 +4358,7 @@
type="int"
transient="false"
volatile="false"
- value="16843473"
+ value="16843475"
static="true"
final="true"
deprecated="not deprecated"
@@ -4655,7 +4655,7 @@
type="int"
transient="false"
volatile="false"
- value="16843485"
+ value="16843487"
static="true"
final="true"
deprecated="not deprecated"
@@ -4787,7 +4787,7 @@
type="int"
transient="false"
volatile="false"
- value="16843526"
+ value="16843528"
static="true"
final="true"
deprecated="not deprecated"
@@ -4908,7 +4908,7 @@
type="int"
transient="false"
volatile="false"
- value="16843514"
+ value="16843516"
static="true"
final="true"
deprecated="not deprecated"
@@ -4919,7 +4919,7 @@
type="int"
transient="false"
volatile="false"
- value="16843512"
+ value="16843514"
static="true"
final="true"
deprecated="not deprecated"
@@ -4930,7 +4930,7 @@
type="int"
transient="false"
volatile="false"
- value="16843513"
+ value="16843515"
static="true"
final="true"
deprecated="not deprecated"
@@ -5953,7 +5953,7 @@
type="int"
transient="false"
volatile="false"
- value="16843516"
+ value="16843518"
static="true"
final="true"
deprecated="not deprecated"
@@ -5997,7 +5997,7 @@
type="int"
transient="false"
volatile="false"
- value="16843537"
+ value="16843539"
static="true"
final="true"
deprecated="not deprecated"
@@ -6008,7 +6008,7 @@
type="int"
transient="false"
volatile="false"
- value="16843531"
+ value="16843533"
static="true"
final="true"
deprecated="not deprecated"
@@ -6096,7 +6096,7 @@
type="int"
transient="false"
volatile="false"
- value="16843539"
+ value="16843541"
static="true"
final="true"
deprecated="not deprecated"
@@ -6261,7 +6261,7 @@
type="int"
transient="false"
volatile="false"
- value="16843486"
+ value="16843488"
static="true"
final="true"
deprecated="not deprecated"
@@ -6404,7 +6404,7 @@
type="int"
transient="false"
volatile="false"
- value="16843481"
+ value="16843483"
static="true"
final="true"
deprecated="not deprecated"
@@ -6580,7 +6580,7 @@
type="int"
transient="false"
volatile="false"
- value="16843500"
+ value="16843502"
static="true"
final="true"
deprecated="not deprecated"
@@ -6910,7 +6910,7 @@
type="int"
transient="false"
volatile="false"
- value="16843532"
+ value="16843534"
static="true"
final="true"
deprecated="not deprecated"
@@ -7009,7 +7009,7 @@
type="int"
transient="false"
volatile="false"
- value="16843492"
+ value="16843494"
static="true"
final="true"
deprecated="not deprecated"
@@ -7174,7 +7174,7 @@
type="int"
transient="false"
volatile="false"
- value="16843499"
+ value="16843501"
static="true"
final="true"
deprecated="not deprecated"
@@ -7621,6 +7621,17 @@
visibility="public"
>
</field>
+<field name="screenDensity"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843467"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="screenOrientation"
type="int"
transient="false"
@@ -7632,6 +7643,17 @@
visibility="public"
>
</field>
+<field name="screenSize"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843466"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="scrollHorizontally"
type="int"
transient="false"
@@ -7955,7 +7977,7 @@
type="int"
transient="false"
volatile="false"
- value="16843467"
+ value="16843469"
static="true"
final="true"
deprecated="not deprecated"
@@ -8076,7 +8098,7 @@
type="int"
transient="false"
volatile="false"
- value="16843491"
+ value="16843493"
static="true"
final="true"
deprecated="not deprecated"
@@ -8164,7 +8186,7 @@
type="int"
transient="false"
volatile="false"
- value="16843468"
+ value="16843470"
static="true"
final="true"
deprecated="not deprecated"
@@ -8219,7 +8241,7 @@
type="int"
transient="false"
volatile="false"
- value="16843517"
+ value="16843519"
static="true"
final="true"
deprecated="not deprecated"
@@ -8241,7 +8263,7 @@
type="int"
transient="false"
volatile="false"
- value="16843515"
+ value="16843517"
static="true"
final="true"
deprecated="not deprecated"
@@ -8340,7 +8362,7 @@
type="int"
transient="false"
volatile="false"
- value="16843530"
+ value="16843532"
static="true"
final="true"
deprecated="not deprecated"
@@ -8560,7 +8582,7 @@
type="int"
transient="false"
volatile="false"
- value="16843483"
+ value="16843485"
static="true"
final="true"
deprecated="not deprecated"
@@ -8571,7 +8593,7 @@
type="int"
transient="false"
volatile="false"
- value="16843525"
+ value="16843527"
static="true"
final="true"
deprecated="not deprecated"
@@ -8956,7 +8978,7 @@
type="int"
transient="false"
volatile="false"
- value="16843533"
+ value="16843535"
static="true"
final="true"
deprecated="not deprecated"
@@ -9033,7 +9055,7 @@
type="int"
transient="false"
volatile="false"
- value="16843534"
+ value="16843536"
static="true"
final="true"
deprecated="not deprecated"
@@ -9077,7 +9099,7 @@
type="int"
transient="false"
volatile="false"
- value="16843538"
+ value="16843540"
static="true"
final="true"
deprecated="not deprecated"
@@ -9275,7 +9297,7 @@
type="int"
transient="false"
volatile="false"
- value="16843542"
+ value="16843544"
static="true"
final="true"
deprecated="not deprecated"
@@ -9506,7 +9528,7 @@
type="int"
transient="false"
volatile="false"
- value="16843524"
+ value="16843526"
static="true"
final="true"
deprecated="not deprecated"
@@ -9517,7 +9539,7 @@
type="int"
transient="false"
volatile="false"
- value="16843471"
+ value="16843473"
static="true"
final="true"
deprecated="not deprecated"
@@ -9550,7 +9572,7 @@
type="int"
transient="false"
volatile="false"
- value="16843474"
+ value="16843476"
static="true"
final="true"
deprecated="not deprecated"
@@ -9737,7 +9759,7 @@
type="int"
transient="false"
volatile="false"
- value="16843469"
+ value="16843471"
static="true"
final="true"
deprecated="not deprecated"
@@ -9781,7 +9803,7 @@
type="int"
transient="false"
volatile="false"
- value="16843496"
+ value="16843498"
static="true"
final="true"
deprecated="not deprecated"
@@ -9792,7 +9814,7 @@
type="int"
transient="false"
volatile="false"
- value="16843497"
+ value="16843499"
static="true"
final="true"
deprecated="not deprecated"
@@ -9803,7 +9825,7 @@
type="int"
transient="false"
volatile="false"
- value="16843498"
+ value="16843500"
static="true"
final="true"
deprecated="not deprecated"
@@ -10122,7 +10144,7 @@
type="int"
transient="false"
volatile="false"
- value="16843479"
+ value="16843481"
static="true"
final="true"
deprecated="not deprecated"
@@ -10133,7 +10155,7 @@
type="int"
transient="false"
volatile="false"
- value="16843502"
+ value="16843504"
static="true"
final="true"
deprecated="not deprecated"
@@ -10144,7 +10166,7 @@
type="int"
transient="false"
volatile="false"
- value="16843495"
+ value="16843497"
static="true"
final="true"
deprecated="not deprecated"
@@ -10364,7 +10386,7 @@
type="int"
transient="false"
volatile="false"
- value="16843477"
+ value="16843479"
static="true"
final="true"
deprecated="not deprecated"
@@ -10375,7 +10397,7 @@
type="int"
transient="false"
volatile="false"
- value="16843476"
+ value="16843478"
static="true"
final="true"
deprecated="not deprecated"
@@ -22935,17 +22957,6 @@
visibility="public"
>
</field>
-<field name="IMPORTANCE_HEAVY_WEIGHT"
- type="int"
- transient="false"
- volatile="false"
- value="170"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="IMPORTANCE_PERCEPTIBLE"
type="int"
transient="false"
@@ -30357,11 +30368,11 @@
<parameter name="holder" type="android.view.SurfaceHolder">
</parameter>
</method>
-<field name="KEY_NATIVE_SAVED_STATE"
+<field name="META_DATA_FUNC_NAME"
type="java.lang.String"
transient="false"
volatile="false"
- value="&quot;android:native_state&quot;"
+ value="&quot;android.app.func_name&quot;"
static="true"
final="true"
deprecated="not deprecated"
@@ -36131,7 +36142,7 @@
<implements name="android.bluetooth.BluetoothProfile">
</implements>
<method name="getConnectedDevices"
- return="java.util.Set&lt;android.bluetooth.BluetoothDevice&gt;"
+ return="java.util.List&lt;android.bluetooth.BluetoothDevice&gt;"
abstract="false"
native="false"
synchronized="false"
@@ -36155,7 +36166,7 @@
</parameter>
</method>
<method name="getDevicesMatchingConnectionStates"
- return="java.util.Set&lt;android.bluetooth.BluetoothDevice&gt;"
+ return="java.util.List&lt;android.bluetooth.BluetoothDevice&gt;"
abstract="false"
native="false"
synchronized="false"
@@ -37969,7 +37980,7 @@
<implements name="android.bluetooth.BluetoothProfile">
</implements>
<method name="getConnectedDevices"
- return="java.util.Set&lt;android.bluetooth.BluetoothDevice&gt;"
+ return="java.util.List&lt;android.bluetooth.BluetoothDevice&gt;"
abstract="false"
native="false"
synchronized="false"
@@ -37993,7 +38004,7 @@
</parameter>
</method>
<method name="getDevicesMatchingConnectionStates"
- return="java.util.Set&lt;android.bluetooth.BluetoothDevice&gt;"
+ return="java.util.List&lt;android.bluetooth.BluetoothDevice&gt;"
abstract="false"
native="false"
synchronized="false"
@@ -38097,7 +38108,7 @@
visibility="public"
>
<method name="getConnectedDevices"
- return="java.util.Set&lt;android.bluetooth.BluetoothDevice&gt;"
+ return="java.util.List&lt;android.bluetooth.BluetoothDevice&gt;"
abstract="true"
native="false"
synchronized="false"
@@ -38121,7 +38132,7 @@
</parameter>
</method>
<method name="getDevicesMatchingConnectionStates"
- return="java.util.Set&lt;android.bluetooth.BluetoothDevice&gt;"
+ return="java.util.List&lt;android.bluetooth.BluetoothDevice&gt;"
abstract="true"
native="false"
synchronized="false"
@@ -111981,6 +111992,18 @@
deprecated="not deprecated"
visibility="public"
>
+<parameter name="data" type="byte[]">
+</parameter>
+<exception name="FormatException" type="android.nfc.FormatException">
+</exception>
+</constructor>
+<constructor name="NdefMessage"
+ type="android.nfc.NdefMessage"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
<parameter name="records" type="android.nfc.NdefRecord[]">
</parameter>
</constructor>
@@ -112006,6 +112029,17 @@
visibility="public"
>
</method>
+<method name="toByteArray"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="writeToParcel"
return="void"
abstract="false"
@@ -112125,6 +112159,17 @@
visibility="public"
>
</method>
+<method name="toByteArray"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="writeToParcel"
return="void"
abstract="false"
@@ -112315,6 +112360,29 @@
>
<implements name="android.os.Parcelable">
</implements>
+<method name="createMockNdefTag"
+ return="android.nfc.NdefTag"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="byte[]">
+</parameter>
+<parameter name="rawTargets" type="java.lang.String[]">
+</parameter>
+<parameter name="pollBytes" type="byte[]">
+</parameter>
+<parameter name="activationBytes" type="byte[]">
+</parameter>
+<parameter name="ndefTargets" type="java.lang.String[]">
+</parameter>
+<parameter name="messages" type="android.nfc.NdefMessage[][]">
+</parameter>
+</method>
<method name="getNdefMessages"
return="android.nfc.NdefMessage[]"
abstract="false"
@@ -112784,6 +112852,25 @@
>
<implements name="android.os.Parcelable">
</implements>
+<method name="createMockTag"
+ return="android.nfc.Tag"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="byte[]">
+</parameter>
+<parameter name="rawTargets" type="java.lang.String[]">
+</parameter>
+<parameter name="pollBytes" type="byte[]">
+</parameter>
+<parameter name="activationBytes" type="byte[]">
+</parameter>
+</method>
<method name="describeContents"
return="int"
abstract="false"
@@ -112795,6 +112882,17 @@
visibility="public"
>
</method>
+<method name="getActivationBytes"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getId"
return="byte[]"
abstract="false"
@@ -112806,6 +112904,17 @@
visibility="public"
>
</method>
+<method name="getPollBytes"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getRawTargets"
return="java.lang.String[]"
abstract="false"
@@ -112864,17 +112973,6 @@
visibility="public"
>
</field>
-<field name="TARGET_ISO_14443_3B_PRIME"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;iso14443_3b&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
<field name="TARGET_ISO_14443_4"
type="java.lang.String"
transient="false"
@@ -112919,17 +113017,6 @@
visibility="public"
>
</field>
-<field name="TARGET_TOPAZ"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value="&quot;topaz&quot;"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
</class>
</package>
<package name="android.opengl"
@@ -186728,6 +186815,17 @@
visibility="public"
>
</field>
+<field name="DENSITY_XHIGH"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="320"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="density"
type="float"
transient="false"
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 35f0249..d309ef9 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -84,7 +84,7 @@ static void dumpstate() {
LOGI("wrote screenshot: %s\n", screenshot_path);
}
- run_command("SYSTEM LOG", 20, "logcat", "-v", "time", "-d", "*:v", NULL);
+ run_command("SYSTEM LOG", 20, "logcat", "-v", "threadtime", "-d", "*:v", NULL);
/* show the traces we collected in main(), if that was done */
if (dump_traces_path != NULL) {
@@ -104,8 +104,8 @@ static void dumpstate() {
}
// dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
- run_command("EVENT LOG", 20, "logcat", "-b", "events", "-v", "time", "-d", "*:v", NULL);
- run_command("RADIO LOG", 20, "logcat", "-b", "radio", "-v", "time", "-d", "*:v", NULL);
+ run_command("EVENT LOG", 20, "logcat", "-b", "events", "-v", "threadtime", "-d", "*:v", NULL);
+ run_command("RADIO LOG", 20, "logcat", "-b", "radio", "-v", "threadtime", "-d", "*:v", NULL);
run_command("NETWORK INTERFACES", 10, "netcfg", NULL);
dump_file("NETWORK ROUTES", "/proc/net/route");
@@ -174,6 +174,14 @@ static void dumpstate() {
to increase its timeout. we really need to do the timeouts in
dumpsys itself... */
run_command("DUMPSYS", 60, "dumpsys", NULL);
+
+ printf("========================================================\n");
+ printf("== Application Services\n");
+ printf("========================================================\n");
+
+ /* Instead of a 60s timeout, we should give each service a 5 second timeout */
+ run_command("APP SERVICES", 60, "dumpsys", "activity", "service", NULL);
+
}
static void usage() {
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index a5b3e0e..2f03c7a 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -946,14 +946,12 @@ int linklib(const char* dataDir, const char* asecLibDir)
const size_t libdirLen = strlen(dataDir) + strlen(PKG_LIB_POSTFIX);
if (libdirLen >= PKG_PATH_MAX) {
LOGE("library dir len too large");
- rc = -1;
- goto out;
+ return -1;
}
if (snprintf(libdir, sizeof(libdir), "%s%s", dataDir, PKG_LIB_POSTFIX) != (ssize_t)libdirLen) {
LOGE("library dir not written successfully: %s\n", strerror(errno));
- rc = -1;
- goto out;
+ return -1;
}
if (stat(dataDir, &s) < 0) return -1;
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index d60a598..e269c31 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -1215,4 +1215,16 @@ public class ValueAnimator extends Animator {
void onAnimationUpdate(ValueAnimator animation);
}
-} \ No newline at end of file
+
+ /**
+ * Return the number of animations currently running.
+ *
+ * Used by StrictMode internally to annotate violations. Only
+ * called on the main thread.
+ *
+ * @hide
+ */
+ public static int getCurrentAnimationsCount() {
+ return sAnimations.size();
+ }
+}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 5ae8a1f..fe1e7d7 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -797,10 +797,12 @@ public class ActivityManager {
public static final int IMPORTANCE_PERCEPTIBLE = 130;
/**
- * Constant for {@link #importance}: this process is running a
- * heavy-weight application and thus should not be killed.
+ * Constant for {@link #importance}: this process is running an
+ * application that can not save its state, and thus can't be killed
+ * while in the background.
+ * @hide
*/
- public static final int IMPORTANCE_HEAVY_WEIGHT = 170;
+ public static final int IMPORTANCE_CANT_SAVE_STATE = 170;
/**
* Constant for {@link #importance}: this process is contains services
diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java
index c98128c..de36f27 100644
--- a/core/java/android/app/NativeActivity.java
+++ b/core/java/android/app/NativeActivity.java
@@ -5,7 +5,6 @@ import com.android.internal.view.IInputMethodSession;
import android.content.Context;
import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Configuration;
@@ -48,9 +47,22 @@ import java.lang.ref.WeakReference;
*/
public class NativeActivity extends Activity implements SurfaceHolder.Callback2,
InputQueue.Callback, OnGlobalLayoutListener {
+ /**
+ * Optional meta-that can be in the manifest for this component, specifying
+ * the name of the native shared library to load. If not specified,
+ * "main" is used.
+ */
public static final String META_DATA_LIB_NAME = "android.app.lib_name";
- public static final String KEY_NATIVE_SAVED_STATE = "android:native_state";
+ /**
+ * Optional meta-that can be in the manifest for this component, specifying
+ * the name of the main entry point for this native activity in the
+ * {@link #META_DATA_LIB_NAME} native code. If not specified,
+ * "ANativeActivity_onCreate" is used.
+ */
+ public static final String META_DATA_FUNC_NAME = "android.app.func_name";
+
+ private static final String KEY_NATIVE_SAVED_STATE = "android:native_state";
private NativeContentView mNativeContentView;
private InputMethodManager mIMM;
@@ -71,7 +83,7 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback2,
private boolean mDestroyed;
- private native int loadNativeCode(String path, MessageQueue queue,
+ private native int loadNativeCode(String path, String funcname, MessageQueue queue,
String internalDataPath, String externalDataPath, int sdkVersion,
AssetManager assetMgr, byte[] savedState);
private native void unloadNativeCode(int handle);
@@ -131,6 +143,7 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback2,
@Override
protected void onCreate(Bundle savedInstanceState) {
String libname = "main";
+ String funcname = "ANativeActivity_onCreate";
ActivityInfo ai;
mIMM = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
@@ -155,6 +168,8 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback2,
if (ai.metaData != null) {
String ln = ai.metaData.getString(META_DATA_LIB_NAME);
if (ln != null) libname = ln;
+ ln = ai.metaData.getString(META_DATA_FUNC_NAME);
+ if (ln != null) funcname = ln;
}
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException("Error getting activity info", e);
@@ -175,7 +190,7 @@ public class NativeActivity extends Activity implements SurfaceHolder.Callback2,
byte[] nativeSavedState = savedInstanceState != null
? savedInstanceState.getByteArray(KEY_NATIVE_SAVED_STATE) : null;
- mNativeHandle = loadNativeCode(path, Looper.myQueue(),
+ mNativeHandle = loadNativeCode(path, funcname, Looper.myQueue(),
getFilesDir().toString(),
Environment.getExternalStorageAppFilesDirectory(ai.packageName).toString(),
Build.VERSION.SDK_INT, getAssets(), nativeSavedState);
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 920ef89..61b4303 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -26,11 +26,8 @@ import android.os.ServiceManager;
import android.server.BluetoothA2dpService;
import android.util.Log;
-import java.util.Collections;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.ArrayList;
+import java.util.List;
/**
@@ -167,35 +164,35 @@ public final class BluetoothA2dp implements BluetoothProfile {
/**
* {@inheritDoc}
*/
- public Set<BluetoothDevice> getConnectedDevices() {
+ public List<BluetoothDevice> getConnectedDevices() {
if (DBG) log("getConnectedDevices()");
if (mService != null && isEnabled()) {
try {
- return toDeviceSet(mService.getConnectedDevices());
+ return mService.getConnectedDevices();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return toDeviceSet(new BluetoothDevice[0]);
+ return new ArrayList<BluetoothDevice>();
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
- return toDeviceSet(new BluetoothDevice[0]);
+ return new ArrayList<BluetoothDevice>();
}
/**
* {@inheritDoc}
*/
- public Set<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) log("getDevicesMatchingStates()");
if (mService != null && isEnabled()) {
try {
- return toDeviceSet(mService.getDevicesMatchingConnectionStates(states));
+ return mService.getDevicesMatchingConnectionStates(states);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
- return toDeviceSet(new BluetoothDevice[0]);
+ return new ArrayList<BluetoothDevice>();
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
- return toDeviceSet(new BluetoothDevice[0]);
+ return new ArrayList<BluetoothDevice>();
}
/**
@@ -396,11 +393,6 @@ public final class BluetoothA2dp implements BluetoothProfile {
return false;
}
- private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) {
- return Collections.unmodifiableSet(
- new HashSet<BluetoothDevice>(Arrays.asList(devices)));
- }
-
private static void log(String msg) {
Log.d(TAG, msg);
}
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index b33ab21..fd8f930 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -321,7 +321,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
mA2dpService.getDevicesMatchingConnectionStates(
new int[] {BluetoothA2dp.STATE_CONNECTED,
BluetoothProfile.STATE_CONNECTING,
- BluetoothProfile.STATE_DISCONNECTING}).length == 0) {
+ BluetoothProfile.STATE_DISCONNECTING}).size() == 0) {
mA2dpService.connect(mDevice);
}
if (mService.getInputDevicePriority(mDevice) ==
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 0496b1f..c64fdbe 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -18,20 +18,16 @@ package android.bluetooth;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
-import android.os.RemoteException;
import android.os.IBinder;
+import android.os.RemoteException;
import android.util.Log;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.ArrayList;
+import java.util.List;
/**
* Public API for controlling the Bluetooth Headset Service. This includes both
@@ -218,35 +214,35 @@ public final class BluetoothHeadset implements BluetoothProfile {
/**
* {@inheritDoc}
*/
- public Set<BluetoothDevice> getConnectedDevices() {
+ public List<BluetoothDevice> getConnectedDevices() {
if (DBG) log("getConnectedDevices()");
if (mService != null && isEnabled()) {
try {
- return toDeviceSet(mService.getConnectedDevices());
+ return mService.getConnectedDevices();
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
- return toDeviceSet(new BluetoothDevice[0]);
+ return new ArrayList<BluetoothDevice>();
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
- return toDeviceSet(new BluetoothDevice[0]);
+ return new ArrayList<BluetoothDevice>();
}
/**
* {@inheritDoc}
*/
- public Set<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) log("getDevicesMatchingStates()");
if (mService != null && isEnabled()) {
try {
- return toDeviceSet(mService.getDevicesMatchingConnectionStates(states));
+ return mService.getDevicesMatchingConnectionStates(states);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
- return toDeviceSet(new BluetoothDevice[0]);
+ return new ArrayList<BluetoothDevice>();
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
- return toDeviceSet(new BluetoothDevice[0]);
+ return new ArrayList<BluetoothDevice>();
}
/**
@@ -569,11 +565,6 @@ public final class BluetoothHeadset implements BluetoothProfile {
return false;
}
- private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) {
- return Collections.unmodifiableSet(
- new HashSet<BluetoothDevice>(Arrays.asList(devices)));
- }
-
private static void log(String msg) {
Log.d(TAG, msg);
}
diff --git a/core/java/android/bluetooth/BluetoothInputDevice.java b/core/java/android/bluetooth/BluetoothInputDevice.java
index 1793838..bc8a836 100644
--- a/core/java/android/bluetooth/BluetoothInputDevice.java
+++ b/core/java/android/bluetooth/BluetoothInputDevice.java
@@ -24,10 +24,8 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.ArrayList;
+import java.util.List;
/**
* Public API for controlling the Bluetooth HID (Input Device) Profile
@@ -167,18 +165,16 @@ public final class BluetoothInputDevice {
/** Check if any Input Device is connected.
*
- * @return a unmodifiable set of connected Input Devices, or null on error.
+ * @return List of devices, empty List on error.
* @hide
*/
- public Set<BluetoothDevice> getConnectedInputDevices() {
+ public List<BluetoothDevice> getConnectedInputDevices() {
if (DBG) log("getConnectedInputDevices()");
try {
- return Collections.unmodifiableSet(
- new HashSet<BluetoothDevice>(
- Arrays.asList(mService.getConnectedInputDevices())));
+ return mService.getConnectedInputDevices();
} catch (RemoteException e) {
Log.e(TAG, "", e);
- return null;
+ return new ArrayList<BluetoothDevice>();
}
}
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index 9d0b3f2..f55e96a 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -19,15 +19,13 @@ package android.bluetooth;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
-import android.os.ServiceManager;
-import android.os.RemoteException;
import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.util.Log;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.ArrayList;
+import java.util.List;
/**
* @hide
@@ -154,18 +152,16 @@ public final class BluetoothPan {
*
* Does not include devices that are currently connecting or disconnecting
*
- * @return a unmodifiable set of connected PAN Devices, or null on error.
+ * @return List of PAN devices or empty on Error
* @hide
*/
- public Set<BluetoothDevice> getConnectedDevices() {
+ public List<BluetoothDevice> getConnectedDevices() {
if (DBG) log("getConnectedDevices");
try {
- return Collections.unmodifiableSet(
- new HashSet<BluetoothDevice>(
- Arrays.asList(mService.getConnectedPanDevices())));
+ return mService.getConnectedPanDevices();
} catch (RemoteException e) {
Log.e(TAG, "", e);
- return null;
+ return new ArrayList<BluetoothDevice>();
}
}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 3b4c84c..3949b26 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -17,10 +17,7 @@
package android.bluetooth;
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-
-import java.util.Set;
+import java.util.List;
/**
* Public APIs for the Bluetooth Profiles.
@@ -150,9 +147,9 @@ public interface BluetoothProfile {
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH}
*
- * @return An unmodifiable set of devices. The set will be empty on error.
+ * @return List of devices. The list will be empty on error.
*/
- public Set<BluetoothDevice> getConnectedDevices();
+ public List<BluetoothDevice> getConnectedDevices();
/**
* Get a set of devices that match any of the given connection
@@ -166,9 +163,9 @@ public interface BluetoothProfile {
* @param states Array of states. States can be one of
* {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING},
* {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING},
- * @return An unmodifiable set of devices. The set will be empty on error.
+ * @return List of devices. The list will be empty on error.
*/
- public Set<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states);
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states);
/**
* Get the current connection state of the profile
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index cc23146..f0252b7 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -81,7 +81,7 @@ interface IBluetooth
// HID profile APIs
boolean connectInputDevice(in BluetoothDevice device);
boolean disconnectInputDevice(in BluetoothDevice device);
- BluetoothDevice[] getConnectedInputDevices(); // change to Set<> once AIDL supports
+ List<BluetoothDevice> getConnectedInputDevices();
int getInputDeviceState(in BluetoothDevice device);
boolean setInputDevicePriority(in BluetoothDevice device, int priority);
int getInputDevicePriority(in BluetoothDevice device);
@@ -89,7 +89,7 @@ interface IBluetooth
boolean isTetheringOn();
void setBluetoothTethering(boolean value);
int getPanDeviceState(in BluetoothDevice device);
- BluetoothDevice[] getConnectedPanDevices();
+ List<BluetoothDevice> getConnectedPanDevices();
boolean connectPanDevice(in BluetoothDevice device);
boolean disconnectPanDevice(in BluetoothDevice device);
}
diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl
index c5044c2..b4fc366 100644
--- a/core/java/android/bluetooth/IBluetoothA2dp.aidl
+++ b/core/java/android/bluetooth/IBluetoothA2dp.aidl
@@ -27,9 +27,8 @@ interface IBluetoothA2dp {
// Public API
boolean connect(in BluetoothDevice device);
boolean disconnect(in BluetoothDevice device);
- // change to Set<> once AIDL supports
- BluetoothDevice[] getConnectedDevices();
- BluetoothDevice[] getDevicesMatchingConnectionStates(in int[] states);
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
int getConnectionState(in BluetoothDevice device);
boolean setPriority(in BluetoothDevice device, int priority);
int getPriority(in BluetoothDevice device);
diff --git a/core/java/android/bluetooth/IBluetoothHeadset.aidl b/core/java/android/bluetooth/IBluetoothHeadset.aidl
index 8bcf103..3e4c7b4 100644
--- a/core/java/android/bluetooth/IBluetoothHeadset.aidl
+++ b/core/java/android/bluetooth/IBluetoothHeadset.aidl
@@ -27,9 +27,8 @@ interface IBluetoothHeadset {
// Public API
boolean connect(in BluetoothDevice device);
boolean disconnect(in BluetoothDevice device);
- // Change to Set<> when AIDL supports
- BluetoothDevice[] getConnectedDevices();
- BluetoothDevice[] getDevicesMatchingConnectionStates(in int[] states);
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
int getConnectionState(in BluetoothDevice device);
boolean setPriority(in BluetoothDevice device, int priority);
int getPriority(in BluetoothDevice device);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 89c9d25..54dbe37 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1076,6 +1076,16 @@ public class PackageParser {
XmlUtils.skipCurrentTag(parser);
+ } else if (tagName.equals("uses-gl-texture")) {
+ // Just skip this tag
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+
+ } else if (tagName.equals("compatible-screens")) {
+ // Just skip this tag
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+
} else if (tagName.equals("eat-comment")) {
// Just skip this tag
XmlUtils.skipCurrentTag(parser);
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 6ff5a40..275e2eb 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -779,9 +779,9 @@ public class Camera {
* Set the clockwise rotation of preview display in degrees. This affects
* the preview frames and the picture displayed after snapshot. This method
* is useful for portrait mode applications. Note that preview display of
- * front-facing cameras is flipped horizontally, that is, the image is
- * reflected along the central vertical axis of the camera sensor. So the
- * users can see themselves as looking into a mirror.
+ * front-facing cameras is flipped horizontally before the rotation, that
+ * is, the image is reflected along the central vertical axis of the camera
+ * sensor. So the users can see themselves as looking into a mirror.
*
* This does not affect the order of byte array passed in {@link
* PreviewCallback#onPreviewFrame}, JPEG pictures, or recorded videos. This
diff --git a/core/java/android/net/http/CertificateChainValidator.java b/core/java/android/net/http/CertificateChainValidator.java
index 503c470..218df75 100644
--- a/core/java/android/net/http/CertificateChainValidator.java
+++ b/core/java/android/net/http/CertificateChainValidator.java
@@ -129,57 +129,6 @@ class CertificateChainValidator {
}
}
- // Clean up the certificates chain and build a new one.
- // Theoretically, we shouldn't have to do this, but various web servers
- // in practice are mis-configured to have out-of-order certificates or
- // expired self-issued root certificate.
- int chainLength = serverCertificates.length;
- if (serverCertificates.length > 1) {
- // 1. we clean the received certificates chain.
- // We start from the end-entity certificate, tracing down by matching
- // the "issuer" field and "subject" field until we can't continue.
- // This helps when the certificates are out of order or
- // some certificates are not related to the site.
- int currIndex;
- for (currIndex = 0; currIndex < serverCertificates.length; ++currIndex) {
- boolean foundNext = false;
- for (int nextIndex = currIndex + 1;
- nextIndex < serverCertificates.length;
- ++nextIndex) {
- if (serverCertificates[currIndex].getIssuerDN().equals(
- serverCertificates[nextIndex].getSubjectDN())) {
- foundNext = true;
- // Exchange certificates so that 0 through currIndex + 1 are in proper order
- if (nextIndex != currIndex + 1) {
- X509Certificate tempCertificate = serverCertificates[nextIndex];
- serverCertificates[nextIndex] = serverCertificates[currIndex + 1];
- serverCertificates[currIndex + 1] = tempCertificate;
- }
- break;
- }
- }
- if (!foundNext) break;
- }
-
- // 2. we exam if the last traced certificate is self issued and it is expired.
- // If so, we drop it and pass the rest to checkServerTrusted(), hoping we might
- // have a similar but unexpired trusted root.
- chainLength = currIndex + 1;
- X509Certificate lastCertificate = serverCertificates[chainLength - 1];
- Date now = new Date();
- if (lastCertificate.getSubjectDN().equals(lastCertificate.getIssuerDN())
- && now.after(lastCertificate.getNotAfter())) {
- --chainLength;
- }
- }
-
- // 3. Now we copy the newly built chain into an appropriately sized array.
- X509Certificate[] newServerCertificates = null;
- newServerCertificates = new X509Certificate[chainLength];
- for (int i = 0; i < chainLength; ++i) {
- newServerCertificates[i] = serverCertificates[i];
- }
-
// first, we validate the new chain using the standard validation
// solution; if we do not find any errors, we are done; if we
// fail the standard validation, we re-validate again below,
@@ -188,7 +137,7 @@ class CertificateChainValidator {
//
try {
SSLParametersImpl.getDefaultTrustManager().checkServerTrusted(
- newServerCertificates, "RSA");
+ serverCertificates, "RSA");
// no errors!!!
return null;
diff --git a/core/java/android/nfc/NdefMessage.java b/core/java/android/nfc/NdefMessage.java
index 378304e..feca94e 100644
--- a/core/java/android/nfc/NdefMessage.java
+++ b/core/java/android/nfc/NdefMessage.java
@@ -34,15 +34,12 @@ public class NdefMessage implements Parcelable {
private final NdefRecord[] mRecords;
- //TODO(npelly) FormatException
/**
* Create an NDEF message from raw bytes.
* <p>
* Validation is performed to make sure the Record format headers are valid,
* and the ID + TYPE + PAYLOAD fields are of the correct size.
* @throws FormatException
- *
- * @hide
*/
public NdefMessage(byte[] data) throws FormatException {
mRecords = null; // stop compiler complaints about final field
@@ -69,10 +66,7 @@ public class NdefMessage implements Parcelable {
}
/**
- * Get a byte array representation of this NDEF message.
- *
- * @return byte array
- * @hide
+ * Returns a byte array representation of this entire NDEF message.
*/
public byte[] toByteArray() {
//TODO(nxp): do not return null
diff --git a/core/java/android/nfc/NdefRecord.java b/core/java/android/nfc/NdefRecord.java
index edc5ab9..557e44d 100644
--- a/core/java/android/nfc/NdefRecord.java
+++ b/core/java/android/nfc/NdefRecord.java
@@ -247,8 +247,7 @@ public class NdefRecord implements Parcelable {
}
/**
- * Return this NDEF Record as a byte array.
- * @hide
+ * Returns this entire NDEF Record as a byte array.
*/
public byte[] toByteArray() {
return generate(mFlags, mTnf, mType, mId, mPayload);
diff --git a/core/java/android/nfc/NdefTag.java b/core/java/android/nfc/NdefTag.java
index 45cdc31..d8681dc 100644
--- a/core/java/android/nfc/NdefTag.java
+++ b/core/java/android/nfc/NdefTag.java
@@ -16,8 +16,6 @@
package android.nfc;
-import java.util.HashMap;
-
import android.os.Parcel;
import android.os.Parcelable;
@@ -33,19 +31,92 @@ import android.os.Parcelable;
* is possible for {@link NdefTag}s to contain multiple {@link NdefMessage}s.
* <p>{@link NfcAdapter#createNdefTagConnection createNdefTagConnection()} can be used to modify the
* contents of some tags.
- * <p>This is an immutable data class.
+ * <p>This is an immutable data class. All properties are set at Tag discovery
+ * time and calls on this class will retrieve those read-only properties, and
+ * not cause any further RF activity or block. Note however that arrays passed to and
+ * returned by this class are *not* cloned, so be careful not to modify them.
*/
public class NdefTag extends Tag implements Parcelable {
- private final NdefMessage[] mMessages;
+ /**
+ * Target for NFC Forum Type 1 compliant tag.
+ * <p>This is based on Jewel/Topaz technology
+ */
+ public static final String TARGET_TYPE_1 = "type_1";
+
+ /**
+ * Target for NFC Forum Type 2 compliant tag.
+ * <p>This is based on Mifare Ultralight technology.
+ */
+ public static final String TARGET_TYPE_2 = "type_2";
/**
- * Hidden constructor to be used by NFC service when a
- * tag is discovered and by Parcelable methods.
+ * Target for NFC Forum Type 3 compliant tag.
+ * <p>This is based on Felica technology.
+ */
+ public static final String TARGET_TYPE_3 = "type_3";
+
+ /**
+ * Target for NFC Forum Type 4 compliant tag.
+ * <p>This is based on Mifare Desfire technology.
+ */
+ public static final String TARGET_TYPE_4 = "type_4";
+
+ /**
+ * Target for NFC Forum Enabled: Mifare Classic tag.
+ * <p>This is not strictly a NFC Forum tag type, but is a common
+ * NDEF message container.
+ */
+ public static final String TARGET_MIFARE_CLASSIC = "type_mifare_classic";
+
+ /**
+ * Any other target.
+ */
+ public static final String TARGET_OTHER = "other";
+
+ private final String[] mNdefTargets;
+ private final NdefMessage[][] mMessages; // one NdefMessage[] per NDEF target
+ private NdefMessage[] mFlatMessages; // collapsed mMessages, built lazily, protected by (this)
+
+ /**
+ * Hidden constructor to be used by NFC service only.
* @hide
*/
- public NdefTag(String typeName, byte[] uid, int nativeHandle, NdefMessage[] messages) {
- super(typeName, true, uid, nativeHandle);
- mMessages = messages.clone();
+ public NdefTag(byte[] id, String[] rawTargets, byte[] pollBytes, byte[] activationBytes,
+ int serviceHandle, String[] ndefTargets, NdefMessage[][] messages) {
+ super(id, true, rawTargets, pollBytes, activationBytes, serviceHandle);
+ if (ndefTargets == null || messages == null) {
+ throw new IllegalArgumentException("ndefTargets or messages cannot be null");
+ }
+ if (ndefTargets.length != messages.length){
+ throw new IllegalArgumentException("ndefTargets and messages arrays must match");
+ }
+ for (NdefMessage[] ms : messages) {
+ if (ms == null) {
+ throw new IllegalArgumentException("messages elements cannot be null");
+ }
+ }
+ mNdefTargets = ndefTargets;
+ mMessages = messages;
+ }
+
+ /**
+ * Construct a mock NdefTag.
+ * <p>This is an application constructed tag, so NfcAdapter methods on this
+ * Tag such as {@link NfcAdapter#createRawTagConnection} will fail with
+ * {@link IllegalArgumentException} since it does not represent a physical Tag.
+ * <p>This constructor might be useful for mock testing.
+ * @param id The tag identifier, can be null
+ * @param rawTargets must not be null
+ * @param pollBytes can be null
+ * @param activationBytes can be null
+ * @param ndefTargets NDEF target array, such as {TARGET_TYPE_2}, cannot be null
+ * @param messages messages, one array per NDEF target, cannot be null
+ * @return freshly constructed NdefTag
+ */
+ public static NdefTag createMockNdefTag(byte[] id, String[] rawTargets, byte[] pollBytes,
+ byte[] activationBytes, String[] ndefTargets, NdefMessage[][] messages) {
+ // set serviceHandle to 0 to indicate mock tag
+ return new NdefTag(id, rawTargets, pollBytes, activationBytes, 0, ndefTargets, messages);
}
/**
@@ -59,7 +130,29 @@ public class NdefTag extends Tag implements Parcelable {
* @return NDEF Messages found at Tag discovery
*/
public NdefMessage[] getNdefMessages() {
- return mMessages.clone();
+ // common-case optimization
+ if (mMessages.length == 1) {
+ return mMessages[0];
+ }
+
+ // return cached flat array
+ synchronized(this) {
+ if (mFlatMessages != null) {
+ return mFlatMessages;
+ }
+ // not cached - build a flat array
+ int sz = 0;
+ for (NdefMessage[] ms : mMessages) {
+ sz += ms.length;
+ }
+ mFlatMessages = new NdefMessage[sz];
+ int i = 0;
+ for (NdefMessage[] ms : mMessages) {
+ System.arraycopy(ms, 0, mFlatMessages, i, ms.length);
+ i += ms.length;
+ }
+ return mFlatMessages;
+ }
}
/**
@@ -70,58 +163,25 @@ public class NdefTag extends Tag implements Parcelable {
* <p>
* Most tags only contain a single NDEF message.
*
- * @param target One of targets strings provided by getNdefTargets()
+ * @param target one of targets strings provided by getNdefTargets()
* @return NDEF Messages found at Tag discovery
*/
public NdefMessage[] getNdefMessages(String target) {
- // TODO: handle multiprotocol
- String[] localTypes = convertToNdefType(mTypeName);
- if (!target.equals(localTypes[0])) {
- throw new IllegalArgumentException();
- }
- return getNdefMessages();
- }
-
- /** TODO(npelly):
- * - check that any single tag can only have one of each NDEF type
- * - ok to include mifare_classic?
- */
- public static final String TARGET_TYPE_1 = "type_1";
- public static final String TARGET_TYPE_2 = "type_2";
- public static final String TARGET_TYPE_3 = "type_3";
- public static final String TARGET_TYPE_4 = "type_4";
- public static final String TARGET_MIFARE_CLASSIC = "type_mifare_classic";
- public static final String TARGET_OTHER = "other";
-
- private static final HashMap<String, String[]> NDEF_TYPES_CONVERTION_TABLE = new HashMap<String, String[]>() {
- {
- // TODO: handle multiprotocol
- // TODO: move INTERNAL_TARGET_Type to TARGET_TYPE mapping to NFC service
- put(Tag.INTERNAL_TARGET_TYPE_JEWEL, new String[] { NdefTag.TARGET_TYPE_1 });
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_UL, new String[] { NdefTag.TARGET_TYPE_2 });
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_1K, new String[] { NdefTag.TARGET_MIFARE_CLASSIC });
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_4K, new String[] { NdefTag.TARGET_MIFARE_CLASSIC });
- put(Tag.INTERNAL_TARGET_TYPE_FELICA, new String[] { NdefTag.TARGET_TYPE_3 });
- put(Tag.INTERNAL_TARGET_TYPE_ISO14443_4, new String[] { NdefTag.TARGET_TYPE_4 });
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_DESFIRE, new String[] { NdefTag.TARGET_TYPE_4 });
+ for (int i=0; i<mNdefTargets.length; i++) {
+ if (target.equals(mNdefTargets[i])) {
+ return mMessages[i];
+ }
}
- };
-
- private String[] convertToNdefType(String internalTypeName) {
- String[] result = NDEF_TYPES_CONVERTION_TABLE.get(internalTypeName);
- if (result == null) {
- return new String[] { NdefTag.TARGET_OTHER };
- }
- return result;
+ throw new IllegalArgumentException("target (" + target + ") not found");
}
/**
- * Return the
+ * Return the NDEF targets on this Tag that support NDEF messages.
*
* @return
*/
public String[] getNdefTargets() {
- return convertToNdefType(mTypeName);
+ return mNdefTargets;
}
@Override
@@ -131,19 +191,50 @@ public class NdefTag extends Tag implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
- super.writeToParcel(dest, flags);
+ // Tag fields
+ dest.writeInt(mIsNdef ? 1 : 0);
+ writeBytesWithNull(dest, mId);
+ dest.writeInt(mRawTargets.length);
+ dest.writeStringArray(mRawTargets);
+ writeBytesWithNull(dest, mPollBytes);
+ writeBytesWithNull(dest, mActivationBytes);
+ dest.writeInt(mServiceHandle);
+
+ // NdefTag fields
+ dest.writeInt(mNdefTargets.length);
+ dest.writeStringArray(mNdefTargets);
dest.writeInt(mMessages.length);
- dest.writeTypedArray(mMessages, flags);
+ for (NdefMessage[] ms : mMessages) {
+ dest.writeTypedArray(ms, flags);
+ }
}
public static final Parcelable.Creator<NdefTag> CREATOR =
new Parcelable.Creator<NdefTag>() {
public NdefTag createFromParcel(Parcel in) {
- Tag tag = Tag.CREATOR.createFromParcel(in);
- int messagesLength = in.readInt();
- NdefMessage[] messages = new NdefMessage[messagesLength];
- in.readTypedArray(messages, NdefMessage.CREATOR);
- return new NdefTag(tag.mTypeName, tag.mUid, tag.mNativeHandle, messages);
+ boolean isNdef = (in.readInt() == 1);
+ if (!isNdef) {
+ throw new IllegalArgumentException("Creating NdefTag from Tag parcel");
+ }
+
+ // Tag fields
+ byte[] id = readBytesWithNull(in);
+ String[] rawTargets = new String[in.readInt()];
+ in.readStringArray(rawTargets);
+ byte[] pollBytes = readBytesWithNull(in);
+ byte[] activationBytes = readBytesWithNull(in);
+ int serviceHandle = in.readInt();
+
+ // NdefTag fields
+ String[] ndefTargets = new String[in.readInt()];
+ in.readStringArray(ndefTargets);
+ NdefMessage[][] messages = new NdefMessage[in.readInt()][];
+ for (int i=0; i<messages.length; i++) {
+ messages[i] = new NdefMessage[in.readInt()];
+ in.readTypedArray(messages[i], NdefMessage.CREATOR);
+ }
+ return new NdefTag(id, rawTargets, pollBytes, activationBytes, serviceHandle,
+ ndefTargets, messages);
}
public NdefTag[] newArray(int size) {
return new NdefTag[size];
diff --git a/core/java/android/nfc/NdefTagConnection.java b/core/java/android/nfc/NdefTagConnection.java
index 4795fa7..321b0ec 100644
--- a/core/java/android/nfc/NdefTagConnection.java
+++ b/core/java/android/nfc/NdefTagConnection.java
@@ -81,9 +81,9 @@ public class NdefTagConnection extends RawTagConnection {
//TODO(nxp): do not use getLastError(), it is racy
try {
NdefMessage[] msgArray = new NdefMessage[1];
- NdefMessage msg = mTagService.read(mTag.mNativeHandle);
+ NdefMessage msg = mTagService.read(mTag.mServiceHandle);
if (msg == null) {
- int errorCode = mTagService.getLastError(mTag.mNativeHandle);
+ int errorCode = mTagService.getLastError(mTag.mServiceHandle);
switch (errorCode) {
case ErrorCodes.ERROR_IO:
throw new IOException();
@@ -121,7 +121,7 @@ public class NdefTagConnection extends RawTagConnection {
*/
public void writeNdefMessage(NdefMessage message) throws IOException, FormatException {
try {
- int errorCode = mTagService.write(mTag.mNativeHandle, message);
+ int errorCode = mTagService.write(mTag.mServiceHandle, message);
switch (errorCode) {
case ErrorCodes.SUCCESS:
break;
@@ -148,7 +148,7 @@ public class NdefTagConnection extends RawTagConnection {
*/
public boolean makeReadOnly() throws IOException {
try {
- int errorCode = mTagService.makeReadOnly(mTag.mNativeHandle);
+ int errorCode = mTagService.makeReadOnly(mTag.mServiceHandle);
switch (errorCode) {
case ErrorCodes.SUCCESS:
return true;
@@ -175,7 +175,7 @@ public class NdefTagConnection extends RawTagConnection {
*/
public int getModeHint() throws IOException {
try {
- int result = mTagService.getModeHint(mTag.mNativeHandle);
+ int result = mTagService.getModeHint(mTag.mServiceHandle);
if (ErrorCodes.isError(result)) {
switch (result) {
case ErrorCodes.ERROR_IO:
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 6884abb..7f4b4a2 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -327,6 +327,9 @@ public final class NfcAdapter {
* <p>Requires {@link android.Manifest.permission#NFC} permission.
*/
public RawTagConnection createRawTagConnection(Tag tag) {
+ if (tag.mServiceHandle == 0) {
+ throw new IllegalArgumentException("mock tag cannot be used for connections");
+ }
try {
return new RawTagConnection(mService, tag);
} catch (RemoteException e) {
@@ -340,6 +343,9 @@ public final class NfcAdapter {
* <p>Requires {@link android.Manifest.permission#NFC} permission.
*/
public RawTagConnection createRawTagConnection(Tag tag, String target) {
+ if (tag.mServiceHandle == 0) {
+ throw new IllegalArgumentException("mock tag cannot be used for connections");
+ }
try {
return new RawTagConnection(mService, tag, target);
} catch (RemoteException e) {
@@ -353,6 +359,9 @@ public final class NfcAdapter {
* <p>Requires {@link android.Manifest.permission#NFC} permission.
*/
public NdefTagConnection createNdefTagConnection(NdefTag tag) {
+ if (tag.mServiceHandle == 0) {
+ throw new IllegalArgumentException("mock tag cannot be used for connections");
+ }
try {
return new NdefTagConnection(mService, tag);
} catch (RemoteException e) {
@@ -366,6 +375,9 @@ public final class NfcAdapter {
* <p>Requires {@link android.Manifest.permission#NFC} permission.
*/
public NdefTagConnection createNdefTagConnection(NdefTag tag, String target) {
+ if (tag.mServiceHandle == 0) {
+ throw new IllegalArgumentException("mock tag cannot be used for connections");
+ }
try {
return new NdefTagConnection(mService, tag, target);
} catch (RemoteException e) {
diff --git a/core/java/android/nfc/RawTagConnection.java b/core/java/android/nfc/RawTagConnection.java
index 1261db1..cf8283b 100644
--- a/core/java/android/nfc/RawTagConnection.java
+++ b/core/java/android/nfc/RawTagConnection.java
@@ -100,7 +100,7 @@ public class RawTagConnection {
}
try {
- return mTagService.isPresent(mTag.mNativeHandle);
+ return mTagService.isPresent(mTag.mServiceHandle);
} catch (RemoteException e) {
Log.e(TAG, "NFC service died", e);
return false;
@@ -135,7 +135,7 @@ public class RawTagConnection {
public void close() {
mIsConnected = false;
try {
- mTagService.close(mTag.mNativeHandle);
+ mTagService.close(mTag.mServiceHandle);
} catch (RemoteException e) {
Log.e(TAG, "NFC service died", e);
}
@@ -154,7 +154,7 @@ public class RawTagConnection {
*/
public byte[] transceive(byte[] data) throws IOException {
try {
- byte[] response = mTagService.transceive(mTag.mNativeHandle, data);
+ byte[] response = mTagService.transceive(mTag.mServiceHandle, data);
if (response == null) {
throw new IOException("transcieve failed");
}
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index abf02b5..f9205a6 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -16,8 +16,6 @@
package android.nfc;
-import java.util.HashMap;
-
import android.os.Parcel;
import android.os.Parcelable;
@@ -39,202 +37,180 @@ import android.os.Parcelable;
* range. If it is removed and then returned to range, then the most recent
* {@link Tag} object (in {@link NfcAdapter#ACTION_TAG_DISCOVERED}) should be used to create a
* {@link RawTagConnection}.
- * <p>This is an immutable data class.
+ * <p>This is an immutable data class. All properties are set at Tag discovery
+ * time and calls on this class will retrieve those read-only properties, and
+ * not cause any further RF activity or block. Note however that arrays passed to and
+ * returned by this class are *not* cloned, so be careful not to modify them.
*/
public class Tag implements Parcelable {
-
- /**
- * @hide
- */
- public static final int NFC_TAG_ISO14443_A = 1; /* phNfc_eISO14443_A_PICC */
-
- /**
- * @hide
- */
- public static final int NFC_TAG_ISO14443_4A = 2; /* phNfc_eISO14443_4A_PICC */
-
- /**
- * @hide
- */
- public static final int NFC_TAG_ISO14443_3A = 3; /* phNfc_eISO14443_3A_PICC */
-
- /**
- * @hide
- */
- public static final int NFC_TAG_MIFARE = 4; /* phNfc_eMifare_PICC */
-
- /**
- * @hide
- */
- public static final int NFC_TAG_ISO14443_B = 5; /* phNfc_eISO14443_B_PICC */
-
/**
- * @hide
+ * ISO 14443-3A technology.
+ * <p>
+ * Includes Topaz (which is -3A compatible)
*/
- public static final int NFC_TAG_ISO14443_4B = 6; /* phNfc_eISO14443_4B_PICC */
+ public static final String TARGET_ISO_14443_3A = "iso14443_3a";
/**
- * @hide
+ * ISO 14443-3B technology.
*/
- public static final int NFC_TAG_ISO14443_B_PRIME = 7; /* phNfc_eISO14443_BPrime_PICC */
+ public static final String TARGET_ISO_14443_3B = "iso14443_3b";
/**
- * @hide
+ * ISO 14443-4 technology.
*/
- public static final int NFC_TAG_FELICA = 8; /* phNfc_eFelica_PICC */
+ public static final String TARGET_ISO_14443_4 = "iso14443_4";
/**
- * @hide
+ * ISO 15693 technology, commonly known as RFID.
*/
- public static final int NFC_TAG_JEWEL = 9; /* phNfc_eJewel_PICC */
+ public static final String TARGET_ISO_15693 = "iso15693";
/**
- * @hide
+ * JIS X-6319-4 technology, commonly known as Felica.
*/
- public static final int NFC_TAG_ISO15693 = 10; /* phNfc_eISO15693_PICC */
+ public static final String TARGET_JIS_X_6319_4 = "jis_x_6319_4";
/**
- * @hide
+ * Any other technology.
*/
- public static final int NFC_TAG_OTHER = 11; /* phNfc_ePICC_DevType */
-
-
- public static final String TARGET_ISO_14443_3A = "iso14443_3a";
-
- public static final String TARGET_ISO_14443_3B = "iso14443_3b";
-
- public static final String TARGET_ISO_14443_3B_PRIME = "iso14443_3b";
-
- public static final String TARGET_ISO_14443_4 = "iso14443_4";
-
- public static final String TARGET_ISO_15693 = "iso15693";
-
- public static final String TARGET_JIS_X_6319_4 = "jis_x_6319_4";
-
- public static final String TARGET_TOPAZ = "topaz";
-
public static final String TARGET_OTHER = "other";
- /*package*/ final String mTypeName;
/*package*/ final boolean mIsNdef;
- /*package*/ final byte[] mUid;
- /*package*/ final int mNativeHandle;
-
- /*package*/ static final String INTERNAL_TARGET_TYPE_ISO14443_3A = "Iso14443-3A";
- /*package*/ static final String INTERNAL_TARGET_TYPE_ISO14443_3B = "Iso14443-3B";
- /*package*/ static final String INTERNAL_TARGET_TYPE_ISO14443_4 = "Iso14443-4";
- /*package*/ static final String INTERNAL_TARGET_TYPE_MIFARE_UL = "MifareUL";
- /*package*/ static final String INTERNAL_TARGET_TYPE_MIFARE_1K = "Mifare1K";
- /*package*/ static final String INTERNAL_TARGET_TYPE_MIFARE_4K = "Mifare4K";
- /*package*/ static final String INTERNAL_TARGET_TYPE_MIFARE_DESFIRE = "MifareDESFIRE";
- /*package*/ static final String INTERNAL_TARGET_TYPE_MIFARE_UNKNOWN = "Unknown Mifare";
- /*package*/ static final String INTERNAL_TARGET_TYPE_FELICA = "Felica";
- /*package*/ static final String INTERNAL_TARGET_TYPE_JEWEL = "Jewel";
- /*package*/ static final String INTERNAL_TARGET_TYPE_UNKNOWN = "Unknown Type";
-
- private static final HashMap<String, Integer> INT_TYPES_CONVERTION_TABLE = new HashMap<String, Integer>() {
- {
- put(Tag.INTERNAL_TARGET_TYPE_ISO14443_3A, Tag.NFC_TAG_ISO14443_A );
- put(Tag.INTERNAL_TARGET_TYPE_ISO14443_3B, Tag.NFC_TAG_ISO14443_B );
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_UL, Tag.NFC_TAG_MIFARE );
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_1K, Tag.NFC_TAG_MIFARE );
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_4K, Tag.NFC_TAG_MIFARE );
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_DESFIRE, Tag.NFC_TAG_MIFARE );
- put(Tag.INTERNAL_TARGET_TYPE_FELICA, Tag.NFC_TAG_FELICA );
- put(Tag.INTERNAL_TARGET_TYPE_JEWEL, Tag.NFC_TAG_JEWEL );
- }
- };
-
- private int convertToInt(String internalTypeName) {
- Integer result = INT_TYPES_CONVERTION_TABLE.get(internalTypeName);
- if (result == null) {
- return Tag.NFC_TAG_OTHER;
- }
- return result;
- }
-
- private static final HashMap<String, String[]> RAW_TYPES_CONVERTION_TABLE = new HashMap<String, String[]>() {
- {
- /* TODO: handle multiprotocol */
- put(Tag.INTERNAL_TARGET_TYPE_ISO14443_3A, new String[] { Tag.TARGET_ISO_14443_3A });
- put(Tag.INTERNAL_TARGET_TYPE_ISO14443_3B, new String[] { Tag.TARGET_ISO_14443_3B });
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_UL, new String[] { Tag.TARGET_ISO_14443_3A });
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_1K, new String[] { Tag.TARGET_ISO_14443_3A });
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_4K, new String[] { Tag.TARGET_ISO_14443_3A });
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_DESFIRE, new String[] { Tag.TARGET_ISO_14443_3A });
- put(Tag.INTERNAL_TARGET_TYPE_MIFARE_UNKNOWN, new String[] { Tag.TARGET_ISO_14443_3A });
- put(Tag.INTERNAL_TARGET_TYPE_FELICA, new String[] { Tag.TARGET_JIS_X_6319_4 });
- put(Tag.INTERNAL_TARGET_TYPE_JEWEL, new String[] { Tag.TARGET_TOPAZ });
- }
- };
-
- private String[] convertToRaw(String internalTypeName) {
- String[] result = RAW_TYPES_CONVERTION_TABLE.get(internalTypeName);
- if (result == null) {
- return new String[] { Tag.TARGET_OTHER };
- }
- return result;
- }
+ /*package*/ final byte[] mId;
+ /*package*/ final String[] mRawTargets;
+ /*package*/ final byte[] mPollBytes;
+ /*package*/ final byte[] mActivationBytes;
+ /*package*/ final int mServiceHandle; // for use by NFC service, 0 indicates a mock
/**
- * Hidden constructor to be used by NFC service only.
+ * Hidden constructor to be used by NFC service and internal classes.
* @hide
*/
- public Tag(String typeName, boolean isNdef, byte[] uid, int nativeHandle) {
- mTypeName = typeName;
+ public Tag(byte[] id, boolean isNdef, String[] rawTargets, byte[] pollBytes,
+ byte[] activationBytes, int serviceHandle) {
+ if (rawTargets == null) {
+ throw new IllegalArgumentException("rawTargets cannot be null");
+ }
mIsNdef = isNdef;
- mUid = uid.clone();
- mNativeHandle = nativeHandle;
+ mId = id;
+ mRawTargets = rawTargets;
+ mPollBytes = pollBytes;
+ mActivationBytes = activationBytes;
+ mServiceHandle = serviceHandle;
+ }
+
+ /**
+ * Construct a mock Tag.
+ * <p>This is an application constructed tag, so NfcAdapter methods on this
+ * Tag such as {@link NfcAdapter#createRawTagConnection} will fail with
+ * {@link IllegalArgumentException} since it does not represent a physical Tag.
+ * <p>This constructor might be useful for mock testing.
+ * @param id The tag identifier, can be null
+ * @param rawTargets must not be null
+ * @param pollBytes can be null
+ * @param activationBytes can be null
+ * @return freshly constructed tag
+ */
+ public static Tag createMockTag(byte[] id, String[] rawTargets, byte[] pollBytes,
+ byte[] activationBytes) {
+ // set serviceHandle to 0 to indicate mock tag
+ return new Tag(id, false, rawTargets, pollBytes, activationBytes, 0);
}
/**
* For use by NfcService only.
* @hide
*/
- public int getHandle() {
- return mNativeHandle;
+ public int getServiceHandle() {
+ return mServiceHandle;
}
/**
* Return the available targets that this NFC adapter can use to create
* a RawTagConnection.
*
- * @return
+ * @return raw targets, will not be null
*/
public String[] getRawTargets() {
- return convertToRaw(mTypeName);
+ return mRawTargets;
}
/**
- * Get the Tag type.
- * <p>
- * The Tag type is one of the NFC_TAG constants. It is read at discovery
- * time and this method does not cause any further RF activity and does not
- * block.
+ * Get the Tag Identifier (if it has one).
+ * <p>Tag ID is usually a serial number for the tag.
*
- * @return a NFC_TAG constant
- * @hide
+ * @return ID, or null if it does not exist
*/
- public int getType() {
- return convertToInt(mTypeName);
+ public byte[] getId() {
+ return mId;
}
/**
- * Get the Tag Identifier (if it has one).
- * <p>
- * Tag ID is usually a serial number for the tag.
- * <p>
- * The Tag ID is read at discovery time and this method does not cause any
- * further RF activity and does not block.
+ * Get the low-level bytes returned by this Tag at poll-time.
+ * <p>These can be used to help with advanced identification of a Tag.
+ * <p>The meaning of these bytes depends on the Tag technology.
+ * <p>ISO14443-3A: ATQA/SENS_RES
+ * <p>ISO14443-3B: Application data (4 bytes) and Protocol Info (3 bytes) from ATQB/SENSB_RES
+ * <p>JIS_X_6319_4: PAD0 (2 byte), PAD1 (2 byte), MRTI(2 byte), PAD2 (1 byte), RC (2 byte)
+ * <p>ISO15693: response flags (1 byte), DSFID (1 byte)
+ * from SENSF_RES
*
- * @return ID, or null if it does not exist
+ * @return poll bytes, or null if they do not exist for this Tag technology
*/
- public byte[] getId() {
- if (mUid.length > 0) {
- return mUid.clone();
- } else {
- return null;
+ public byte[] getPollBytes() {
+ return mPollBytes;
+ }
+
+ /**
+ * Get the low-level bytes returned by this Tag at activation-time.
+ * <p>These can be used to help with advanced identification of a Tag.
+ * <p>The meaning of these bytes depends on the Tag technology.
+ * <p>ISO14443-3A: SAK/SEL_RES
+ * <p>ISO14443-3B: null
+ * <p>ISO14443-3A & ISO14443-4: SAK/SEL_RES, historical bytes from ATS <TODO: confirm>
+ * <p>ISO14443-3B & ISO14443-4: ATTRIB response
+ * <p>JIS_X_6319_4: null
+ * <p>ISO15693: response flags (1 byte), DSFID (1 byte): null
+ * @return activation bytes, or null if they do not exist for this Tag technology
+ */
+ public byte[] getActivationBytes() {
+ return mActivationBytes;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("TAG ")
+ .append("uid = ")
+ .append(mId)
+ .append(" poll ")
+ .append(mPollBytes)
+ .append(" activation ")
+ .append(mActivationBytes)
+ .append(" Raw [");
+ for (String s : mRawTargets) {
+ sb.append(s)
+ .append(", ");
+ }
+ return sb.toString();
+ }
+
+ /*package*/ static byte[] readBytesWithNull(Parcel in) {
+ int len = in.readInt();
+ byte[] result = null;
+ if (len > 0) {
+ result = new byte[len];
+ in.readByteArray(result);
}
+ return result;
+ }
+
+ /*package*/ static void writeBytesWithNull(Parcel out, byte[] b) {
+ if (b == null) {
+ out.writeInt(-1);
+ return;
+ }
+ out.writeInt(b.length);
+ out.writeByteArray(b);
}
@Override
@@ -242,29 +218,34 @@ public class Tag implements Parcelable {
return 0;
}
+
@Override
public void writeToParcel(Parcel dest, int flags) {
- boolean[] booleans = new boolean[] {mIsNdef};
- dest.writeString(mTypeName);
- dest.writeBooleanArray(booleans);
- dest.writeInt(mUid.length);
- dest.writeByteArray(mUid);
- dest.writeInt(mNativeHandle);
+ dest.writeInt(mIsNdef ? 1 : 0);
+ writeBytesWithNull(dest, mId);
+ dest.writeInt(mRawTargets.length);
+ dest.writeStringArray(mRawTargets);
+ writeBytesWithNull(dest, mPollBytes);
+ writeBytesWithNull(dest, mActivationBytes);
+ dest.writeInt(mServiceHandle);
}
public static final Parcelable.Creator<Tag> CREATOR =
new Parcelable.Creator<Tag>() {
public Tag createFromParcel(Parcel in) {
- boolean[] booleans = new boolean[1];
- String type = in.readString();
- in.readBooleanArray(booleans);
- boolean isNdef = booleans[0];
- int uidLength = in.readInt();
- byte[] uid = new byte[uidLength];
- in.readByteArray(uid);
- int nativeHandle = in.readInt();
-
- return new Tag(type, isNdef, uid, nativeHandle);
+ boolean isNdef = (in.readInt() == 1);
+ if (isNdef) {
+ throw new IllegalArgumentException("Creating Tag from NdefTag parcel");
+ }
+ // Tag fields
+ byte[] id = Tag.readBytesWithNull(in);
+ String[] rawTargets = new String[in.readInt()];
+ in.readStringArray(rawTargets);
+ byte[] pollBytes = Tag.readBytesWithNull(in);
+ byte[] activationBytes = Tag.readBytesWithNull(in);
+ int serviceHandle = in.readInt();
+
+ return new Tag(id, isNdef, rawTargets, pollBytes, activationBytes, serviceHandle);
}
public Tag[] newArray(int size) {
return new Tag[size];
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 9767786..b4c6a2923 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -188,15 +188,7 @@ public class Build {
public static final int FROYO = 8;
/**
- * Next version of Android.
- *
- * <p>Applications targeting this or a later release will get these
- * new changes in behavior:</p>
- * <ul>
- * <li> The status bar is now dark. Targeting this version allows
- * the platform to perform performing compatibility on status bar
- * graphics to ensure they look okay on a dark background.
- * </ul>
+ * Newest version of Android, version 2.3.
*/
public static final int GINGERBREAD = 9;
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index e912089..9786959 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -15,6 +15,7 @@
*/
package android.os;
+import android.animation.ValueAnimator;
import android.app.ActivityManagerNative;
import android.app.ApplicationErrorReport;
import android.util.Log;
@@ -1110,6 +1111,11 @@ public final class StrictMode {
public int durationMillis = -1;
/**
+ * The number of animations currently running.
+ */
+ public int numAnimationsRunning = 0;
+
+ /**
* Which violation number this was (1-based) since the last Looper loop,
* from the perspective of the root caller (if it crossed any processes
* via Binder calls). The value is 0 if the root caller wasn't on a Looper
@@ -1138,6 +1144,7 @@ public final class StrictMode {
crashInfo = new ApplicationErrorReport.CrashInfo(tr);
violationUptimeMillis = SystemClock.uptimeMillis();
this.policy = policy;
+ this.numAnimationsRunning = ValueAnimator.getCurrentAnimationsCount();
}
/**
@@ -1163,6 +1170,7 @@ public final class StrictMode {
}
durationMillis = in.readInt();
violationNumThisLoop = in.readInt();
+ numAnimationsRunning = in.readInt();
violationUptimeMillis = in.readLong();
}
@@ -1174,6 +1182,7 @@ public final class StrictMode {
dest.writeInt(policy);
dest.writeInt(durationMillis);
dest.writeInt(violationNumThisLoop);
+ dest.writeInt(numAnimationsRunning);
dest.writeLong(violationUptimeMillis);
}
@@ -1190,6 +1199,9 @@ public final class StrictMode {
if (violationNumThisLoop != 0) {
pw.println(prefix + "violationNumThisLoop: " + violationNumThisLoop);
}
+ if (numAnimationsRunning != 0) {
+ pw.println(prefix + "numAnimationsRunning: " + numAnimationsRunning);
+ }
pw.println(prefix + "violationUptimeMillis: " + violationUptimeMillis);
}
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index 7b2022b..61e2305 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -41,6 +41,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
@@ -107,10 +108,10 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
} else if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {
int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
if (streamType == AudioManager.STREAM_MUSIC) {
- BluetoothDevice sinks[] = getConnectedDevices();
+ List<BluetoothDevice> sinks = getConnectedDevices();
- if (sinks.length != 0 && isPhoneDocked(sinks[0])) {
- String address = sinks[0].getAddress();
+ if (sinks.size() != 0 && isPhoneDocked(sinks.get(0))) {
+ String address = sinks.get(0).getAddress();
int newVolLevel =
intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 0);
int oldVolLevel =
@@ -319,7 +320,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
if (getDevicesMatchingConnectionStates(new int[] {
BluetoothA2dp.STATE_CONNECTING,
BluetoothA2dp.STATE_CONNECTED,
- BluetoothA2dp.STATE_DISCONNECTING}).length != 0) {
+ BluetoothA2dp.STATE_DISCONNECTING}).size() != 0) {
return false;
}
@@ -430,19 +431,16 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
return state;
}
- public synchronized BluetoothDevice[] getConnectedDevices() {
+ public synchronized List<BluetoothDevice> getConnectedDevices() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- BluetoothDevice[] sinks = getDevicesMatchingConnectionStates(
+ List<BluetoothDevice> sinks = getDevicesMatchingConnectionStates(
new int[] {BluetoothA2dp.STATE_CONNECTED});
return sinks;
}
- public synchronized BluetoothDevice[] getDevicesMatchingConnectionStates(int[] states) {
+ public synchronized List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- ArrayList<BluetoothDevice> sinks = new ArrayList();
- if (mAudioDevices.isEmpty()) {
- return sinks.toArray(new BluetoothDevice[sinks.size()]);
- }
+ ArrayList<BluetoothDevice> sinks = new ArrayList<BluetoothDevice>();
for (BluetoothDevice device: mAudioDevices.keySet()) {
int sinkState = getConnectionState(device);
for (int state : states) {
@@ -452,7 +450,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
}
}
}
- return sinks.toArray(new BluetoothDevice[sinks.size()]);
+ return sinks;
}
public synchronized int getPriority(BluetoothDevice device) {
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 239c3ac..f47c553 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -29,11 +29,12 @@ import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelUuid;
+import android.os.PowerManager;
import android.util.Log;
import java.util.HashMap;
+import java.util.List;
import java.util.Set;
-import android.os.PowerManager;
/**
@@ -629,7 +630,7 @@ class BluetoothEventLoop {
}
private boolean isOtherInputDeviceConnected(String address) {
- Set<BluetoothDevice> devices =
+ List<BluetoothDevice> devices =
mBluetoothService.lookupInputDevicesMatchingStates(new int[] {
BluetoothInputDevice.STATE_CONNECTING,
BluetoothInputDevice.STATE_CONNECTED});
@@ -654,13 +655,13 @@ class BluetoothEventLoop {
}
private boolean isOtherSinkInNonDisconnectedState(String address) {
- Set<BluetoothDevice> devices =
+ List<BluetoothDevice> devices =
mA2dp.getDevicesMatchingConnectionStates(new int[] {BluetoothA2dp.STATE_CONNECTED,
BluetoothA2dp.STATE_CONNECTING,
BluetoothA2dp.STATE_DISCONNECTING});
if (devices.size() == 0) return false;
- for(BluetoothDevice dev: devices) {
+ for (BluetoothDevice dev: devices) {
if (!dev.getAddress().equals(address)) return true;
}
return false;
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 7abb98e..660f9ab 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -27,12 +27,12 @@ package android.server;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothDeviceProfileState;
+import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothInputDevice;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothProfileState;
-import android.bluetooth.BluetoothInputDevice;
import android.bluetooth.BluetoothSocket;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.IBluetooth;
@@ -80,6 +80,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -1415,7 +1416,7 @@ public class BluetoothService extends IBluetooth.Stub {
}
/*package*/ synchronized boolean allowIncomingTethering() {
- if (isTetheringOn() && getConnectedPanDevices().length < mMaxPanDevices)
+ if (isTetheringOn() && getConnectedPanDevices().size() < mMaxPanDevices)
return true;
return false;
}
@@ -1503,16 +1504,17 @@ public class BluetoothService extends IBluetooth.Stub {
return true;
}
- public synchronized BluetoothDevice[] getConnectedPanDevices() {
+ public synchronized List<BluetoothDevice> getConnectedPanDevices() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- Set<BluetoothDevice> devices = new HashSet<BluetoothDevice>();
+ List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
+
for (BluetoothDevice device: mPanDevices.keySet()) {
if (getPanDeviceState(device) == BluetoothPan.STATE_CONNECTED) {
devices.add(device);
}
}
- return devices.toArray(new BluetoothDevice[devices.size()]);
+ return devices;
}
public synchronized boolean disconnectPanDevice(BluetoothDevice device) {
@@ -1569,7 +1571,7 @@ public class BluetoothService extends IBluetooth.Stub {
}
private String createNewTetheringAddressLocked() {
- if (getConnectedPanDevices().length == mMaxPanDevices) {
+ if (getConnectedPanDevices().size() == mMaxPanDevices) {
log("Max PAN device connections reached");
return null;
}
@@ -1688,7 +1690,7 @@ public class BluetoothService extends IBluetooth.Stub {
"Need BLUETOOTH_ADMIN permission");
String objectPath = getObjectPathFromAddress(device.getAddress());
- if (objectPath == null || getConnectedInputDevices().length == 0) {
+ if (objectPath == null || getConnectedInputDevices().size() == 0) {
return false;
}
BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress());
@@ -1721,11 +1723,11 @@ public class BluetoothService extends IBluetooth.Stub {
return mInputDevices.get(device);
}
- public synchronized BluetoothDevice[] getConnectedInputDevices() {
+ public synchronized List<BluetoothDevice> getConnectedInputDevices() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- Set<BluetoothDevice> devices = lookupInputDevicesMatchingStates(
+ List<BluetoothDevice> devices = lookupInputDevicesMatchingStates(
new int[] {BluetoothInputDevice.STATE_CONNECTED});
- return devices.toArray(new BluetoothDevice[devices.size()]);
+ return devices;
}
public synchronized int getInputDevicePriority(BluetoothDevice device) {
@@ -1746,11 +1748,9 @@ public class BluetoothService extends IBluetooth.Stub {
priority);
}
- /*package*/synchronized Set<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) {
- Set<BluetoothDevice> inputDevices = new HashSet<BluetoothDevice>();
- if (mInputDevices.isEmpty()) {
- return inputDevices;
- }
+ /*package*/synchronized List<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) {
+ List<BluetoothDevice> inputDevices = new ArrayList<BluetoothDevice>();
+
for (BluetoothDevice device: mInputDevices.keySet()) {
int inputDeviceState = getInputDeviceState(device);
for (int state : states) {
@@ -2487,11 +2487,11 @@ public class BluetoothService extends IBluetooth.Stub {
// dump
pw.println("\n--Headset Service--");
if (mBluetoothHeadset != null) {
- Set<BluetoothDevice> deviceSet = mBluetoothHeadset.getConnectedDevices();
- if (deviceSet.size() == 0) {
+ List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();
+ if (deviceList.size() == 0) {
pw.println("\n--No headsets connected--");
}
- BluetoothDevice device = (BluetoothDevice) deviceSet.toArray()[0];
+ BluetoothDevice device = deviceList.get(0);
switch (mBluetoothHeadset.getConnectionState(device)) {
case BluetoothHeadset.STATE_DISCONNECTED:
@@ -2511,11 +2511,11 @@ public class BluetoothService extends IBluetooth.Stub {
break;
}
- deviceSet.clear();
- deviceSet = mBluetoothHeadset.getDevicesMatchingConnectionStates(new int[] {
+ deviceList.clear();
+ deviceList = mBluetoothHeadset.getDevicesMatchingConnectionStates(new int[] {
BluetoothProfile.STATE_CONNECTED, BluetoothProfile.STATE_DISCONNECTED});
pw.println("\n--Connected and Disconnected Headsets");
- for (BluetoothDevice dev: deviceSet) {
+ for (BluetoothDevice dev: deviceList) {
pw.println(device);
if (mBluetoothHeadset.isAudioConnected(device)) {
pw.println("SCO audio connected to device:" + device);
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 76d8106..63baf14 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -45,6 +45,11 @@ public class DisplayMetrics {
public static final int DENSITY_HIGH = 240;
/**
+ * Standard quantized DPI for extra-high-density screens.
+ */
+ public static final int DENSITY_XHIGH = 320;
+
+ /**
* The reference density used throughout the system.
*/
public static final int DENSITY_DEFAULT = DENSITY_MEDIUM;
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index 61a8cda..3010178 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -98,6 +98,10 @@ public final class CookieManager {
private boolean mAcceptCookie = true;
+ // TODO: Remove this if/when we permanently switch to the Chromium HTTP stack
+ // http:/b/3118772
+ private static Boolean sUseChromiumHttpStack;
+
/**
* This contains a list of 2nd-level domains that aren't allowed to have
* wildcards when combined with country-codes. For example: [.co.uk].
@@ -257,6 +261,13 @@ public final class CookieManager {
return sRef;
}
+ private static boolean useChromiumHttpStack() {
+ if (sUseChromiumHttpStack == null) {
+ sUseChromiumHttpStack = nativeUseChromiumHttpStack();
+ }
+ return sUseChromiumHttpStack;
+ }
+
/**
* Control whether cookie is enabled or disabled
* @param accept TRUE if accept cookie
@@ -524,11 +535,11 @@ public final class CookieManager {
* Remove all cookies
*/
public void removeAllCookie() {
- // Clear cookies for the Chromium HTTP stack
- nativeRemoveAllCookie();
- // Clear cookies for the Android HTTP stack
- // TODO: Remove this if/when we permanently switch to the Chromium HTTP stack
- // http:/b/3118772
+ if (useChromiumHttpStack()) {
+ nativeRemoveAllCookie();
+ return;
+ }
+
final Runnable clearCache = new Runnable() {
public void run() {
synchronized(CookieManager.this) {
@@ -1023,5 +1034,6 @@ public final class CookieManager {
}
// Native functions
+ private static native boolean nativeUseChromiumHttpStack();
private static native void nativeRemoveAllCookie();
}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index be1af65..c095199 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -2388,7 +2388,7 @@ public class WebView extends AbsoluteLayout
if (!rect.equals(mLastVisibleRectSent)) {
Point pos = new Point(rect.left, rect.top);
mWebViewCore.sendMessage(EventHub.SET_SCROLL_OFFSET,
- nativeMoveGeneration(), 0, pos);
+ nativeMoveGeneration(), mUserScroll ? 1 : 0, pos);
mLastVisibleRectSent = rect;
}
Rect globalRect = new Rect();
@@ -3966,7 +3966,9 @@ public class WebView extends AbsoluteLayout
imm.restartInput(mWebTextView);
}
}
- mWebTextView.requestFocus();
+ if (isFocused()) {
+ mWebTextView.requestFocus();
+ }
}
/**
@@ -6442,6 +6444,7 @@ public class WebView extends AbsoluteLayout
}
case NEW_PICTURE_MSG_ID: {
// called for new content
+ mUserScroll = false;
final WebViewCore.DrawData draw = (WebViewCore.DrawData) msg.obj;
setBaseLayer(draw.mBaseLayer, draw.mInvalRegion.getBounds());
final Point viewSize = draw.mViewPoint;
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 8cd9f68..1c8e2cd 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -1074,7 +1074,7 @@ final class WebViewCore {
// note: these are in document coordinates
// (inv-zoom)
Point pt = (Point) msg.obj;
- nativeSetScrollOffset(msg.arg1, pt.x, pt.y);
+ nativeSetScrollOffset(msg.arg1, msg.arg2, pt.x, pt.y);
break;
case SET_GLOBAL_BOUNDS:
@@ -2203,7 +2203,8 @@ final class WebViewCore {
if (mViewportInitialScale > 0) {
mInitialViewState.mViewScale = mInitialViewState.mTextWrapScale =
mViewportInitialScale / 100.0f;
- } else if (mViewportWidth > 0 && mViewportWidth < webViewWidth) {
+ } else if (mViewportWidth > 0 && mViewportWidth < webViewWidth &&
+ !mWebView.getSettings().getUseFixedViewport()) {
mInitialViewState.mViewScale = mInitialViewState.mTextWrapScale =
(float) webViewWidth / mViewportWidth;
} else {
@@ -2347,7 +2348,7 @@ final class WebViewCore {
private native void nativeScrollFocusedTextInput(float xPercent, int y);
// these must be in document space (i.e. not scaled/zoomed).
- private native void nativeSetScrollOffset(int gen, int dx, int dy);
+ private native void nativeSetScrollOffset(int gen, int userScrolled, int dx, int dy);
private native void nativeSetGlobalBounds(int x, int y, int w, int h);
diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java
index 0a91ac4..91c0fb2 100644
--- a/core/java/android/webkit/ZoomManager.java
+++ b/core/java/android/webkit/ZoomManager.java
@@ -554,9 +554,7 @@ class ZoomManager {
}
if (settings.getLayoutAlgorithm() == WebSettings.LayoutAlgorithm.NARROW_COLUMNS
- && willScaleTriggerZoom(mTextWrapScale)
- // For tablet, not much need to reflow text w/o double tapping.
- && !settings.getUseFixedViewport()) {
+ && willScaleTriggerZoom(mTextWrapScale)) {
refreshZoomScale(true);
} else if (!mInZoomOverview) {
zoomToOverview();
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 9e7cc44..728c2a7 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -856,6 +856,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
@Override
public boolean performItemClick(View view, int position, long id) {
boolean handled = false;
+ boolean dispatchItemClick = true;
if (mChoiceMode != CHOICE_MODE_NONE) {
handled = true;
@@ -879,6 +880,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (mChoiceActionMode != null) {
mMultiChoiceModeCallback.onItemCheckedStateChanged(mChoiceActionMode,
position, id, newValue);
+ dispatchItemClick = false;
}
} else if (mChoiceMode == CHOICE_MODE_SINGLE) {
boolean newValue = !mCheckStates.get(position, false);
@@ -900,7 +902,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
requestLayout();
}
- handled |= super.performItemClick(view, position, id);
+ if (dispatchItemClick) {
+ handled |= super.performItemClick(view, position, id);
+ }
return handled;
}
@@ -1984,6 +1988,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (mAdapter != null && mDataSetObserver == null) {
mDataSetObserver = new AdapterDataSetObserver();
mAdapter.registerDataSetObserver(mDataSetObserver);
+
+ // Data may have changed while we were detached. Refresh.
+ mDataChanged = true;
+ mOldItemCount = mItemCount;
+ mItemCount = mAdapter.getCount();
}
}
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index 87453ae..bb2e26c3 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -69,12 +69,12 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
* The number of views that the {@link AdapterViewAnimator} keeps as children at any
* given time (not counting views that are pending removal, see {@link #mPreviousViews}).
*/
- int mNumActiveViews = 1;
+ int mMaxNumActiveViews = 1;
/**
* Map of the children of the {@link AdapterViewAnimator}.
*/
- private HashMap<Integer, ViewAndIndex> mViewsMap = new HashMap<Integer, ViewAndIndex>();
+ HashMap<Integer, ViewAndIndex> mViewsMap = new HashMap<Integer, ViewAndIndex>();
/**
* List of views pending removal from the {@link AdapterViewAnimator}
@@ -141,8 +141,6 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
ObjectAnimator mInAnimation;
ObjectAnimator mOutAnimation;
- private ArrayList<View> mViewsToBringToFront;
-
private static final int DEFAULT_ANIMATION_DURATION = 200;
public AdapterViewAnimator(Context context) {
@@ -188,10 +186,9 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
private void initViewAnimator() {
mMainQueue = new Handler(Looper.myLooper());
mPreviousViews = new ArrayList<Integer>();
- mViewsToBringToFront = new ArrayList<View>();
}
- private class ViewAndIndex {
+ class ViewAndIndex {
ViewAndIndex(View v, int i) {
view = v;
index = i;
@@ -217,7 +214,7 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
if (activeOffset > numVisibleViews - 1) {
// Throw an exception here.
}
- mNumActiveViews = numVisibleViews;
+ mMaxNumActiveViews = numVisibleViews;
mActiveOffset = activeOffset;
mPreviousViews.clear();
mViewsMap.clear();
@@ -266,10 +263,10 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
public void setDisplayedChild(int whichChild) {
if (mAdapter != null) {
mWhichChild = whichChild;
- if (whichChild >= mAdapter.getCount()) {
- mWhichChild = mLoopViews ? 0 : mAdapter.getCount() - 1;
+ if (whichChild >= getWindowSize()) {
+ mWhichChild = mLoopViews ? 0 : getWindowSize() - 1;
} else if (whichChild < 0) {
- mWhichChild = mLoopViews ? mAdapter.getCount() - 1 : 0;
+ mWhichChild = mLoopViews ? getWindowSize() - 1 : 0;
}
boolean hasFocus = getFocusedChild() != null;
@@ -327,7 +324,7 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
showOnly(childIndex, animate, false);
}
- private int modulo(int pos, int size) {
+ int modulo(int pos, int size) {
if (size > 0) {
return (size + (pos % size)) % size;
} else {
@@ -342,9 +339,8 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
* @return View at this index, null if the index is outside the bounds
*/
View getViewAtRelativeIndex(int relativeIndex) {
- if (relativeIndex >= 0 && relativeIndex <= mNumActiveViews - 1 && mAdapter != null) {
- int adapterCount = mAdapter.getCount();
- int i = modulo(mCurrentWindowStartUnbounded + relativeIndex, adapterCount);
+ if (relativeIndex >= 0 && relativeIndex <= getNumActiveViews() - 1 && mAdapter != null) {
+ int i = modulo(mCurrentWindowStartUnbounded + relativeIndex, getWindowSize());
if (mViewsMap.get(i) != null) {
return mViewsMap.get(i).view;
}
@@ -352,6 +348,27 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
return null;
}
+ int getNumActiveViews() {
+ if (mAdapter != null) {
+ return Math.min(mAdapter.getCount() + 1, mMaxNumActiveViews);
+ } else {
+ return mMaxNumActiveViews;
+ }
+ }
+
+ int getWindowSize() {
+ if (mAdapter != null) {
+ int adapterCount = mAdapter.getCount();
+ if (adapterCount <= getNumActiveViews() && mLoopViews) {
+ return adapterCount*mMaxNumActiveViews;
+ } else {
+ return adapterCount;
+ }
+ } else {
+ return 0;
+ }
+ }
+
LayoutParams createOrReuseLayoutParams(View v) {
final ViewGroup.LayoutParams currentLp = v.getLayoutParams();
if (currentLp instanceof ViewGroup.LayoutParams) {
@@ -363,7 +380,7 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
void refreshChildren() {
for (int i = mCurrentWindowStart; i <= mCurrentWindowEnd; i++) {
- int index = modulo(i, mNumActiveViews);
+ int index = modulo(i, mMaxNumActiveViews);
// get the fresh child from the adapter
View updatedChild = mAdapter.getView(i, null, this);
@@ -412,7 +429,7 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
}
mPreviousViews.clear();
int newWindowStartUnbounded = childIndex - mActiveOffset;
- int newWindowEndUnbounded = newWindowStartUnbounded + mNumActiveViews - 1;
+ int newWindowEndUnbounded = newWindowStartUnbounded + getNumActiveViews() - 1;
int newWindowStart = Math.max(0, newWindowStartUnbounded);
int newWindowEnd = Math.min(adapterCount - 1, newWindowEndUnbounded);
@@ -420,8 +437,8 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
newWindowStart = newWindowStartUnbounded;
newWindowEnd = newWindowEndUnbounded;
}
- int rangeStart = modulo(newWindowStart, adapterCount);
- int rangeEnd = modulo(newWindowEnd, adapterCount);
+ int rangeStart = modulo(newWindowStart, getWindowSize());
+ int rangeEnd = modulo(newWindowEnd, getWindowSize());
boolean wrap = false;
if (rangeStart > rangeEnd) {
@@ -450,11 +467,12 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
}
// If the window has changed
- if (!(newWindowStart == mCurrentWindowStart && newWindowEnd == mCurrentWindowEnd)) {
+ if (!(newWindowStart == mCurrentWindowStart && newWindowEnd == mCurrentWindowEnd &&
+ newWindowStartUnbounded == mCurrentWindowStartUnbounded)) {
// Run through the indices in the new range
for (int i = newWindowStart; i <= newWindowEnd; i++) {
- int index = modulo(i, adapterCount);
+ int index = modulo(i, getWindowSize());
int oldRelativeIndex;
if (mViewsMap.containsKey(index)) {
oldRelativeIndex = mViewsMap.get(index).index;
@@ -494,13 +512,6 @@ public abstract class AdapterViewAnimator extends AdapterView<Adapter>
}
mViewsMap.get(index).view.bringToFront();
}
-
- for (int i = 0; i < mViewsToBringToFront.size(); i++) {
- View v = mViewsToBringToFront.get(i);
- v.bringToFront();
- }
- mViewsToBringToFront.clear();
-
mCurrentWindowStart = newWindowStart;
mCurrentWindowEnd = newWindowEnd;
mCurrentWindowStartUnbounded = newWindowStartUnbounded;
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 1d36b49..029aebf 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -306,6 +306,10 @@ public class SearchView extends LinearLayout {
*/
public void setQuery(CharSequence query, boolean submit) {
mQueryTextView.setText(query);
+ if (query != null) {
+ mQueryTextView.setSelection(query.length());
+ }
+
// If the query is not empty and submit is requested, submit the query
if (submit && !TextUtils.isEmpty(query)) {
onSubmitQuery();
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 4c3927b..c05da03 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -129,7 +129,7 @@ public class StackView extends AdapterViewAnimator {
}
private void initStackView() {
- configureViewAnimator(NUM_ACTIVE_VIEWS, NUM_ACTIVE_VIEWS - 2);
+ configureViewAnimator(NUM_ACTIVE_VIEWS, 1);
setStaticTransformationsEnabled(true);
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = configuration.getScaledTouchSlop();
@@ -165,7 +165,7 @@ public class StackView extends AdapterViewAnimator {
* Animate the views between different relative indexes within the {@link AdapterViewAnimator}
*/
void animateViewForTransition(int fromIndex, int toIndex, View view) {
- if (fromIndex == -1 && toIndex == 0) {
+ if (fromIndex == -1 && toIndex != 0) {
// Fade item in
if (view.getAlpha() == 1) {
view.setAlpha(0);
@@ -175,7 +175,7 @@ public class StackView extends AdapterViewAnimator {
ObjectAnimator fadeIn = ObjectAnimator.ofFloat(view, "alpha", view.getAlpha(), 1.0f);
fadeIn.setDuration(DEFAULT_ANIMATION_DURATION);
fadeIn.start();
- } else if (fromIndex == mNumActiveViews - 1 && toIndex == mNumActiveViews - 2) {
+ } else if (fromIndex == 0 && toIndex == 1) {
// Slide item in
view.setVisibility(VISIBLE);
@@ -189,7 +189,7 @@ public class StackView extends AdapterViewAnimator {
pa.setDuration(duration);
pa.setInterpolator(new LinearInterpolator());
pa.start();
- } else if (fromIndex == mNumActiveViews - 2 && toIndex == mNumActiveViews - 1) {
+ } else if (fromIndex == 1 && toIndex == 0) {
// Slide item out
int duration = Math.round(mStackSlider.getDurationForOffscreenPosition(mYVelocity));
@@ -201,7 +201,7 @@ public class StackView extends AdapterViewAnimator {
pa.setDuration(duration);
pa.setInterpolator(new LinearInterpolator());
pa.start();
- } else if (fromIndex == -1 && toIndex == mNumActiveViews - 1) {
+ } else if (fromIndex == -1 && toIndex == 0) {
// Make sure this view that is "waiting in the wings" is invisible
view.setAlpha(0.0f);
view.setVisibility(INVISIBLE);
@@ -223,9 +223,10 @@ public class StackView extends AdapterViewAnimator {
private void transformViewAtIndex(int index, View view) {
float maxPerpectiveShift = mMeasuredHeight * PERSPECTIVE_SHIFT_FACTOR;
- if (index == mNumActiveViews -1) index--;
+ index = mMaxNumActiveViews - index - 1;
+ if (index == mMaxNumActiveViews - 1) index--;
- float r = (index * 1.0f) / (mNumActiveViews - 2);
+ float r = (index * 1.0f) / (mMaxNumActiveViews - 2);
float scale = 1 - PERSPECTIVE_SCALE_FACTOR * (1 - r);
PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", scale);
@@ -245,8 +246,20 @@ public class StackView extends AdapterViewAnimator {
pa.start();
}
+ @Override
+ void showOnly(int childIndex, boolean animate, boolean onLayout) {
+ super.showOnly(childIndex, animate, onLayout);
+
+ // Here we need to make sure that the z-order of the children is correct
+ for (int i = mCurrentWindowEnd; i >= mCurrentWindowStart; i--) {
+ int index = modulo(i, getWindowSize());
+ View v = mViewsMap.get(index).view;
+ if (v != null) v.bringToFront();
+ }
+ }
+
private void updateChildTransforms() {
- for (int i = 0; i < mNumActiveViews - 1; i++) {
+ for (int i = 0; i < getNumActiveViews(); i++) {
View v = getViewAtRelativeIndex(i);
if (v != null) {
transformViewAtIndex(i, v);
@@ -341,19 +354,17 @@ public class StackView extends AdapterViewAnimator {
int activeIndex;
if (mStackMode == ITEMS_SLIDE_UP) {
- activeIndex = (swipeGestureType == GESTURE_SLIDE_DOWN) ?
- mNumActiveViews - 1 : mNumActiveViews - 2;
+ activeIndex = (swipeGestureType == GESTURE_SLIDE_DOWN) ? 0 : 1;
} else {
- activeIndex = (swipeGestureType == GESTURE_SLIDE_DOWN) ?
- mNumActiveViews - 2 : mNumActiveViews - 1;
+ activeIndex = (swipeGestureType == GESTURE_SLIDE_DOWN) ? 1 : 0;
}
if (mLoopViews) {
mStackSlider.setMode(StackSlider.NORMAL_MODE);
- } else if (mCurrentWindowStartUnbounded + activeIndex == 0) {
+ } else if (mCurrentWindowStartUnbounded + activeIndex == -1) {
+ activeIndex++;
mStackSlider.setMode(StackSlider.BEGINNING_OF_STACK_MODE);
- } else if (mCurrentWindowStartUnbounded + activeIndex == mAdapter.getCount()) {
- activeIndex--;
+ } else if (mCurrentWindowStartUnbounded + activeIndex == mAdapter.getCount() - 1) {
mStackSlider.setMode(StackSlider.END_OF_STACK_MODE);
} else {
mStackSlider.setMode(StackSlider.NORMAL_MODE);
@@ -439,8 +450,7 @@ public class StackView extends AdapterViewAnimator {
final int pointerId = ev.getPointerId(activePointerIndex);
if (pointerId == mActivePointerId) {
- int activeViewIndex = (mSwipeGestureType == GESTURE_SLIDE_DOWN) ? mNumActiveViews - 1
- : mNumActiveViews - 2;
+ int activeViewIndex = (mSwipeGestureType == GESTURE_SLIDE_DOWN) ? 0 : 1;
View v = getViewAtRelativeIndex(activeViewIndex);
if (v == null) return;
@@ -498,18 +508,18 @@ public class StackView extends AdapterViewAnimator {
&& mStackSlider.mMode == StackSlider.NORMAL_MODE) {
// Swipe threshold exceeded, swipe down
if (mStackMode == ITEMS_SLIDE_UP) {
- showNext();
- } else {
showPrevious();
+ } else {
+ showNext();
}
mHighlight.bringToFront();
} else if (deltaY < -mSwipeThreshold && mSwipeGestureType == GESTURE_SLIDE_UP
&& mStackSlider.mMode == StackSlider.NORMAL_MODE) {
// Swipe threshold exceeded, swipe up
if (mStackMode == ITEMS_SLIDE_UP) {
- showPrevious();
- } else {
showNext();
+ } else {
+ showPrevious();
}
mHighlight.bringToFront();
@@ -643,13 +653,13 @@ public class StackView extends AdapterViewAnimator {
mView.setRotationX(stackDirection * 90.0f * rotationInterpolator(r));
mHighlight.setRotationX(stackDirection * 90.0f * rotationInterpolator(r));
break;
- case BEGINNING_OF_STACK_MODE:
+ case END_OF_STACK_MODE:
r = r * 0.2f;
viewLp.setVerticalOffset(Math.round(-stackDirection * r * mSlideAmount));
highlightLp.setVerticalOffset(Math.round(-stackDirection * r * mSlideAmount));
mHighlight.setAlpha(highlightAlphaInterpolator(r));
break;
- case END_OF_STACK_MODE:
+ case BEGINNING_OF_STACK_MODE:
r = (1-r) * 0.2f;
viewLp.setVerticalOffset(Math.round(stackDirection * r * mSlideAmount));
highlightLp.setVerticalOffset(Math.round(stackDirection * r * mSlideAmount));
@@ -735,12 +745,10 @@ public class StackView extends AdapterViewAnimator {
public void onRemoteAdapterConnected() {
super.onRemoteAdapterConnected();
// On first run, we want to set the stack to the end.
- if (mAdapter != null && mWhichChild == -1) {
- mWhichChild = mAdapter.getCount() - 1;
- }
- if (mWhichChild >= 0) {
- setDisplayedChild(mWhichChild);
+ if (mWhichChild == -1) {
+ mWhichChild = 0;
}
+ setDisplayedChild(mWhichChild);
}
LayoutParams createOrReuseLayoutParams(View v) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index be056da..09563fc 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -5018,6 +5018,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
mLayout = mHintLayout = null;
+
+ // Since it depends on the value of mLayout
+ prepareCursorControllers();
}
/**
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 224f9a5..0f482b7 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -51,8 +51,8 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
@@ -65,16 +65,16 @@ public final class BatteryStatsImpl extends BatteryStats {
private static final String TAG = "BatteryStatsImpl";
private static final boolean DEBUG = false;
private static final boolean DEBUG_HISTORY = false;
-
+
// In-memory Parcel magic number, used to detect attempts to unmarshall bad data
- private static final int MAGIC = 0xBA757475; // 'BATSTATS'
+ private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
private static final int VERSION = 52;
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
-
+
// No, really, THIS is the maximum number of items we will record in the history.
private static final int MAX_MAX_HISTORY_ITEMS = 3000;
@@ -82,9 +82,9 @@ public final class BatteryStatsImpl extends BatteryStats {
// per uid; once the limit is reached, we batch the remaining wakelocks
// in to one common name.
private static final int MAX_WAKELOCKS_PER_UID = 30;
-
+
private static final String BATCHED_WAKELOCK_NAME = "*overflow*";
-
+
private static int sNumSpeedSteps;
private final JournaledFile mFile;
@@ -147,9 +147,9 @@ public final class BatteryStatsImpl extends BatteryStats {
// These are the objects that will want to do something when the device
// is unplugged from power.
final ArrayList<Unpluggable> mUnpluggables = new ArrayList<Unpluggable>();
-
+
boolean mShuttingDown;
-
+
long mHistoryBaseTime;
boolean mHaveBatteryLevel = false;
boolean mRecordingHistory = true;
@@ -159,7 +159,7 @@ public final class BatteryStatsImpl extends BatteryStats {
HistoryItem mHistoryLastEnd;
HistoryItem mHistoryCache;
final HistoryItem mHistoryCur = new HistoryItem();
-
+
int mStartCount;
long mBatteryUptime;
@@ -173,41 +173,41 @@ public final class BatteryStatsImpl extends BatteryStats {
long mRealtime;
long mRealtimeStart;
long mLastRealtime;
-
+
boolean mScreenOn;
StopwatchTimer mScreenOnTimer;
int mScreenBrightnessBin = -1;
final StopwatchTimer[] mScreenBrightnessTimer = new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
-
+
Counter mInputEventCounter;
-
+
boolean mPhoneOn;
StopwatchTimer mPhoneOnTimer;
-
+
boolean mAudioOn;
StopwatchTimer mAudioOnTimer;
-
+
boolean mVideoOn;
StopwatchTimer mVideoOnTimer;
-
+
int mPhoneSignalStrengthBin = -1;
- final StopwatchTimer[] mPhoneSignalStrengthsTimer =
+ final StopwatchTimer[] mPhoneSignalStrengthsTimer =
new StopwatchTimer[NUM_SIGNAL_STRENGTH_BINS];
StopwatchTimer mPhoneSignalScanningTimer;
int mPhoneDataConnectionType = -1;
- final StopwatchTimer[] mPhoneDataConnectionsTimer =
+ final StopwatchTimer[] mPhoneDataConnectionsTimer =
new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
-
+
boolean mWifiOn;
StopwatchTimer mWifiOnTimer;
int mWifiOnUid = -1;
boolean mGlobalWifiRunning;
StopwatchTimer mGlobalWifiRunningTimer;
-
+
boolean mBluetoothOn;
StopwatchTimer mBluetoothOnTimer;
@@ -256,15 +256,15 @@ public final class BatteryStatsImpl extends BatteryStats {
/*
* Holds a SamplingTimer associated with each kernel wakelock name being tracked.
*/
- private final HashMap<String, SamplingTimer> mKernelWakelockStats =
+ private final HashMap<String, SamplingTimer> mKernelWakelockStats =
new HashMap<String, SamplingTimer>();
-
+
public Map<String, ? extends SamplingTimer> getKernelWakelockStats() {
return mKernelWakelockStats;
}
-
+
private static int sKernelWakelockUpdateVersion = 0;
-
+
private static final int[] PROC_WAKELOCKS_FORMAT = new int[] {
Process.PROC_TAB_TERM|Process.PROC_OUT_STRING, // 0: name
Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 1: count
@@ -273,19 +273,19 @@ public final class BatteryStatsImpl extends BatteryStats {
Process.PROC_TAB_TERM,
Process.PROC_TAB_TERM|Process.PROC_OUT_LONG, // 5: totalTime
};
-
+
private final String[] mProcWakelocksName = new String[3];
private final long[] mProcWakelocksData = new long[3];
-
+
/*
* Used as a buffer for reading in data from /proc/wakelocks before it is processed and added
* to mKernelWakelockStats.
*/
- private final Map<String, KernelWakelockStats> mProcWakelockFileStats =
+ private final Map<String, KernelWakelockStats> mProcWakelockFileStats =
new HashMap<String, KernelWakelockStats>();
private HashMap<String, Integer> mUidCache = new HashMap<String, Integer>();
-
+
// For debugging
public BatteryStatsImpl() {
mFile = null;
@@ -296,7 +296,7 @@ public final class BatteryStatsImpl extends BatteryStats {
void unplug(long batteryUptime, long batteryRealtime);
void plug(long batteryUptime, long batteryRealtime);
}
-
+
/**
* State for keeping track of counting information.
*/
@@ -307,7 +307,7 @@ public final class BatteryStatsImpl extends BatteryStats {
int mLastCount;
int mUnpluggedCount;
int mPluggedCount;
-
+
Counter(ArrayList<Unpluggable> unpluggables, Parcel in) {
mUnpluggables = unpluggables;
mPluggedCount = in.readInt();
@@ -322,7 +322,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mUnpluggables = unpluggables;
unpluggables.add(this);
}
-
+
public void writeToParcel(Parcel out) {
out.writeInt(mCount.get());
out.writeInt(mLoadedCount);
@@ -337,7 +337,7 @@ public final class BatteryStatsImpl extends BatteryStats {
public void plug(long batteryUptime, long batteryRealtime) {
mPluggedCount = mCount.get();
}
-
+
/**
* Writes a possibly null Counter to a Parcel.
*
@@ -377,7 +377,7 @@ public final class BatteryStatsImpl extends BatteryStats {
+ " mUnpluggedCount=" + mUnpluggedCount
+ " mPluggedCount=" + mPluggedCount);
}
-
+
void stepAtomic() {
mCount.incrementAndGet();
}
@@ -392,11 +392,11 @@ public final class BatteryStatsImpl extends BatteryStats {
detach();
}
}
-
+
void detach() {
mUnpluggables.remove(this);
}
-
+
void writeSummaryFromParcelLocked(Parcel out) {
int count = mCount.get();
out.writeInt(count);
@@ -431,41 +431,41 @@ public final class BatteryStatsImpl extends BatteryStats {
public static abstract class Timer extends BatteryStats.Timer implements Unpluggable {
final int mType;
final ArrayList<Unpluggable> mUnpluggables;
-
+
int mCount;
int mLoadedCount;
int mLastCount;
int mUnpluggedCount;
-
+
// Times are in microseconds for better accuracy when dividing by the
// lock count, and are in "battery realtime" units.
-
+
/**
* The total time we have accumulated since the start of the original
* boot, to the last time something interesting happened in the
* current run.
*/
long mTotalTime;
-
+
/**
* The total time we loaded for the previous runs. Subtract this from
* mTotalTime to find the time for the current run of the system.
*/
long mLoadedTime;
-
+
/**
* The run time of the last run of the system, as loaded from the
* saved data.
*/
long mLastTime;
-
+
/**
* The value of mTotalTime when unplug() was last called. Subtract
* this from mTotalTime to find the time since the last unplug from
* power.
*/
long mUnpluggedTime;
-
+
/**
* Constructs from a parcel.
* @param type
@@ -476,7 +476,7 @@ public final class BatteryStatsImpl extends BatteryStats {
Timer(int type, ArrayList<Unpluggable> unpluggables, Parcel in) {
mType = type;
mUnpluggables = unpluggables;
-
+
mCount = in.readInt();
mLoadedCount = in.readInt();
mLastCount = 0;
@@ -495,9 +495,9 @@ public final class BatteryStatsImpl extends BatteryStats {
}
protected abstract long computeRunTimeLocked(long curBatteryRealtime);
-
+
protected abstract int computeCurrentCountLocked();
-
+
/**
* Clear state of this timer. Returns true if the timer is inactive
* so can be completely dropped.
@@ -510,11 +510,11 @@ public final class BatteryStatsImpl extends BatteryStats {
}
return true;
}
-
+
void detach() {
mUnpluggables.remove(this);
}
-
+
public void writeToParcel(Parcel out, long batteryRealtime) {
out.writeInt(mCount);
out.writeInt(mLoadedCount);
@@ -551,7 +551,7 @@ public final class BatteryStatsImpl extends BatteryStats {
+ ": new mTotalTime=" + mTotalTime);
}
}
-
+
/**
* Writes a possibly null Timer to a Parcel.
*
@@ -612,8 +612,8 @@ public final class BatteryStatsImpl extends BatteryStats {
pw.println(prefix + "mLastTime=" + mLastTime
+ " mUnpluggedTime=" + mUnpluggedTime);
}
-
-
+
+
void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
long runTime = computeRunTimeLocked(batteryRealtime);
// Divide by 1000 for backwards compatibility
@@ -631,9 +631,9 @@ public final class BatteryStatsImpl extends BatteryStats {
mUnpluggedCount = mCount;
}
}
-
+
public static final class SamplingTimer extends Timer {
-
+
/**
* The most recent reported count from /proc/wakelocks.
*/
@@ -647,7 +647,7 @@ public final class BatteryStatsImpl extends BatteryStats {
/**
* The most recent reported total_time from /proc/wakelocks.
- */
+ */
long mCurrentReportedTotalTime;
@@ -666,12 +666,12 @@ public final class BatteryStatsImpl extends BatteryStats {
* Whether we are currently recording reported values.
*/
boolean mTrackingReportedValues;
-
+
/*
* A sequnce counter, incremented once for each update of the stats.
*/
int mUpdateVersion;
-
+
SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge, Parcel in) {
super(0, unpluggables, in);
mCurrentReportedCount = in.readInt();
@@ -681,28 +681,28 @@ public final class BatteryStatsImpl extends BatteryStats {
mTrackingReportedValues = in.readInt() == 1;
mInDischarge = inDischarge;
}
-
- SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge,
+
+ SamplingTimer(ArrayList<Unpluggable> unpluggables, boolean inDischarge,
boolean trackReportedValues) {
super(0, unpluggables);
mTrackingReportedValues = trackReportedValues;
mInDischarge = inDischarge;
}
-
+
public void setStale() {
mTrackingReportedValues = false;
mUnpluggedReportedTotalTime = 0;
mUnpluggedReportedCount = 0;
}
-
+
public void setUpdateVersion(int version) {
mUpdateVersion = version;
}
-
+
public int getUpdateVersion() {
return mUpdateVersion;
}
-
+
public void updateCurrentReportedCount(int count) {
if (mInDischarge && mUnpluggedReportedCount == 0) {
// Updating the reported value for the first time.
@@ -712,7 +712,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
mCurrentReportedCount = count;
}
-
+
public void updateCurrentReportedTotalTime(long totalTime) {
if (mInDischarge && mUnpluggedReportedTotalTime == 0) {
// Updating the reported value for the first time.
@@ -722,7 +722,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
mCurrentReportedTotalTime = totalTime;
}
-
+
public void unplug(long batteryUptime, long batteryRealtime) {
super.unplug(batteryUptime, batteryRealtime);
if (mTrackingReportedValues) {
@@ -736,25 +736,25 @@ public final class BatteryStatsImpl extends BatteryStats {
super.plug(batteryUptime, batteryRealtime);
mInDischarge = false;
}
-
+
public void logState(Printer pw, String prefix) {
super.logState(pw, prefix);
- pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
+ pw.println(prefix + "mCurrentReportedCount=" + mCurrentReportedCount
+ " mUnpluggedReportedCount=" + mUnpluggedReportedCount
+ " mCurrentReportedTotalTime=" + mCurrentReportedTotalTime
+ " mUnpluggedReportedTotalTime=" + mUnpluggedReportedTotalTime);
}
-
+
protected long computeRunTimeLocked(long curBatteryRealtime) {
- return mTotalTime + (mInDischarge && mTrackingReportedValues
+ return mTotalTime + (mInDischarge && mTrackingReportedValues
? mCurrentReportedTotalTime - mUnpluggedReportedTotalTime : 0);
}
-
+
protected int computeCurrentCountLocked() {
return mCount + (mInDischarge && mTrackingReportedValues
? mCurrentReportedCount - mUnpluggedReportedCount : 0);
}
-
+
public void writeToParcel(Parcel out, long batteryRealtime) {
super.writeToParcel(out, batteryRealtime);
out.writeInt(mCurrentReportedCount);
@@ -763,13 +763,13 @@ public final class BatteryStatsImpl extends BatteryStats {
out.writeLong(mUnpluggedReportedTotalTime);
out.writeInt(mTrackingReportedValues ? 1 : 0);
}
-
+
boolean reset(BatteryStatsImpl stats, boolean detachIfReset) {
super.reset(stats, detachIfReset);
setStale();
return true;
}
-
+
void writeSummaryFromParcelLocked(Parcel out, long batteryRealtime) {
super.writeSummaryFromParcelLocked(out, batteryRealtime);
out.writeLong(mCurrentReportedTotalTime);
@@ -784,7 +784,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mTrackingReportedValues = in.readInt() == 1;
}
}
-
+
/**
* State for keeping track of timing information.
*/
@@ -800,7 +800,7 @@ public final class BatteryStatsImpl extends BatteryStats {
* time we have been running since we last computed an update.
*/
long mUpdateTime;
-
+
/**
* The total time at which the timer was acquired, to determine if it
* was actually held for an interesting duration.
@@ -829,7 +829,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mUid = uid;
mTimerPool = timerPool;
}
-
+
void setTimeout(long timeout) {
mTimeout = timeout;
}
@@ -857,7 +857,7 @@ public final class BatteryStatsImpl extends BatteryStats {
pw.println(prefix + "mNesting=" + mNesting + "mUpdateTime=" + mUpdateTime
+ " mAcquireTime=" + mAcquireTime);
}
-
+
void startRunningLocked(BatteryStatsImpl stats) {
if (mNesting++ == 0) {
mUpdateTime = stats.getBatteryRealtimeLocked(
@@ -897,19 +897,19 @@ public final class BatteryStatsImpl extends BatteryStats {
// Remove this timer from the active pool
mTimerPool.remove(this);
} else {
- final long realtime = SystemClock.elapsedRealtime() * 1000;
+ final long realtime = SystemClock.elapsedRealtime() * 1000;
final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime);
mNesting = 1;
mTotalTime = computeRunTimeLocked(batteryRealtime);
mNesting = 0;
}
-
+
if (DEBUG && mType < 0) {
Log.v(TAG, "stop #" + mType + ": mUpdateTime=" + mUpdateTime
+ " mTotalTime=" + mTotalTime + " mCount=" + mCount
+ " mAcquireTime=" + mAcquireTime);
}
-
+
if (mTotalTime == mAcquireTime) {
// If there was no change in the time, then discard this
// count. A somewhat cheezy strategy, but hey.
@@ -922,7 +922,7 @@ public final class BatteryStatsImpl extends BatteryStats {
// due to a change in timer count
private static void refreshTimersLocked(final BatteryStatsImpl stats,
final ArrayList<StopwatchTimer> pool) {
- final long realtime = SystemClock.elapsedRealtime() * 1000;
+ final long realtime = SystemClock.elapsedRealtime() * 1000;
final long batteryRealtime = stats.getBatteryRealtimeLocked(realtime);
final int N = pool.size();
for (int i=N-1; i>= 0; i--) {
@@ -961,25 +961,25 @@ public final class BatteryStatsImpl extends BatteryStats {
mAcquireTime = mTotalTime;
return canDetach;
}
-
+
void detach() {
super.detach();
if (mTimerPool != null) {
mTimerPool.remove(this);
}
}
-
+
void readSummaryFromParcelLocked(Parcel in) {
super.readSummaryFromParcelLocked(in);
mNesting = 0;
}
}
-
+
private final Map<String, KernelWakelockStats> readKernelWakelockStats() {
-
+
byte[] buffer = new byte[8192];
int len;
-
+
try {
FileInputStream is = new FileInputStream("/proc/wakelocks");
len = is.read(buffer);
@@ -999,10 +999,10 @@ public final class BatteryStatsImpl extends BatteryStats {
} catch (java.io.IOException e) {
return null;
}
-
+
return parseProcWakelocks(buffer, len);
}
-
+
private final Map<String, KernelWakelockStats> parseProcWakelocks(
byte[] wlBuffer, int len) {
String name;
@@ -1018,11 +1018,11 @@ public final class BatteryStatsImpl extends BatteryStats {
synchronized(this) {
Map<String, KernelWakelockStats> m = mProcWakelockFileStats;
-
+
sKernelWakelockUpdateVersion++;
while (endIndex < len) {
- for (endIndex=startIndex;
- endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0';
+ for (endIndex=startIndex;
+ endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0';
endIndex++);
endIndex++; // endIndex is an exclusive upper bound.
// Don't go over the end of the buffer, Process.parseProcLine might
@@ -1049,7 +1049,7 @@ public final class BatteryStatsImpl extends BatteryStats {
if (parsed && name.length() > 0) {
if (!m.containsKey(name)) {
- m.put(name, new KernelWakelockStats(count, totalTime,
+ m.put(name, new KernelWakelockStats(count, totalTime,
sKernelWakelockUpdateVersion));
numUpdatedWlNames++;
} else {
@@ -1080,27 +1080,27 @@ public final class BatteryStatsImpl extends BatteryStats {
return m;
}
}
-
+
private class KernelWakelockStats {
public int mCount;
public long mTotalTime;
public int mVersion;
-
+
KernelWakelockStats(int count, long totalTime, int version) {
mCount = count;
mTotalTime = totalTime;
mVersion = version;
}
}
-
+
/*
- * Get the KernelWakelockTimer associated with name, and create a new one if one
+ * Get the KernelWakelockTimer associated with name, and create a new one if one
* doesn't already exist.
*/
public SamplingTimer getKernelWakelockTimerLocked(String name) {
SamplingTimer kwlt = mKernelWakelockStats.get(name);
if (kwlt == null) {
- kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal,
+ kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal,
true /* track reported values */);
mKernelWakelockStats.put(name, kwlt);
}
@@ -1144,7 +1144,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
/**
- * Returns the duration that the cell radio was up for data transfers.
+ * Returns the duration that the cell radio was up for data transfers.
*/
public long getRadioDataUptime() {
if (mRadioDataStart == -1) {
@@ -1156,10 +1156,9 @@ public final class BatteryStatsImpl extends BatteryStats {
private int getCurrentBluetoothPingCount() {
if (mBtHeadset != null) {
- Set<BluetoothDevice> deviceSet = mBtHeadset.getConnectedDevices();
- BluetoothDevice[] devices = deviceSet.toArray(new BluetoothDevice[deviceSet.size()]);
- if (devices.length > 0) {
- return mBtHeadset.getBatteryUsageHint(devices[0]);
+ List<BluetoothDevice> deviceList = mBtHeadset.getConnectedDevices();
+ if (deviceList.size() > 0) {
+ return mBtHeadset.getBatteryUsageHint(deviceList.get(0));
}
}
return -1;
@@ -1234,7 +1233,7 @@ public final class BatteryStatsImpl extends BatteryStats {
addHistoryRecordLocked(curTime, HistoryItem.CMD_UPDATE);
}
-
+
void addHistoryRecordLocked(long curTime, byte cmd) {
HistoryItem rec = mHistoryCache;
if (rec != null) {
@@ -1243,10 +1242,10 @@ public final class BatteryStatsImpl extends BatteryStats {
rec = new HistoryItem();
}
rec.setTo(mHistoryBaseTime + curTime, cmd, mHistoryCur);
-
+
addHistoryRecordLocked(rec);
}
-
+
void addHistoryRecordLocked(HistoryItem rec) {
mNumHistoryItems++;
rec.next = null;
@@ -1258,7 +1257,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mHistory = mHistoryEnd = rec;
}
}
-
+
void clearHistoryLocked() {
if (mHistory != null) {
mHistoryEnd.next = mHistoryCache;
@@ -1268,7 +1267,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mNumHistoryItems = 0;
mHistoryBaseTime = 0;
}
-
+
public void doUnplugLocked(long batteryUptime, long batteryRealtime) {
for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
Uid u = mUidStats.valueAt(iu);
@@ -1532,7 +1531,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
int mGpsNesting;
-
+
public void noteStartGpsLocked(int uid) {
if (mGpsNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_GPS_ON_FLAG;
@@ -1543,7 +1542,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mGpsNesting++;
getUidStatsLocked(uid).noteStartGps();
}
-
+
public void noteStopGpsLocked(int uid) {
mGpsNesting--;
if (mGpsNesting == 0) {
@@ -1572,7 +1571,7 @@ public final class BatteryStatsImpl extends BatteryStats {
noteStartWakeLocked(-1, -1, "dummy", WAKE_TYPE_PARTIAL);
}
}
-
+
public void noteScreenOffLocked() {
if (mScreenOn) {
mHistoryCur.states &= ~HistoryItem.STATE_SCREEN_ON_FLAG;
@@ -1588,7 +1587,7 @@ public final class BatteryStatsImpl extends BatteryStats {
noteStopWakeLocked(-1, -1, "dummy", WAKE_TYPE_PARTIAL);
}
}
-
+
public void noteScreenBrightnessLocked(int brightness) {
// Bin the brightness.
int bin = brightness / (256/NUM_SCREEN_BRIGHTNESS_BINS);
@@ -1609,15 +1608,15 @@ public final class BatteryStatsImpl extends BatteryStats {
mScreenBrightnessBin = bin;
}
}
-
+
public void noteInputEventAtomic() {
mInputEventCounter.stepAtomic();
}
-
+
public void noteUserActivityLocked(int uid, int event) {
getUidStatsLocked(uid).noteUserActivityLocked(event);
}
-
+
public void notePhoneOnLocked() {
if (!mPhoneOn) {
mHistoryCur.states |= HistoryItem.STATE_PHONE_IN_CALL_FLAG;
@@ -1628,7 +1627,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mPhoneOnTimer.startRunningLocked(this);
}
}
-
+
public void notePhoneOffLocked() {
if (mPhoneOn) {
mHistoryCur.states &= ~HistoryItem.STATE_PHONE_IN_CALL_FLAG;
@@ -1688,7 +1687,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mPhoneSignalScanningTimer.startRunningLocked(this);
}
}
-
+
if (!scanning) {
// If we are no longer scanning, then stop the scanning timer.
if (mPhoneSignalScanningTimer.isRunningLocked()) {
@@ -1746,7 +1745,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mPhoneSignalStrengthsTimer[bin].startRunningLocked(this);
}
}
-
+
public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
int bin = DATA_CONNECTION_NONE;
if (hasData) {
@@ -1806,7 +1805,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mPhoneDataConnectionsTimer[bin].startRunningLocked(this);
}
}
-
+
public void noteWifiOnLocked() {
if (!mWifiOn) {
mHistoryCur.states |= HistoryItem.STATE_WIFI_ON_FLAG;
@@ -1817,7 +1816,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mWifiOnTimer.startRunningLocked(this);
}
}
-
+
public void noteWifiOffLocked() {
if (mWifiOn) {
mHistoryCur.states &= ~HistoryItem.STATE_WIFI_ON_FLAG;
@@ -1844,7 +1843,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
getUidStatsLocked(uid).noteAudioTurnedOnLocked();
}
-
+
public void noteAudioOffLocked(int uid) {
if (mAudioOn) {
mHistoryCur.states &= ~HistoryItem.STATE_AUDIO_ON_FLAG;
@@ -1868,7 +1867,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
getUidStatsLocked(uid).noteVideoTurnedOnLocked();
}
-
+
public void noteVideoOffLocked(int uid) {
if (mVideoOn) {
mHistoryCur.states &= ~HistoryItem.STATE_VIDEO_ON_FLAG;
@@ -1940,7 +1939,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mBluetoothOnTimer.startRunningLocked(this);
}
}
-
+
public void noteBluetoothOffLocked() {
if (mBluetoothOn) {
mHistoryCur.states &= ~HistoryItem.STATE_BLUETOOTH_ON_FLAG;
@@ -1951,9 +1950,9 @@ public final class BatteryStatsImpl extends BatteryStats {
mBluetoothOnTimer.stopRunningLocked(this);
}
}
-
+
int mWifiFullLockNesting = 0;
-
+
public void noteFullWifiLockAcquiredLocked(int uid) {
if (mWifiFullLockNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_WIFI_FULL_LOCK_FLAG;
@@ -1977,7 +1976,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
int mWifiScanLockNesting = 0;
-
+
public void noteScanWifiLockAcquiredLocked(int uid) {
if (mWifiScanLockNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_WIFI_SCAN_LOCK_FLAG;
@@ -2001,7 +2000,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
int mWifiMulticastNesting = 0;
-
+
public void noteWifiMulticastEnabledLocked(int uid) {
if (mWifiMulticastNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_WIFI_MULTICAST_ON_FLAG;
@@ -2069,7 +2068,7 @@ public final class BatteryStatsImpl extends BatteryStats {
@Override public long getScreenOnTime(long batteryRealtime, int which) {
return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
-
+
@Override public long getScreenBrightnessTime(int brightnessBin,
long batteryRealtime, int which) {
return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
@@ -2079,7 +2078,7 @@ public final class BatteryStatsImpl extends BatteryStats {
@Override public int getInputEventCount(int which) {
return mInputEventCounter.getCountLocked(which);
}
-
+
@Override public long getPhoneOnTime(long batteryRealtime, int which) {
return mPhoneOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
@@ -2099,21 +2098,21 @@ public final class BatteryStatsImpl extends BatteryStats {
@Override public int getPhoneSignalStrengthCount(int dataType, int which) {
return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
}
-
+
@Override public long getPhoneDataConnectionTime(int dataType,
long batteryRealtime, int which) {
return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
batteryRealtime, which);
}
-
+
@Override public int getPhoneDataConnectionCount(int dataType, int which) {
return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
}
-
+
@Override public long getWifiOnTime(long batteryRealtime, int which) {
return mWifiOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
-
+
@Override public long getGlobalWifiRunningTime(long batteryRealtime, int which) {
return mGlobalWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which);
}
@@ -2121,11 +2120,11 @@ public final class BatteryStatsImpl extends BatteryStats {
@Override public long getBluetoothOnTime(long batteryRealtime, int which) {
return mBluetoothOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
-
+
@Override public boolean getIsOnBattery() {
return mOnBattery;
}
-
+
@Override public SparseArray<? extends BatteryStats.Uid> getUidStats() {
return mUidStats;
}
@@ -2134,7 +2133,7 @@ public final class BatteryStatsImpl extends BatteryStats {
* The statistics associated with a particular uid.
*/
public final class Uid extends BatteryStats.Uid {
-
+
final int mUid;
long mLoadedTcpBytesReceived;
long mLoadedTcpBytesSent;
@@ -2142,32 +2141,32 @@ public final class BatteryStatsImpl extends BatteryStats {
long mCurrentTcpBytesSent;
long mTcpBytesReceivedAtLastUnplug;
long mTcpBytesSentAtLastUnplug;
-
+
// These are not saved/restored when parcelling, since we want
// to return from the parcel with a snapshot of the state.
long mStartedTcpBytesReceived = -1;
long mStartedTcpBytesSent = -1;
-
+
boolean mWifiRunning;
StopwatchTimer mWifiRunningTimer;
-
+
boolean mFullWifiLockOut;
StopwatchTimer mFullWifiLockTimer;
-
+
boolean mScanWifiLockOut;
StopwatchTimer mScanWifiLockTimer;
-
+
boolean mWifiMulticastEnabled;
StopwatchTimer mWifiMulticastTimer;
-
+
boolean mAudioTurnedOn;
StopwatchTimer mAudioTurnedOnTimer;
-
+
boolean mVideoTurnedOn;
StopwatchTimer mVideoTurnedOnTimer;
Counter[] mUserActivityCounters;
-
+
/**
* The statistics we have collected for this uid's wake locks.
*/
@@ -2187,7 +2186,7 @@ public final class BatteryStatsImpl extends BatteryStats {
* The statistics we have collected for this uid's processes.
*/
final HashMap<String, Pkg> mPackageStats = new HashMap<String, Pkg>();
-
+
/**
* The transient wake stats we have collected for this uid's pids.
*/
@@ -2248,7 +2247,7 @@ public final class BatteryStatsImpl extends BatteryStats {
return current;
}
}
-
+
public long computeCurrentTcpBytesReceived() {
return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0
? (TrafficStats.getUidRxBytes(mUid) - mStartedTcpBytesReceived) : 0);
@@ -2268,7 +2267,7 @@ public final class BatteryStatsImpl extends BatteryStats {
return current;
}
}
-
+
@Override
public void noteWifiRunningLocked() {
if (!mWifiRunning) {
@@ -2280,7 +2279,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mWifiRunningTimer.startRunningLocked(BatteryStatsImpl.this);
}
}
-
+
@Override
public void noteWifiStoppedLocked() {
if (mWifiRunning) {
@@ -2288,7 +2287,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mWifiRunningTimer.stopRunningLocked(BatteryStatsImpl.this);
}
}
-
+
@Override
public void noteFullWifiLockAcquiredLocked() {
if (!mFullWifiLockOut) {
@@ -2300,7 +2299,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
}
}
-
+
@Override
public void noteFullWifiLockReleasedLocked() {
if (mFullWifiLockOut) {
@@ -2308,7 +2307,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mFullWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this);
}
}
-
+
@Override
public void noteScanWifiLockAcquiredLocked() {
if (!mScanWifiLockOut) {
@@ -2320,7 +2319,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
}
}
-
+
@Override
public void noteScanWifiLockReleasedLocked() {
if (mScanWifiLockOut) {
@@ -2389,7 +2388,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
- @Override
+ @Override
public long getWifiRunningTime(long batteryRealtime, int which) {
if (mWifiRunningTimer == null) {
return 0;
@@ -2397,15 +2396,15 @@ public final class BatteryStatsImpl extends BatteryStats {
return mWifiRunningTimer.getTotalTimeLocked(batteryRealtime, which);
}
- @Override
+ @Override
public long getFullWifiLockTime(long batteryRealtime, int which) {
if (mFullWifiLockTimer == null) {
return 0;
}
return mFullWifiLockTimer.getTotalTimeLocked(batteryRealtime, which);
}
-
- @Override
+
+ @Override
public long getScanWifiLockTime(long batteryRealtime, int which) {
if (mScanWifiLockTimer == null) {
return 0;
@@ -2422,7 +2421,7 @@ public final class BatteryStatsImpl extends BatteryStats {
which);
}
- @Override
+ @Override
public long getAudioTurnedOnTime(long batteryRealtime, int which) {
if (mAudioTurnedOnTimer == null) {
return 0;
@@ -2430,7 +2429,7 @@ public final class BatteryStatsImpl extends BatteryStats {
return mAudioTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
- @Override
+ @Override
public long getVideoTurnedOnTime(long batteryRealtime, int which) {
if (mVideoTurnedOnTimer == null) {
return 0;
@@ -2447,12 +2446,12 @@ public final class BatteryStatsImpl extends BatteryStats {
else if (type >= NUM_USER_ACTIVITY_TYPES) type = NUM_USER_ACTIVITY_TYPES-1;
mUserActivityCounters[type].stepAtomic();
}
-
+
@Override
public boolean hasUserActivity() {
return mUserActivityCounters != null;
}
-
+
@Override
public int getUserActivityCount(int type, int which) {
if (mUserActivityCounters == null) {
@@ -2460,14 +2459,14 @@ public final class BatteryStatsImpl extends BatteryStats {
}
return mUserActivityCounters[type].getCountLocked(which);
}
-
+
void initUserActivityLocked() {
mUserActivityCounters = new Counter[NUM_USER_ACTIVITY_TYPES];
for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
mUserActivityCounters[i] = new Counter(mUnpluggables);
}
}
-
+
public long computeCurrentTcpBytesSent() {
return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0
? (TrafficStats.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0);
@@ -2479,7 +2478,7 @@ public final class BatteryStatsImpl extends BatteryStats {
*/
boolean reset() {
boolean active = false;
-
+
if (mWifiRunningTimer != null) {
active |= !mWifiRunningTimer.reset(BatteryStatsImpl.this, false);
active |= mWifiRunning;
@@ -2504,10 +2503,10 @@ public final class BatteryStatsImpl extends BatteryStats {
active |= !mVideoTurnedOnTimer.reset(BatteryStatsImpl.this, false);
active |= mVideoTurnedOn;
}
-
+
mLoadedTcpBytesReceived = mLoadedTcpBytesSent = 0;
mCurrentTcpBytesReceived = mCurrentTcpBytesSent = 0;
-
+
if (mUserActivityCounters != null) {
for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
mUserActivityCounters[i].reset(false);
@@ -2571,7 +2570,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
mPackageStats.clear();
}
-
+
mPids.clear();
if (!active) {
@@ -2599,10 +2598,10 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
}
-
+
return !active;
}
-
+
void writeToParcelLocked(Parcel out, long batteryRealtime) {
out.writeInt(mWakelockStats.size());
for (Map.Entry<String, Uid.Wakelock> wakelockEntry : mWakelockStats.entrySet()) {
@@ -2631,7 +2630,7 @@ public final class BatteryStatsImpl extends BatteryStats {
Uid.Pkg pkg = pkgEntry.getValue();
pkg.writeToParcelLocked(out);
}
-
+
out.writeLong(mLoadedTcpBytesReceived);
out.writeLong(mLoadedTcpBytesSent);
out.writeLong(computeCurrentTcpBytesReceived());
@@ -2725,7 +2724,7 @@ public final class BatteryStatsImpl extends BatteryStats {
pkg.readFromParcelLocked(in);
mPackageStats.put(packageName, pkg);
}
-
+
mLoadedTcpBytesReceived = in.readLong();
mLoadedTcpBytesSent = in.readLong();
mCurrentTcpBytesReceived = in.readLong();
@@ -2846,7 +2845,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
return !wlactive;
}
-
+
void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
mTimerPartial = readTimerFromParcel(WAKE_TYPE_PARTIAL,
mPartialTimers, unpluggables, in);
@@ -2876,7 +2875,7 @@ public final class BatteryStatsImpl extends BatteryStats {
public final class Sensor extends BatteryStats.Uid.Sensor {
final int mHandle;
StopwatchTimer mTimer;
-
+
public Sensor(int handle) {
mHandle = handle;
}
@@ -2902,7 +2901,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
return false;
}
-
+
void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
mTimer = readTimerFromParcel(unpluggables, in);
}
@@ -3024,7 +3023,7 @@ public final class BatteryStatsImpl extends BatteryStats {
public void plug(long batteryUptime, long batteryRealtime) {
}
-
+
void detach() {
mUnpluggables.remove(this);
for (int i = 0; i < mSpeedBins.length; i++) {
@@ -3035,7 +3034,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
}
-
+
public int countExcessivePowers() {
return mExcessivePower != null ? mExcessivePower.size() : 0;
}
@@ -3302,18 +3301,18 @@ public final class BatteryStatsImpl extends BatteryStats {
Pkg() {
mUnpluggables.add(this);
}
-
+
public void unplug(long batteryUptime, long batteryRealtime) {
mUnpluggedWakeups = mWakeups;
}
public void plug(long batteryUptime, long batteryRealtime) {
}
-
+
void detach() {
mUnpluggables.remove(this);
}
-
+
void readFromParcelLocked(Parcel in) {
mWakeups = in.readInt();
mLoadedWakeups = in.readInt();
@@ -3464,7 +3463,7 @@ public final class BatteryStatsImpl extends BatteryStats {
Serv() {
mUnpluggables.add(this);
}
-
+
public void unplug(long batteryUptime, long batteryRealtime) {
mUnpluggedStartTime = getStartTimeToNowLocked(batteryUptime);
mUnpluggedStarts = mStarts;
@@ -3473,11 +3472,11 @@ public final class BatteryStatsImpl extends BatteryStats {
public void plug(long batteryUptime, long batteryRealtime) {
}
-
+
void detach() {
mUnpluggables.remove(this);
}
-
+
void readFromParcelLocked(Parcel in) {
mStartTime = in.readLong();
mRunningSince = in.readLong();
@@ -3652,7 +3651,7 @@ public final class BatteryStatsImpl extends BatteryStats {
public SparseArray<? extends Pid> getPidStats() {
return mPids;
}
-
+
public Pid getPidStatsLocked(int pid) {
Pid p = mPids.get(pid);
if (p == null) {
@@ -3790,7 +3789,7 @@ public final class BatteryStatsImpl extends BatteryStats {
p.addExcessiveWake(overTime, usedTime);
}
}
-
+
public void reportExcessiveCpuLocked(String proc, long overTime, long usedTime) {
Proc p = getProcessStatsLocked(proc);
if (p != null) {
@@ -3802,7 +3801,7 @@ public final class BatteryStatsImpl extends BatteryStats {
StopwatchTimer t = getSensorTimerLocked(sensor, true);
if (t != null) {
t.startRunningLocked(BatteryStatsImpl.this);
- }
+ }
}
public void noteStopSensor(int sensor) {
@@ -3810,16 +3809,16 @@ public final class BatteryStatsImpl extends BatteryStats {
StopwatchTimer t = getSensorTimerLocked(sensor, false);
if (t != null) {
t.stopRunningLocked(BatteryStatsImpl.this);
- }
+ }
}
-
+
public void noteStartGps() {
StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, true);
if (t != null) {
t.startRunningLocked(BatteryStatsImpl.this);
- }
+ }
}
-
+
public void noteStopGps() {
StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false);
if (t != null) {
@@ -3909,12 +3908,12 @@ public final class BatteryStatsImpl extends BatteryStats {
public HistoryItem getHistory() {
return mHistory;
}
-
+
@Override
public long getHistoryBaseTime() {
return mHistoryBaseTime;
}
-
+
@Override
public int getStartCount() {
return mStartCount;
@@ -3936,7 +3935,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart);
mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart);
}
-
+
public void resetAllStatsLocked() {
mStartCount = 0;
initTimes();
@@ -3958,24 +3957,24 @@ public final class BatteryStatsImpl extends BatteryStats {
mWifiOnTimer.reset(this, false);
mGlobalWifiRunningTimer.reset(this, false);
mBluetoothOnTimer.reset(this, false);
-
+
for (int i=0; i<mUidStats.size(); i++) {
if (mUidStats.valueAt(i).reset()) {
mUidStats.remove(mUidStats.keyAt(i));
i--;
}
}
-
+
if (mKernelWakelockStats.size() > 0) {
for (SamplingTimer timer : mKernelWakelockStats.values()) {
mUnpluggables.remove(timer);
}
mKernelWakelockStats.clear();
}
-
+
clearHistoryLocked();
}
-
+
void setOnBattery(boolean onBattery, int oldStatus, int level) {
synchronized(this) {
boolean doWrite = false;
@@ -3983,7 +3982,7 @@ public final class BatteryStatsImpl extends BatteryStats {
m.arg1 = onBattery ? 1 : 0;
mHandler.sendMessage(m);
mOnBattery = mOnBatteryInternal = onBattery;
-
+
long uptime = SystemClock.uptimeMillis() * 1000;
long mSecRealtime = SystemClock.elapsedRealtime();
long realtime = mSecRealtime * 1000;
@@ -4036,10 +4035,10 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
}
-
+
// This should probably be exposed in the API, though it's not critical
private static final int BATTERY_PLUGGED_NONE = 0;
-
+
public void setBatteryState(int status, int health, int plugType, int level,
int temp, int volt) {
boolean onBattery = plugType == BATTERY_PLUGGED_NONE;
@@ -4107,10 +4106,10 @@ public final class BatteryStatsImpl extends BatteryStats {
mRecordingHistory = false;
}
}
-
+
public void updateKernelWakelocksLocked() {
Map<String, KernelWakelockStats> m = readKernelWakelockStats();
-
+
if (m == null) {
// Not crashing might make board bringup easier.
Slog.w(TAG, "Couldn't get kernel wake lock stats");
@@ -4120,10 +4119,10 @@ public final class BatteryStatsImpl extends BatteryStats {
for (Map.Entry<String, KernelWakelockStats> ent : m.entrySet()) {
String name = ent.getKey();
KernelWakelockStats kws = ent.getValue();
-
+
SamplingTimer kwlt = mKernelWakelockStats.get(name);
if (kwlt == null) {
- kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal,
+ kwlt = new SamplingTimer(mUnpluggables, mOnBatteryInternal,
true /* track reported values */);
mKernelWakelockStats.put(name, kwlt);
}
@@ -4131,7 +4130,7 @@ public final class BatteryStatsImpl extends BatteryStats {
kwlt.updateCurrentReportedTotalTime(kws.mTotalTime);
kwlt.setUpdateVersion(sKernelWakelockUpdateVersion);
}
-
+
if (m.size() != mKernelWakelockStats.size()) {
// Set timers to stale if they didn't appear in /proc/wakelocks this time.
for (Map.Entry<String, SamplingTimer> ent : mKernelWakelockStats.entrySet()) {
@@ -4276,18 +4275,18 @@ public final class BatteryStatsImpl extends BatteryStats {
return getDischargeStartLevelLocked();
}
}
-
+
public int getDischargeStartLevelLocked() {
return mDischargeUnplugLevel;
}
-
+
@Override
public int getDischargeCurrentLevel() {
synchronized(this) {
return getDischargeCurrentLevelLocked();
}
}
-
+
public int getDischargeCurrentLevelLocked() {
return mDischargeCurrentLevel;
}
@@ -4430,7 +4429,7 @@ public final class BatteryStatsImpl extends BatteryStats {
writeSyncLocked();
mShuttingDown = true;
}
-
+
Parcel mPendingWrite = null;
final ReentrantLock mWriteLock = new ReentrantLock();
@@ -4451,7 +4450,7 @@ public final class BatteryStatsImpl extends BatteryStats {
if (mShuttingDown) {
return;
}
-
+
Parcel out = Parcel.obtain();
writeSummaryToParcel(out);
mLastWriteTime = SystemClock.elapsedRealtime();
@@ -4551,7 +4550,7 @@ public final class BatteryStatsImpl extends BatteryStats {
} catch(java.io.IOException e) {
Slog.e("BatteryStats", "Error reading battery statistics", e);
}
-
+
addHistoryRecordLocked(SystemClock.elapsedRealtime(), HistoryItem.CMD_START);
}
@@ -4570,7 +4569,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mHistoryBaseTime = rec.time;
}
}
-
+
long oldnow = SystemClock.elapsedRealtime() - (5*60*100);
if (oldnow > 0) {
// If the system process has restarted, but not the entire
@@ -4582,7 +4581,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mHistoryBaseTime -= oldnow;
}
}
-
+
void writeHistory(Parcel out) {
HistoryItem rec = mHistory;
while (rec != null) {
@@ -4591,7 +4590,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
out.writeLong(-1);
}
-
+
private void readSummaryFromParcel(Parcel in) {
final int version = in.readInt();
if (version != VERSION) {
@@ -4601,7 +4600,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
readHistory(in);
-
+
mStartCount = in.readInt();
mBatteryUptime = in.readLong();
mBatteryRealtime = in.readLong();
@@ -4611,9 +4610,9 @@ public final class BatteryStatsImpl extends BatteryStats {
mDischargeCurrentLevel = in.readInt();
mLowDischargeAmountSinceCharge = in.readInt();
mHighDischargeAmountSinceCharge = in.readInt();
-
+
mStartCount++;
-
+
mScreenOn = false;
mScreenOnTimer.readSummaryFromParcelLocked(in);
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
@@ -4693,7 +4692,7 @@ public final class BatteryStatsImpl extends BatteryStats {
u.mUserActivityCounters[i].readSummaryFromParcelLocked(in);
}
}
-
+
int NW = in.readInt();
if (NW > 10000) {
Slog.w(TAG, "File corrupt: too many wake locks " + NW);
@@ -4786,7 +4785,7 @@ public final class BatteryStatsImpl extends BatteryStats {
out.writeInt(VERSION);
writeHistory(out);
-
+
out.writeInt(mStartCount);
out.writeLong(computeBatteryUptime(NOW_SYS, STATS_SINCE_CHARGED));
out.writeLong(computeBatteryRealtime(NOWREAL_SYS, STATS_SINCE_CHARGED));
@@ -4796,7 +4795,7 @@ public final class BatteryStatsImpl extends BatteryStats {
out.writeInt(mDischargeCurrentLevel);
out.writeInt(mLowDischargeAmountSinceCharge);
out.writeInt(mHighDischargeAmountSinceCharge);
-
+
mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL);
@@ -4825,14 +4824,14 @@ public final class BatteryStatsImpl extends BatteryStats {
out.writeInt(0);
}
}
-
+
out.writeInt(sNumSpeedSteps);
final int NU = mUidStats.size();
out.writeInt(NU);
for (int iu = 0; iu < NU; iu++) {
out.writeInt(mUidStats.keyAt(iu));
Uid u = mUidStats.valueAt(iu);
-
+
if (u.mWifiRunningTimer != null) {
out.writeInt(1);
u.mWifiRunningTimer.writeSummaryFromParcelLocked(out, NOWREAL);
@@ -4878,7 +4877,7 @@ public final class BatteryStatsImpl extends BatteryStats {
u.mUserActivityCounters[i].writeSummaryFromParcelLocked(out);
}
}
-
+
int NW = u.mWakelockStats.size();
out.writeInt(NW);
if (NW > 0) {
@@ -4970,7 +4969,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
}
-
+
out.writeLong(u.getTcpBytesReceived(STATS_SINCE_CHARGED));
out.writeLong(u.getTcpBytesSent(STATS_SINCE_CHARGED));
}
@@ -4979,7 +4978,7 @@ public final class BatteryStatsImpl extends BatteryStats {
public void readFromParcel(Parcel in) {
readFromParcelLocked(in);
}
-
+
void readFromParcelLocked(Parcel in) {
int magic = in.readInt();
if (magic != MAGIC) {
@@ -4987,7 +4986,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
readHistory(in);
-
+
mStartCount = in.readInt();
mBatteryUptime = in.readLong();
mBatteryLastUptime = 0;
@@ -5062,7 +5061,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mKernelWakelockStats.put(wakelockName, kwlt);
}
}
-
+
mPartialTimers.clear();
mFullTimers.clear();
mWindowTimers.clear();
@@ -5090,18 +5089,18 @@ public final class BatteryStatsImpl extends BatteryStats {
public void writeToParcelWithoutUids(Parcel out, int flags) {
writeToParcelLocked(out, false, flags);
}
-
- @SuppressWarnings("unused")
+
+ @SuppressWarnings("unused")
void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
final long uSecUptime = SystemClock.uptimeMillis() * 1000;
final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
final long batteryUptime = getBatteryUptimeLocked(uSecUptime);
final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime);
-
+
out.writeInt(MAGIC);
-
+
writeHistory(out);
-
+
out.writeInt(mStartCount);
out.writeLong(mBatteryUptime);
out.writeLong(mBatteryRealtime);
@@ -5190,7 +5189,7 @@ public final class BatteryStatsImpl extends BatteryStats {
return new BatteryStatsImpl[size];
}
};
-
+
public void dumpLocked(PrintWriter pw) {
if (DEBUG) {
Printer pr = new PrintWriterPrinter(pw);
diff --git a/core/java/com/android/internal/view/StandaloneActionMode.java b/core/java/com/android/internal/view/StandaloneActionMode.java
index d381901..b54daba 100644
--- a/core/java/com/android/internal/view/StandaloneActionMode.java
+++ b/core/java/com/android/internal/view/StandaloneActionMode.java
@@ -87,7 +87,6 @@ public class StandaloneActionMode extends ActionMode implements MenuBuilder.Call
mFinished = true;
mCallback.onDestroyActionMode(this);
- mContextView.setVisibility(View.GONE);
}
@Override
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index 5d66372..38f76d3 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -213,7 +213,7 @@ public class ActionBarContextView extends ViewGroup {
}
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- if (heightMode != MeasureSpec.AT_MOST) {
+ if (heightMode == MeasureSpec.UNSPECIFIED) {
throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
"with android:layout_height=\"wrap_content\"");
}
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index f8a80b0..8956e39 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -256,20 +256,20 @@ static void Bitmap_destructor(JNIEnv* env, jobject, SkBitmap* bitmap) {
#ifdef USE_OPENGL_RENDERER
if (android::uirenderer::Caches::hasInstance()) {
android::uirenderer::Caches::getInstance().resourceCache.destructor(bitmap);
+ return;
}
-#else // !USE_OPENGL_RENDERER
+#endif // USE_OPENGL_RENDERER
delete bitmap;
-#endif
}
static void Bitmap_recycle(JNIEnv* env, jobject, SkBitmap* bitmap) {
#ifdef USE_OPENGL_RENDERER
if (android::uirenderer::Caches::hasInstance()) {
android::uirenderer::Caches::getInstance().resourceCache.recycle(bitmap);
+ return;
}
-#else // !USE_OPENGL_RENDERER
- bitmap->setPixels(NULL, NULL);
#endif // USE_OPENGL_RENDERER
+ bitmap->setPixels(NULL, NULL);
}
// These must match the int values in Bitmap.java
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index f700791..bf18d55 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -65,6 +65,7 @@ static SkMemoryStream* buildSkMemoryStream(SkStream *stream) {
}
}
data = (char*)sk_realloc_throw(data, streamLen);
+
SkMemoryStream* streamMem = new SkMemoryStream();
streamMem->setMemoryOwned(data, streamLen);
return streamMem;
@@ -133,6 +134,12 @@ static jobject nativeNewInstanceFromFileDescriptor(JNIEnv* env, jobject clazz,
}
stream = fdStream;
} else {
+ /* Restore our offset when we leave, so we can be called more than once
+ with the same descriptor. This is only required if we didn't dup the
+ file descriptor, but it is OK to do it all the time.
+ */
+ AutoFDSeek as(descriptor);
+
SkFDStream* fdStream = new SkFDStream(descriptor, false);
if (!fdStream->isValid()) {
fdStream->unref();
@@ -142,12 +149,6 @@ static jobject nativeNewInstanceFromFileDescriptor(JNIEnv* env, jobject clazz,
fdStream->unref();
}
- /* Restore our offset when we leave, so we can be called more than once
- with the same descriptor. This is only required if we didn't dup the
- file descriptor, but it is OK to do it all the time.
- */
- AutoFDSeek as(descriptor);
-
return doBuildTileIndex(env, stream);
}
diff --git a/core/jni/android/graphics/Matrix.cpp b/core/jni/android/graphics/Matrix.cpp
index 6667756..b305506 100644
--- a/core/jni/android/graphics/Matrix.cpp
+++ b/core/jni/android/graphics/Matrix.cpp
@@ -35,10 +35,10 @@ public:
#ifdef USE_OPENGL_RENDERER
if (android::uirenderer::Caches::hasInstance()) {
android::uirenderer::Caches::getInstance().resourceCache.destructor(obj);
+ return;
}
-#else // !USE_OPENGL_RENDERER
+#endif // USE_OPENGL_RENDERER
delete obj;
-#endif
}
static SkMatrix* create(JNIEnv* env, jobject clazz, const SkMatrix* src) {
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 339c1a4..79a02f1 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -66,10 +66,10 @@ public:
#ifdef USE_OPENGL_RENDERER
if (android::uirenderer::Caches::hasInstance()) {
android::uirenderer::Caches::getInstance().resourceCache.destructor(obj);
+ return;
}
-#else // !USE_OPENGL_RENDERER
+#endif // USE_OPENGL_RENDERER
delete obj;
-#endif
}
static SkPaint* init(JNIEnv* env, jobject clazz) {
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 63d3578..45fd5a0 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -626,7 +626,8 @@ static int mainWorkCallback(int fd, int events, void* data) {
// ------------------------------------------------------------------------
static jint
-loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jobject messageQueue,
+loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,
+ jobject messageQueue,
jstring internalDataDir, jstring externalDataDir, int sdkVersion,
jobject jAssetMgr, jbyteArray savedState)
{
@@ -640,8 +641,11 @@ loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jobject messageQ
env->ReleaseStringUTFChars(path, pathStr);
if (handle != NULL) {
+ const char* funcStr = env->GetStringUTFChars(funcName, NULL);
code = new NativeCode(handle, (ANativeActivity_createFunc*)
- dlsym(handle, "ANativeActivity_onCreate"));
+ dlsym(handle, funcStr));
+ env->ReleaseStringUTFChars(funcName, funcStr);
+
if (code->createActivityFunc == NULL) {
LOGW("ANativeActivity_onCreate not found");
delete code;
@@ -999,7 +1003,7 @@ finishPreDispatchKeyEvent_native(JNIEnv* env, jobject clazz, jint handle,
}
static const JNINativeMethod g_methods[] = {
- { "loadNativeCode", "(Ljava/lang/String;Landroid/os/MessageQueue;Ljava/lang/String;Ljava/lang/String;ILandroid/content/res/AssetManager;[B)I",
+ { "loadNativeCode", "(Ljava/lang/String;Ljava/lang/String;Landroid/os/MessageQueue;Ljava/lang/String;Ljava/lang/String;ILandroid/content/res/AssetManager;[B)I",
(void*)loadNativeCode_native },
{ "unloadNativeCode", "(I)V", (void*)unloadNativeCode_native },
{ "onStartNative", "(I)V", (void*)onStart_native },
diff --git a/core/jni/android_nfc_NdefMessage.cpp b/core/jni/android_nfc_NdefMessage.cpp
index 99295f4..eaf989d 100644
--- a/core/jni/android_nfc_NdefMessage.cpp
+++ b/core/jni/android_nfc_NdefMessage.cpp
@@ -16,6 +16,8 @@
#define LOG_TAG "NdefMessage"
+#include <stdlib.h>
+
#include "jni.h"
#include "JNIHelp.h"
diff --git a/core/jni/android_nfc_NdefRecord.cpp b/core/jni/android_nfc_NdefRecord.cpp
index 9d20d6d..0a3a519 100644
--- a/core/jni/android_nfc_NdefRecord.cpp
+++ b/core/jni/android_nfc_NdefRecord.cpp
@@ -16,6 +16,8 @@
#define LOG_TAG "NdefRecord"
+#include <stdlib.h>
+
#include "jni.h"
#include "JNIHelp.h"
diff --git a/core/res/res/color/primary_text_holo_dark.xml b/core/res/res/color/primary_text_holo_dark.xml
index 69ee309..6418664 100644
--- a/core/res/res/color/primary_text_holo_dark.xml
+++ b/core/res/res/color/primary_text_holo_dark.xml
@@ -15,10 +15,10 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_enabled="false" android:color="@android:color/bright_foreground_dark_disabled"/>
- <item android:state_window_focused="false" android:color="@android:color/bright_foreground_dark"/>
- <item android:state_pressed="true" android:color="@android:color/bright_foreground_dark"/>
- <item android:state_selected="true" android:color="@android:color/bright_foreground_dark"/>
- <item android:state_activated="true" android:color="@android:color/bright_foreground_dark"/>
- <item android:color="@android:color/bright_foreground_dark"/> <!-- not selected -->
+ <item android:state_enabled="false" android:color="@android:color/bright_foreground_disabled_holo_dark"/>
+ <item android:state_window_focused="false" android:color="@android:color/bright_foreground_holo_dark"/>
+ <item android:state_pressed="true" android:color="@android:color/bright_foreground_holo_dark"/>
+ <item android:state_selected="true" android:color="@android:color/bright_foreground_holo_dark"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_holo_dark"/>
+ <item android:color="@android:color/bright_foreground_holo_dark"/> <!-- not selected -->
</selector>
diff --git a/core/res/res/color/primary_text_holo_light.xml b/core/res/res/color/primary_text_holo_light.xml
index a8d31ce..86f8f86 100644
--- a/core/res/res/color/primary_text_holo_light.xml
+++ b/core/res/res/color/primary_text_holo_light.xml
@@ -15,12 +15,12 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_enabled="false" android:color="@android:color/bright_foreground_light_disabled"/>
- <item android:state_window_focused="false" android:color="@android:color/bright_foreground_light"/>
- <item android:state_pressed="true" android:color="@android:color/bright_foreground_light"/>
- <item android:state_selected="true" android:color="@android:color/bright_foreground_light"/>
- <item android:state_activated="true" android:color="@android:color/bright_foreground_light"/>
- <item android:color="@android:color/bright_foreground_light"/> <!-- not selected -->
+ <item android:state_enabled="false" android:color="@android:color/bright_foreground_disabled_holo_light"/>
+ <item android:state_window_focused="false" android:color="@android:color/bright_foreground_holo_light"/>
+ <item android:state_pressed="true" android:color="@android:color/bright_foreground_holo_light"/>
+ <item android:state_selected="true" android:color="@android:color/bright_foreground_holo_light"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_holo_light"/>
+ <item android:color="@android:color/bright_foreground_holo_light"/> <!-- not selected -->
</selector>
diff --git a/core/res/res/color/secondary_text_holo_dark.xml b/core/res/res/color/secondary_text_holo_dark.xml
index 376156e..881a1de 100644
--- a/core/res/res/color/secondary_text_holo_dark.xml
+++ b/core/res/res/color/secondary_text_holo_dark.xml
@@ -15,13 +15,13 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_window_focused="false" android:state_enabled="false" android:color="@android:color/dim_foreground_dark_disabled"/>
- <item android:state_window_focused="false" android:color="@android:color/dim_foreground_dark"/>
- <item android:state_selected="true" android:state_enabled="false" android:color="@android:color/dim_foreground_dark_inverse_disabled"/>
- <item android:state_pressed="true" android:state_enabled="false" android:color="@android:color/dim_foreground_dark_inverse_disabled"/>
- <item android:state_selected="true" android:color="@android:color/dim_foreground_dark_inverse"/>
- <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse"/>
- <item android:state_pressed="true" android:color="@android:color/dim_foreground_dark_inverse"/>
- <item android:state_enabled="false" android:color="@android:color/dim_foreground_dark_disabled"/>
- <item android:color="@android:color/dim_foreground_dark"/> <!-- not selected -->
+ <item android:state_window_focused="false" android:state_enabled="false" android:color="@android:color/dim_foreground_disabled_holo_dark"/>
+ <item android:state_window_focused="false" android:color="@android:color/dim_foreground_holo_dark"/>
+ <item android:state_selected="true" android:state_enabled="false" android:color="@android:color/dim_foreground_inverse_disabled_holo_dark"/>
+ <item android:state_pressed="true" android:state_enabled="false" android:color="@android:color/dim_foreground_inverse_disabled_holo_dark"/>
+ <item android:state_selected="true" android:color="@android:color/dim_foreground_inverse_holo_dark"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_inverse_holo_dark"/>
+ <item android:state_pressed="true" android:color="@android:color/dim_foreground_inverse_holo_dark"/>
+ <item android:state_enabled="false" android:color="@android:color/dim_foreground_disabled_holo_dark"/>
+ <item android:color="@android:color/dim_foreground_holo_dark"/> <!-- not selected -->
</selector>
diff --git a/core/res/res/color/secondary_text_holo_light.xml b/core/res/res/color/secondary_text_holo_light.xml
index b791aeb..05721b2 100644
--- a/core/res/res/color/secondary_text_holo_light.xml
+++ b/core/res/res/color/secondary_text_holo_light.xml
@@ -15,14 +15,14 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_window_focused="false" android:state_enabled="false" android:color="@android:color/dim_foreground_light_disabled"/>
- <item android:state_window_focused="false" android:color="@android:color/dim_foreground_light"/>
+ <item android:state_window_focused="false" android:state_enabled="false" android:color="@android:color/dim_foreground_disabled_holo_light"/>
+ <item android:state_window_focused="false" android:color="@android:color/dim_foreground_holo_light"/>
<!-- Since there is only one selector (for both light and dark), the light's selected state shouldn't be inversed like the dark's. -->
- <item android:state_pressed="true" android:state_enabled="false" android:color="@android:color/dim_foreground_light_disabled"/>
- <item android:state_selected="true" android:state_enabled="false" android:color="@android:color/dim_foreground_light_disabled"/>
- <item android:state_pressed="true" android:color="@android:color/dim_foreground_light"/>
- <item android:state_selected="true" android:color="@android:color/dim_foreground_light"/>
- <item android:state_activated="true" android:color="@android:color/bright_foreground_light"/>
- <item android:state_enabled="false" android:color="@android:color/dim_foreground_light_disabled"/>
- <item android:color="@android:color/dim_foreground_light"/> <!-- not selected -->
+ <item android:state_pressed="true" android:state_enabled="false" android:color="@android:color/dim_foreground_disabled_holo_light"/>
+ <item android:state_selected="true" android:state_enabled="false" android:color="@android:color/dim_foreground_disabled_holo_light"/>
+ <item android:state_pressed="true" android:color="@android:color/dim_foreground_holo_light"/>
+ <item android:state_selected="true" android:color="@android:color/dim_foreground_holo_light"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_holo_light"/>
+ <item android:state_enabled="false" android:color="@android:color/dim_foreground_disabled_holo_light"/>
+ <item android:color="@android:color/dim_foreground_holo_light"/> <!-- not selected -->
</selector>
diff --git a/core/res/res/color/tertiary_text_holo_dark.xml b/core/res/res/color/tertiary_text_holo_dark.xml
index 269ff71..0718d7d 100644
--- a/core/res/res/color/tertiary_text_holo_dark.xml
+++ b/core/res/res/color/tertiary_text_holo_dark.xml
@@ -18,7 +18,7 @@
<item android:state_enabled="false" android:color="#808080"/>
<item android:state_window_focused="false" android:color="#808080"/>
<item android:state_pressed="true" android:color="#808080"/>
- <item android:state_selected="true" android:color="@android:color/dim_foreground_light"/>
+ <item android:state_selected="true" android:color="@android:color/dim_foreground_holo_light"/>
<item android:color="#808080"/> <!-- not selected -->
</selector>
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
index 05d1668..19ad5c9 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
index 6f7eb42..180cdf5 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
index 2c814f0..c66bb07 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
index a88bdf6..c0d3dd7 100644
--- a/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
index 9a61d82..b440e15 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
index 56ca528..8769d0a 100644
--- a/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
index 6600035..7b8e9e8 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
index 11d31bb..37c8028 100644
--- a/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
index 8c58c37..aa08f45 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
index d543c66..3e99cb6 100644
--- a/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_activated_holo.9.png b/core/res/res/drawable-hdpi/list_activated_holo.9.png
new file mode 100644
index 0000000..cd9a08e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_activated_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_divider_holo_dark.9.png b/core/res/res/drawable-hdpi/list_divider_holo_dark.9.png
new file mode 100644
index 0000000..7b18202
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_divider_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_divider_holo_light.9.png b/core/res/res/drawable-hdpi/list_divider_holo_light.9.png
new file mode 100644
index 0000000..17bcbb4
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_divider_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_focused_holo.9.png b/core/res/res/drawable-hdpi/list_focused_holo.9.png
new file mode 100644
index 0000000..b91e9f2
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_longpressed_holo.9.png b/core/res/res/drawable-hdpi/list_longpressed_holo.9.png
new file mode 100644
index 0000000..db4831d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_longpressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/list_pressed_holo_dark.9.png
new file mode 100644
index 0000000..1ce1601
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/list_pressed_holo_light.9.png
new file mode 100644
index 0000000..b36aa2c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_section_divider_holo_dark.9.png b/core/res/res/drawable-hdpi/list_section_divider_holo_dark.9.png
new file mode 100644
index 0000000..2dabb5f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_section_divider_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_section_divider_holo_light.9.png b/core/res/res/drawable-hdpi/list_section_divider_holo_light.9.png
new file mode 100644
index 0000000..763f4f6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_section_divider_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selected_holo_dark.9.png b/core/res/res/drawable-hdpi/list_selected_holo_dark.9.png
new file mode 100644
index 0000000..c054e14
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/list_selected_holo_light.9.png b/core/res/res/drawable-hdpi/list_selected_holo_light.9.png
new file mode 100644
index 0000000..77c4032
--- /dev/null
+++ b/core/res/res/drawable-hdpi/list_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
index 15003be..ca2271a 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
index 573f197..0d498e3 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
index 953a553..ae922ce 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
index d79a61e..89aef31 100644
--- a/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
index 897676e..1f4be44 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
index b485925..e4d0ba0 100644
--- a/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
index 1cdbf66..050fb19 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
index ab7eb54..75651fc 100644
--- a/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
index d95ef6d..c7d02cf 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
index 60ed4fc..40c9f64 100644
--- a/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_activated_holo.9.png b/core/res/res/drawable-mdpi/list_activated_holo.9.png
new file mode 100644
index 0000000..01ec674
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_activated_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_divider_holo_dark.9.png b/core/res/res/drawable-mdpi/list_divider_holo_dark.9.png
new file mode 100644
index 0000000..7b18202
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_divider_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_divider_holo_light.9.png b/core/res/res/drawable-mdpi/list_divider_holo_light.9.png
new file mode 100644
index 0000000..17bcbb4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_divider_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_focused_holo.9.png b/core/res/res/drawable-mdpi/list_focused_holo.9.png
new file mode 100644
index 0000000..23385df
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_focused_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_longpressed_holo.9.png b/core/res/res/drawable-mdpi/list_longpressed_holo.9.png
new file mode 100644
index 0000000..3312a51
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_longpressed_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/list_pressed_holo_dark.9.png
new file mode 100644
index 0000000..bbb14d8
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/list_pressed_holo_light.9.png
new file mode 100644
index 0000000..72380d4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_section_divider_holo_dark.9.png b/core/res/res/drawable-mdpi/list_section_divider_holo_dark.9.png
new file mode 100644
index 0000000..953d7bf
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_section_divider_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_section_divider_holo_light.9.png b/core/res/res/drawable-mdpi/list_section_divider_holo_light.9.png
new file mode 100644
index 0000000..e5fe664
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_section_divider_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selected_holo_dark.9.png b/core/res/res/drawable-mdpi/list_selected_holo_dark.9.png
new file mode 100644
index 0000000..c453506
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/list_selected_holo_light.9.png b/core/res/res/drawable-mdpi/list_selected_holo_light.9.png
new file mode 100644
index 0000000..58b6b3c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/list_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable/activated_background_holo_dark.xml b/core/res/res/drawable/activated_background_holo_dark.xml
index f71235e..febf2c4 100644
--- a/core/res/res/drawable/activated_background_holo_dark.xml
+++ b/core/res/res/drawable/activated_background_holo_dark.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_activated="true" android:drawable="@android:drawable/list_selector_activated_holo_dark" />
+ <item android:state_activated="true" android:drawable="@android:drawable/list_activated_holo" />
<item android:drawable="@color/transparent" />
</selector>
diff --git a/core/res/res/drawable/activated_background_holo_light.xml b/core/res/res/drawable/activated_background_holo_light.xml
index 615033d..febf2c4 100644
--- a/core/res/res/drawable/activated_background_holo_light.xml
+++ b/core/res/res/drawable/activated_background_holo_light.xml
@@ -15,6 +15,6 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_activated="true" android:drawable="@android:drawable/list_selector_activated_holo_light" />
+ <item android:state_activated="true" android:drawable="@android:drawable/list_activated_holo" />
<item android:drawable="@color/transparent" />
</selector>
diff --git a/core/res/res/drawable/btn_default_holo_light.xml b/core/res/res/drawable/btn_default_holo_light.xml
new file mode 100644
index 0000000..61bb1bd
--- /dev/null
+++ b/core/res/res/drawable/btn_default_holo_light.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_window_focused="false" android:state_enabled="true"
+ android:drawable="@drawable/btn_default_normal_holo_light" />
+ <item android:state_window_focused="false" android:state_enabled="false"
+ android:drawable="@drawable/btn_default_disabled_holo_light" />
+ <item android:state_pressed="true"
+ android:drawable="@drawable/btn_default_pressed_holo_light" />
+ <item android:state_focused="true" android:state_enabled="true"
+ android:drawable="@drawable/btn_default_focused_holo_light" />
+ <item android:state_enabled="true"
+ android:drawable="@drawable/btn_default_normal_holo_light" />
+ <item android:state_focused="true"
+ android:drawable="@drawable/btn_default_disabled_focused_holo_light" />
+ <item
+ android:drawable="@drawable/btn_default_disabled_holo_light" />
+</selector>
diff --git a/core/res/res/drawable/list_selector_background_transition_holo_dark.xml b/core/res/res/drawable/list_selector_background_transition_holo_dark.xml
new file mode 100644
index 0000000..7c68426
--- /dev/null
+++ b/core/res/res/drawable/list_selector_background_transition_holo_dark.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<transition xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@android:drawable/list_pressed_holo_dark" />
+ <item android:drawable="@android:drawable/list_longpressed_holo" />
+</transition>
diff --git a/core/res/res/drawable/list_selector_background_transition_holo_light.xml b/core/res/res/drawable/list_selector_background_transition_holo_light.xml
new file mode 100644
index 0000000..fc08a84
--- /dev/null
+++ b/core/res/res/drawable/list_selector_background_transition_holo_light.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<transition xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:drawable="@android:drawable/list_pressed_holo_light" />
+ <item android:drawable="@android:drawable/list_longpressed_holo" />
+</transition>
diff --git a/core/res/res/drawable/list_selector_holo_dark.xml b/core/res/res/drawable/list_selector_holo_dark.xml
index 9cc993a..e4c5c52 100644
--- a/core/res/res/drawable/list_selector_holo_dark.xml
+++ b/core/res/res/drawable/list_selector_holo_dark.xml
@@ -21,7 +21,7 @@
<!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
<item android:state_focused="true" android:state_enabled="false" android:state_pressed="true" android:drawable="@drawable/list_selector_disabled_holo_dark" />
<item android:state_focused="true" android:state_enabled="false" android:drawable="@drawable/list_selector_disabled_holo_dark" />
- <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/list_selector_background_transition" />
- <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/list_selector_background_transition" />
- <item android:state_focused="true" android:drawable="@drawable/list_selector_focused_holo_dark" />
+ <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/list_selector_background_transition_holo_dark" />
+ <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/list_selector_background_transition_holo_dark" />
+ <item android:state_focused="true" android:drawable="@drawable/list_focused_holo" />
</selector>
diff --git a/core/res/res/drawable/list_selector_holo_light.xml b/core/res/res/drawable/list_selector_holo_light.xml
index f2def40..17631bd 100644
--- a/core/res/res/drawable/list_selector_holo_light.xml
+++ b/core/res/res/drawable/list_selector_holo_light.xml
@@ -21,8 +21,8 @@
<!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
<item android:state_focused="true" android:state_enabled="false" android:state_pressed="true" android:drawable="@drawable/list_selector_disabled_holo_light" />
<item android:state_focused="true" android:state_enabled="false" android:drawable="@drawable/list_selector_disabled_holo_light" />
- <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/list_selector_background_transition" />
- <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/list_selector_background_transition" />
- <item android:state_focused="true" android:drawable="@drawable/list_selector_focused_holo_light" />
+ <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/list_selector_background_transition_holo_light" />
+ <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/list_selector_background_transition_holo_light" />
+ <item android:state_focused="true" android:drawable="@drawable/list_focused_holo" />
</selector>
diff --git a/core/res/res/values-zh-rCN/donottranslate-cldr.xml b/core/res/res/values-zh-rCN/donottranslate-cldr.xml
index bbf7df5..ec9d8c0 100644
--- a/core/res/res/values-zh-rCN/donottranslate-cldr.xml
+++ b/core/res/res/values-zh-rCN/donottranslate-cldr.xml
@@ -144,6 +144,6 @@
<string name="same_month_mdy1_mdy2">%9$s 年 %2$s %3$s - %8$s 日</string>
<string name="same_year_wday1_mdy1_wday2_mdy2">%9$s 年 %2$s %3$s 日%1$s - %7$s %8$s 日%6$s</string>
<string name="short_format_month">%b</string>
- <string name="full_wday_month_day_no_year">M 月 d 日E</string>
- <string name="abbrev_wday_month_day_year">yyyy 年 M 月 d 日EEE</string>
+ <string name="full_wday_month_day_no_year">M 月 d 日 E</string>
+ <string name="abbrev_wday_month_day_year">yyyy 年 M 月 d 日 EEE</string>
</resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 949d960..065c10d 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1441,6 +1441,38 @@
<attr name="functionalTest" />
</declare-styleable>
+ <!-- Attributes that can be supplied in an AndroidManifest.xml
+ <code>screen</code> tag, a child of <code>compatible-screens</code>,
+ which is itseld a child of the root
+ {@link #AndroidManifest manifest} tag. -->
+ <declare-styleable name="AndroidManifestCompatibleScreensScreen">
+ <!-- Specifies a compatible screen size, as per the device
+ configuration screen size bins. -->
+ <attr name="screenSize">
+ <!-- A small screen configuration, at least 240x320db. -->
+ <enum name="small" value="200" />
+ <!-- A normal screen configuration, at least 320x480db. -->
+ <enum name="normal" value="300" />
+ <!-- A large screen configuration, at least 400x530db. -->
+ <enum name="large" value="400" />
+ <!-- An extra large screen configuration, at least 600x800db. -->
+ <enum name="xlarge" value="500" />
+ </attr>
+ <!-- Specifies a compatible screen density, as per the device
+ configuration screen density bins. -->
+ <attr name="screenDensity" format="integer">
+ <!-- A low density screen, approximately 120dpi. -->
+ <enum name="ldpi" value="120" />
+ <!-- A medium density screen, approximately 160dpi. -->
+ <enum name="mdpi" value="160" />
+ <!-- A high density screen, approximately 240dpi. -->
+ <enum name="hdpi" value="240" />
+ <!-- An extra high density screen, approximately 320dpi. -->
+ <enum name="xhdpi" value="320" />
+ </attr>
+ </declare-styleable>
+
+
<!-- Declaration of an {@link android.content.Intent} object in XML. May
also include zero or more {@link #IntentCategory <category> and
{@link #Extra <extra>} tags. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 5add8d6..47bb5f8 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1257,6 +1257,8 @@
<public type="attr" name="textSelectHandle" id="0x010102c7" />
<public type="attr" name="textSelectHandleWindowStyle" id="0x010102c8" />
<public type="attr" name="popupAnimationStyle" id="0x010102c9" />
+ <public type="attr" name="screenSize" id="0x010102ca" />
+ <public type="attr" name="screenDensity" id="0x010102cb" />
<!-- presence drawables for videochat or audiochat capable contacts -->
<public type="drawable" name="presence_video_away" id="0x010800ac" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 5e77ee1..6f6f1db 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1289,7 +1289,7 @@
</style>
<style name="Widget.Holo.TextView.ListSeparator" parent="Widget.TextView.ListSeparator">
- <item name="android:background">@android:drawable/list_section_header_holo_dark</item>
+ <item name="android:background">@android:drawable/list_section_divider_holo_dark</item>
</style>
<style name="Widget.Holo.TextSelectHandle" parent="Widget.TextSelectHandle">
@@ -1332,6 +1332,8 @@
</style>
<style name="Widget.Holo.ListView" parent="Widget.ListView">
+ <item name="android:divider">?android:attr/listDivider</item>
+ <item name="android:listSelector">?android:attr/listChoiceBackgroundIndicator</item>
</style>
<style name="Widget.Holo.ListView.White">
@@ -1521,6 +1523,12 @@
</style>
<style name="Widget.Holo.Light.Button" parent="Widget.Button">
+ <item name="android:background">@android:drawable/btn_default_holo_light</item>
+ <item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
+ <item name="android:textColor">@android:color/primary_text_holo_light</item>
+ <item name="android:minHeight">48dip</item>
+ <item name="android:paddingLeft">32dip</item>
+ <item name="android:paddingRight">32dip</item>
</style>
<style name="Widget.Holo.Light.Button.Small">
@@ -1556,7 +1564,7 @@
</style>
<style name="Widget.Holo.Light.TextView.ListSeparator" parent="Widget.TextView.ListSeparator">
- <item name="android:background">@android:drawable/list_section_header_holo_light</item>
+ <item name="android:background">@android:drawable/list_section_divider_holo_light</item>
</style>
<style name="Widget.Holo.Light.TextSelectHandle" parent="Widget.TextSelectHandle">
@@ -1598,7 +1606,7 @@
<style name="Widget.Holo.Light.ImageWell" parent="Widget.ImageWell">
</style>
- <style name="Widget.Holo.Light.ListView" parent="Widget.ListView">
+ <style name="Widget.Holo.Light.ListView" parent="Widget.Holo.ListView">
</style>
<style name="Widget.Holo.Light.ListView.White">
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index b226aa0..7f6da2a 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -703,7 +703,7 @@
<item name="listPreferredItemHeight">64dip</item>
<!-- @hide -->
<item name="searchResultListItemHeight">58dip</item>
- <item name="listDivider">@drawable/divider_horizontal_holo_dark</item>
+ <item name="listDivider">@drawable/list_divider_holo_dark</item>
<item name="listSeparatorTextViewStyle">@android:style/Widget.Holo.TextView.ListSeparator</item>
<item name="listChoiceIndicatorSingle">@android:drawable/btn_radio_holo_dark</item>
@@ -713,7 +713,7 @@
<item name="activatedBackgroundIndicator">@android:drawable/activated_background_holo_dark</item>
- <item name="listDividerAlertDialog">@android:drawable/divider_horizontal_holo_dark</item>
+ <item name="listDividerAlertDialog">@android:drawable/list_divider_holo_dark</item>
<item name="expandableListPreferredItemPaddingLeft">40dip</item>
<item name="expandableListPreferredChildPaddingLeft">
@@ -936,7 +936,7 @@
<item name="listPreferredItemHeight">64dip</item>
<!-- @hide -->
<item name="searchResultListItemHeight">58dip</item>
- <item name="listDivider">@drawable/divider_horizontal_holo_light</item>
+ <item name="listDivider">@drawable/list_divider_holo_light</item>
<item name="listSeparatorTextViewStyle">@android:style/Widget.Holo.Light.TextView.ListSeparator</item>
<item name="listChoiceIndicatorSingle">@android:drawable/btn_radio_holo_light</item>
@@ -957,7 +957,7 @@
<item name="expandableListPreferredChildIndicatorRight">
?android:attr/expandableListPreferredItemIndicatorRight</item>
- <item name="listDividerAlertDialog">@android:drawable/divider_horizontal_holo_light</item>
+ <item name="listDividerAlertDialog">@android:drawable/list_divider_holo_light</item>
<!-- Gallery attributes -->
<item name="galleryItemBackground">@android:drawable/gallery_item_background</item>
@@ -1143,6 +1143,7 @@
<item name="android:windowAnimationStyle">@android:style/Animation.Holo.Dialog</item>
<item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
<item name="android:windowActionBar">false</item>
+ <item name="android:windowActionModeOverlay">true</item>
<item name="android:colorBackgroundCacheHint">@null</item>
diff --git a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
index 82de509..cddf63d 100644
--- a/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/coretests/src/android/bluetooth/BluetoothTestUtils.java
@@ -35,7 +35,7 @@ public class BluetoothTestUtils extends Assert {
/**
* Timeout for {@link BluetoothAdapter#disable()} in ms.
*/
- private static final int DISABLE_TIMEOUT = 5000;
+ private static final int DISABLE_TIMEOUT = 20000;
/**
* Timeout for {@link BluetoothAdapter#enable()} in ms.
diff --git a/data/sounds/AllAudio.mk b/data/sounds/AllAudio.mk
new file mode 100644
index 0000000..4e7a403
--- /dev/null
+++ b/data/sounds/AllAudio.mk
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+$(call inherit-product, frameworks/base/data/sounds/OriginalAudio.mk)
+$(call inherit-product, frameworks/base/data/sounds/AudioPackage2.mk)
+$(call inherit-product, frameworks/base/data/sounds/AudioPackage3.mk)
+$(call inherit-product, frameworks/base/data/sounds/AudioPackage4.mk)
diff --git a/include/camera/Camera.h b/include/camera/Camera.h
index 171a3b6..8d8edd6 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -81,6 +81,18 @@ enum {
enum {
CAMERA_CMD_START_SMOOTH_ZOOM = 1,
CAMERA_CMD_STOP_SMOOTH_ZOOM = 2,
+ // Set the clockwise rotation of preview display (setPreviewDisplay) in
+ // degrees. This affects the preview frames and the picture displayed after
+ // snapshot. This method is useful for portrait mode applications. Note that
+ // preview display of front-facing cameras is flipped horizontally before
+ // the rotation, that is, the image is reflected along the central vertical
+ // axis of the camera sensor. So the users can see themselves as looking
+ // into a mirror.
+ //
+ // This does not affect the order of byte array of CAMERA_MSG_PREVIEW_FRAME,
+ // CAMERA_MSG_VIDEO_FRAME, CAMERA_MSG_POSTVIEW_FRAME, CAMERA_MSG_RAW_IMAGE,
+ // or CAMERA_MSG_COMPRESSED_IMAGE. This is not allowed to be set during
+ // preview.
CAMERA_CMD_SET_DISPLAY_ORIENTATION = 3,
// cmdType to disable/enable shutter sound.
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index 1f8ce71..fa775e7 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -79,6 +79,9 @@ public:
node_id node, OMX_INDEXTYPE index,
const void *params, size_t size) = 0;
+ virtual status_t storeMetaDataInBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable) = 0;
+
virtual status_t enableGraphicBuffers(
node_id node, OMX_U32 port_index, OMX_BOOL enable) = 0;
diff --git a/include/media/stagefright/HardwareAPI.h b/include/media/stagefright/HardwareAPI.h
index 4ded5e8..b009e1b 100644
--- a/include/media/stagefright/HardwareAPI.h
+++ b/include/media/stagefright/HardwareAPI.h
@@ -49,6 +49,32 @@ struct EnableAndroidNativeBuffersParams {
OMX_BOOL enable;
};
+// A pointer to this struct is passed to OMX_SetParameter() when the extension
+// index "OMX.google.android.index.storeMetaDataInBuffers"
+// is given.
+//
+// When meta data is stored in the video buffers passed between OMX clients
+// and OMX components, interpretation of the buffer data is up to the
+// buffer receiver, and the data may or may not be the actual video data, but
+// some information helpful for the receiver to locate the actual data.
+// The buffer receiver thus needs to know how to interpret what is stored
+// in these buffers, with mechanisms pre-determined externally. How to
+// interpret the meta data is outside of the scope of this method.
+//
+// Currently, this is specifically used to pass meta data from video source
+// (camera component, for instance) to video encoder to avoid memcpying of
+// input video frame data. To do this, bStoreMetaDta is set to OMX_TRUE.
+// If bStoreMetaData is set to false, real YUV frame data will be stored
+// in the buffers. In addition, if no OMX_SetParameter() call is made
+// with the corresponding extension index, real YUV data is stored
+// in the buffers.
+struct StoreMetaDataInBuffersParams {
+ OMX_U32 nSize;
+ OMX_VERSIONTYPE nVersion;
+ OMX_U32 nPortIndex;
+ OMX_BOOL bStoreMetaData;
+};
+
// Color formats in the range [OMX_COLOR_FormatAndroidPrivateStart,
// OMX_COLOR_FormatAndroidPrivateEnd) will be converted to a gralloc pixel
// format when used to allocate Android native buffers via gralloc. The
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
index 2d4bf8b..f3a2dd2 100644
--- a/include/ui/InputReader.h
+++ b/include/ui/InputReader.h
@@ -170,11 +170,10 @@ public:
* and parameters maintained by the input reader.
*/
class InputReaderContext {
-protected:
+public:
InputReaderContext() { }
virtual ~InputReaderContext() { }
-public:
virtual void updateGlobalMetaState() = 0;
virtual int32_t getGlobalMetaState() = 0;
@@ -193,7 +192,7 @@ public:
* the input reader, the input reader never calls into other components while holding
* an exclusive internal lock whenever re-entrance can happen.
*/
-class InputReader : public InputReaderInterface, private InputReaderContext {
+class InputReader : public InputReaderInterface, protected InputReaderContext {
public:
InputReader(const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& policy,
@@ -219,6 +218,11 @@ public:
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
+protected:
+ // These methods are protected virtual so they can be overridden and instrumented
+ // by test cases.
+ virtual InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes);
+
private:
sp<EventHubInterface> mEventHub;
sp<InputReaderPolicyInterface> mPolicy;
@@ -244,12 +248,11 @@ private:
void addDevice(int32_t deviceId);
void removeDevice(int32_t deviceId);
- InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes);
void configureExcludedDevices();
void consumeEvent(const RawEvent* rawEvent);
- void handleConfigurationChanged();
+ void handleConfigurationChanged(nsecs_t when);
// state management for all devices
Mutex mStateLock;
@@ -546,6 +549,21 @@ protected:
int32_t toolMajor;
int32_t toolMinor;
int32_t orientation;
+
+ inline bool operator== (const PointerData& other) const {
+ return id == other.id
+ && x == other.x
+ && y == other.y
+ && pressure == other.pressure
+ && touchMajor == other.touchMajor
+ && touchMinor == other.touchMinor
+ && toolMajor == other.toolMajor
+ && toolMinor == other.toolMinor
+ && orientation == other.orientation;
+ }
+ inline bool operator!= (const PointerData& other) const {
+ return !(*this == other);
+ }
};
// Raw data for a collection of pointers including a pointer id mapping table.
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index f314b09..d661f7b 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -8,6 +8,7 @@ ifeq ($(USE_OPENGL_RENDERER),true)
utils/SortedListImpl.cpp \
FontRenderer.cpp \
GammaFontRenderer.cpp \
+ Caches.cpp \
DisplayListRenderer.cpp \
FboCache.cpp \
GradientCache.cpp \
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
new file mode 100644
index 0000000..a4def0b
--- /dev/null
+++ b/libs/hwui/Caches.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2010 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.
+ */
+
+#define LOG_TAG "OpenGLRenderer"
+
+#include "Caches.h"
+
+namespace android {
+
+#ifdef USE_OPENGL_RENDERER
+using namespace uirenderer;
+ANDROID_SINGLETON_STATIC_INSTANCE(Caches);
+#endif
+
+namespace uirenderer {
+
+///////////////////////////////////////////////////////////////////////////////
+// Constructors/destructor
+///////////////////////////////////////////////////////////////////////////////
+
+Caches::Caches(): Singleton<Caches>(), blend(false), lastSrcMode(GL_ZERO),
+ lastDstMode(GL_ZERO), currentProgram(NULL) {
+ GLint maxTextureUnits;
+ glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
+ if (maxTextureUnits < REQUIRED_TEXTURE_UNITS_COUNT) {
+ LOGW("At least %d texture units are required!", REQUIRED_TEXTURE_UNITS_COUNT);
+ }
+
+ glGenBuffers(1, &meshBuffer);
+ glBindBuffer(GL_ARRAY_BUFFER, meshBuffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(gMeshVertices), gMeshVertices, GL_STATIC_DRAW);
+
+ currentBuffer = meshBuffer;
+}
+
+/**
+ * Binds the VBO used to render simple textured quads.
+ */
+void Caches::bindMeshBuffer() {
+ bindMeshBuffer(meshBuffer);
+}
+
+/**
+ * Binds the specified VBO.
+ */
+void Caches::bindMeshBuffer(const GLuint buffer) {
+ if (currentBuffer != buffer) {
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ currentBuffer = buffer;
+ }
+}
+
+/**
+ * Unbinds the VBO used to render simple textured quads.
+ */
+void Caches::unbindMeshBuffer() {
+ if (currentBuffer) {
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+ currentBuffer = 0;
+ }
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 0c704da..79644a5 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -75,52 +75,16 @@ struct CacheLogger {
///////////////////////////////////////////////////////////////////////////////
class Caches: public Singleton<Caches> {
- Caches(): Singleton<Caches>(), blend(false), lastSrcMode(GL_ZERO),
- lastDstMode(GL_ZERO), currentProgram(NULL) {
- GLint maxTextureUnits;
- glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
- if (maxTextureUnits < REQUIRED_TEXTURE_UNITS_COUNT) {
- LOGW("At least %d texture units are required!", REQUIRED_TEXTURE_UNITS_COUNT);
- }
-
- glGenBuffers(1, &meshBuffer);
- glBindBuffer(GL_ARRAY_BUFFER, meshBuffer);
- glBufferData(GL_ARRAY_BUFFER, sizeof(gMeshVertices), gMeshVertices, GL_STATIC_DRAW);
-
- currentBuffer = meshBuffer;
- }
+ Caches();
friend class Singleton<Caches>;
CacheLogger logger;
public:
- /**
- * Binds the VBO used to render simple textured quads.
- */
- inline void bindMeshBuffer() {
- bindMeshBuffer(meshBuffer);
- }
-
- /**
- * Binds the specified VBO.
- */
- inline void bindMeshBuffer(const GLuint buffer) {
- if (currentBuffer != buffer) {
- glBindBuffer(GL_ARRAY_BUFFER, buffer);
- currentBuffer = buffer;
- }
- }
-
- /**
- * Unbinds the VBO used to render simple textured quads.
- */
- inline void unbindMeshBuffer() {
- if (currentBuffer) {
- glBindBuffer(GL_ARRAY_BUFFER, 0);
- currentBuffer = 0;
- }
- }
+ void bindMeshBuffer();
+ void bindMeshBuffer(const GLuint buffer);
+ void unbindMeshBuffer();
bool blend;
GLenum lastSrcMode;
@@ -146,11 +110,6 @@ public:
}; // namespace uirenderer
-#ifdef USE_OPENGL_RENDERER
-using namespace uirenderer;
-ANDROID_SINGLETON_STATIC_INSTANCE(Caches);
-#endif
-
}; // namespace android
#endif // ANDROID_UI_CACHES_H
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 17ef598..7495a06 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -353,11 +353,22 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
// Window coordinates of the layer
Rect bounds(left, top, right, bottom);
- if (!fboLayer) {
+ if (fboLayer) {
+ // Clear the previous layer regions before we change the viewport
+ clearLayerRegions();
+ } else {
mSnapshot->transform->mapRect(bounds);
+
// Layers only make sense if they are in the framebuffer's bounds
- bounds.intersect(*mSnapshot->clipRect);
+ bounds.intersect(*snapshot->clipRect);
+
+ // We cannot work with sub-pixels in this case
bounds.snapToPixelBoundaries();
+
+ // When the layer is not an FBO, we may use glCopyTexImage so we
+ // need to make sure the layer does not extend outside the bounds
+ // of the framebuffer
+ bounds.intersect(snapshot->previous->viewport);
}
if (bounds.isEmpty() || bounds.getWidth() > mMaxTextureSize ||
@@ -446,14 +457,14 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
// Copy the framebuffer into the layer
glBindTexture(GL_TEXTURE_2D, layer->texture);
- if (layer->empty) {
- glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bounds.left, mHeight - bounds.bottom,
- layer->width, layer->height, 0);
- layer->empty = false;
- } else {
- glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left, mHeight - bounds.bottom,
- bounds.getWidth(), bounds.getHeight());
- }
+ if (layer->empty) {
+ glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bounds.left,
+ snapshot->height - bounds.bottom, layer->width, layer->height, 0);
+ layer->empty = false;
+ } else {
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bounds.left,
+ snapshot->height - bounds.bottom, bounds.getWidth(), bounds.getHeight());
+ }
// Enqueue the buffer coordinates to clear the corresponding region later
mLayers.push(new Rect(bounds));
@@ -479,7 +490,8 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
}
// Restore the clip from the previous snapshot
- const Rect& clip = *previous->clipRect;
+ Rect& clip(*previous->clipRect);
+ clip.snapToPixelBoundaries();
glScissor(clip.left, previous->height - clip.bottom, clip.getWidth(), clip.getHeight());
Layer* layer = current->layer;
@@ -787,7 +799,8 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
}
void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
- const Rect& clip = *mSnapshot->clipRect;
+ Rect& clip(*mSnapshot->clipRect);
+ clip.snapToPixelBoundaries();
drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true);
}
@@ -855,6 +868,7 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
paint->getTextSize());
Rect clipRect(*mSnapshot->clipRect);
+ clipRect.snapToPixelBoundaries();
glScissor(clipRect.left, mSnapshot->height - clipRect.bottom,
clipRect.getWidth(), clipRect.getHeight());
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index c571ea1..8f3655c 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -149,10 +149,10 @@ struct Rect {
}
void snapToPixelBoundaries() {
- left = floorf(left);
- top = floorf(top);
- right = ceilf(right);
- bottom = ceilf(bottom);
+ left = floorf(left + 0.5f);
+ top = floorf(top + 0.5f);
+ right = floorf(right + 0.5f);
+ bottom = floorf(bottom + 0.5f);
}
void dump() const {
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index 05c1a48..2ec003f 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -23,7 +23,13 @@ include $(BUILD_HOST_EXECUTABLE)
# TODO: This should go into build/core/config.mk
RSG_GENERATOR:=$(LOCAL_BUILT_MODULE)
-
+include $(CLEAR_VARS)
+input_data_file := $(LOCAL_PATH)/rslib.bc
+slangdata_output_var_name := rs_runtime_lib_bc
+LOCAL_MODULE := librslib_rt
+LOCAL_MODULE_TAGS := optional
+include frameworks/compile/slang/SlangData.mk
+include $(BUILD_STATIC_LIBRARY)
# Build render script lib ====================
@@ -109,7 +115,7 @@ LOCAL_SRC_FILES:= \
LOCAL_SHARED_LIBRARIES += libcutils libutils libEGL libGLESv1_CM libGLESv2 libui libbcc
-LOCAL_STATIC_LIBRARIES := libft2
+LOCAL_STATIC_LIBRARIES := libft2 librslib_rt
LOCAL_C_INCLUDES += external/freetype/include
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 165fa71..9dce158 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -390,6 +390,9 @@ static BCCvoid* symbolLookup(BCCvoid* pContext, const BCCchar* name)
return NULL;
}
+extern const char rs_runtime_lib_bc[];
+extern unsigned rs_runtime_lib_bc_size;
+
void ScriptCState::runCompiler(Context *rsc, ScriptC *s)
{
LOGV("%p ScriptCState::runCompiler ", rsc);
@@ -398,6 +401,7 @@ void ScriptCState::runCompiler(Context *rsc, ScriptC *s)
s->mBccScript = bccCreateScript();
s->mEnviroment.mIsThreadable = true;
bccScriptBitcode(s->mBccScript, s->mEnviroment.mScriptText, s->mEnviroment.mScriptTextLength);
+ //bccLinkBitcode(s->mBccScript, rs_runtime_lib_bc, rs_runtime_lib_bc_size);
bccRegisterSymbolCallback(s->mBccScript, symbolLookup, s);
bccCompileScript(s->mBccScript);
bccGetScriptLabel(s->mBccScript, "root", (BCCvoid**) &s->mProgram.mRoot);
@@ -533,5 +537,3 @@ RsScript rsi_ScriptCCreate(Context * rsc)
}
}
-
-
diff --git a/libs/rs/rslib.bc b/libs/rs/rslib.bc
new file mode 100644
index 0000000..1897c3b
--- /dev/null
+++ b/libs/rs/rslib.bc
Binary files differ
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index bc08e0a..9c7e7f4 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -403,6 +403,7 @@ bool EventHub::getEvent(RawEvent* outEvent)
outEvent->deviceId = device->id;
}
outEvent->type = DEVICE_REMOVED;
+ outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
delete device;
mNeedToSendFinishedDeviceScan = true;
return true;
@@ -419,6 +420,7 @@ bool EventHub::getEvent(RawEvent* outEvent)
outEvent->deviceId = device->id;
}
outEvent->type = DEVICE_ADDED;
+ outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
mNeedToSendFinishedDeviceScan = true;
return true;
}
@@ -426,6 +428,7 @@ bool EventHub::getEvent(RawEvent* outEvent)
if (mNeedToSendFinishedDeviceScan) {
mNeedToSendFinishedDeviceScan = false;
outEvent->type = FINISHED_DEVICE_SCAN;
+ outEvent->when = systemTime(SYSTEM_TIME_MONOTONIC);
return true;
}
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index d679ea2..629234b 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -124,12 +124,19 @@ static bool validateMotionEvent(int32_t action, size_t pointerCount,
pointerCount, MAX_POINTERS);
return false;
}
+ BitSet32 pointerIdBits;
for (size_t i = 0; i < pointerCount; i++) {
- if (pointerIds[i] < 0 || pointerIds[i] > MAX_POINTER_ID) {
+ int32_t id = pointerIds[i];
+ if (id < 0 || id > MAX_POINTER_ID) {
LOGE("Motion event has invalid pointer id %d; value must be between 0 and %d",
- pointerIds[i], MAX_POINTER_ID);
+ id, MAX_POINTER_ID);
return false;
}
+ if (pointerIdBits.hasBit(id)) {
+ LOGE("Motion event has duplicate pointer id %d", id);
+ return false;
+ }
+ pointerIdBits.markBit(id);
}
return true;
}
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 88b91e0..120222c 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -266,7 +266,7 @@ void InputReader::process(const RawEvent* rawEvent) {
break;
case EventHubInterface::FINISHED_DEVICE_SCAN:
- handleConfigurationChanged();
+ handleConfigurationChanged(rawEvent->when);
break;
default:
@@ -404,7 +404,7 @@ void InputReader::consumeEvent(const RawEvent* rawEvent) {
} // release device registry reader lock
}
-void InputReader::handleConfigurationChanged() {
+void InputReader::handleConfigurationChanged(nsecs_t when) {
// Reset global meta state because it depends on the list of all configured devices.
updateGlobalMetaState();
@@ -412,7 +412,6 @@ void InputReader::handleConfigurationChanged() {
updateInputConfiguration();
// Enqueue configuration changed.
- nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
mDispatcher->notifyConfigurationChanged(when);
}
@@ -2189,7 +2188,7 @@ TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
mLocked.currentVirtualKey.down = false;
#if DEBUG_VIRTUAL_KEYS
LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
- mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
+ mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
#endif
keyEventAction = AKEY_EVENT_ACTION_UP;
keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
@@ -2214,13 +2213,22 @@ TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
mLocked.currentVirtualKey.down = false;
#if DEBUG_VIRTUAL_KEYS
LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
- mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
+ mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
#endif
keyEventAction = AKEY_EVENT_ACTION_UP;
keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
| AKEY_EVENT_FLAG_CANCELED;
- touchResult = DROP_STROKE;
- goto DispatchVirtualKey;
+
+ // Check whether the pointer moved inside the display area where we should
+ // start a new stroke.
+ int32_t x = mCurrentTouch.pointers[0].x;
+ int32_t y = mCurrentTouch.pointers[0].y;
+ if (isPointInsideSurfaceLocked(x, y)) {
+ mLastTouch.clear();
+ touchResult = DISPATCH_TOUCH;
+ } else {
+ touchResult = DROP_STROKE;
+ }
} else {
if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
// Pointer just went down. Handle off-screen touches, if needed.
@@ -2238,7 +2246,8 @@ TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
#if DEBUG_VIRTUAL_KEYS
LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
- mCurrentVirtualKey.keyCode, mCurrentVirtualKey.scanCode);
+ mLocked.currentVirtualKey.keyCode,
+ mLocked.currentVirtualKey.scanCode);
#endif
keyEventAction = AKEY_EVENT_ACTION_DOWN;
keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
@@ -2285,14 +2294,35 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
dispatchTouch(when, policyFlags, & mCurrentTouch,
currentIdBits, -1, currentPointerCount, motionEventAction);
} else {
- // There may be pointers going up and pointers going down at the same time when pointer
- // ids are reported by the device driver.
+ // There may be pointers going up and pointers going down and pointers moving
+ // all at the same time.
BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
BitSet32 activeIdBits(lastIdBits.value);
uint32_t pointerCount = lastPointerCount;
- while (! upIdBits.isEmpty()) {
+ // Produce an intermediate representation of the touch data that consists of the
+ // old location of pointers that have just gone up and the new location of pointers that
+ // have just moved but omits the location of pointers that have just gone down.
+ TouchData interimTouch;
+ interimTouch.copyFrom(mLastTouch);
+
+ BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
+ bool moveNeeded = false;
+ while (!moveIdBits.isEmpty()) {
+ uint32_t moveId = moveIdBits.firstMarkedBit();
+ moveIdBits.clearBit(moveId);
+
+ int32_t oldIndex = mLastTouch.idToIndex[moveId];
+ int32_t newIndex = mCurrentTouch.idToIndex[moveId];
+ if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
+ interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
+ moveNeeded = true;
+ }
+ }
+
+ // Dispatch pointer up events using the interim pointer locations.
+ while (!upIdBits.isEmpty()) {
uint32_t upId = upIdBits.firstMarkedBit();
upIdBits.clearBit(upId);
BitSet32 oldActiveIdBits = activeIdBits;
@@ -2305,12 +2335,21 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
}
- dispatchTouch(when, policyFlags, & mLastTouch,
+ dispatchTouch(when, policyFlags, &interimTouch,
oldActiveIdBits, upId, pointerCount, motionEventAction);
pointerCount -= 1;
}
- while (! downIdBits.isEmpty()) {
+ // Dispatch move events if any of the remaining pointers moved from their old locations.
+ // Although applications receive new locations as part of individual pointer up
+ // events, they do not generally handle them except when presented in a move event.
+ if (moveNeeded) {
+ dispatchTouch(when, policyFlags, &mCurrentTouch,
+ activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
+ }
+
+ // Dispatch pointer down events using the new pointer locations.
+ while (!downIdBits.isEmpty()) {
uint32_t downId = downIdBits.firstMarkedBit();
downIdBits.clearBit(downId);
BitSet32 oldActiveIdBits = activeIdBits;
@@ -2325,7 +2364,7 @@ void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
}
pointerCount += 1;
- dispatchTouch(when, policyFlags, & mCurrentTouch,
+ dispatchTouch(when, policyFlags, &mCurrentTouch,
activeIdBits, downId, pointerCount, motionEventAction);
}
}
@@ -3434,8 +3473,8 @@ void MultiTouchInputMapper::sync(nsecs_t when) {
if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
if (inPointer.absMTPressure <= 0) {
- // Some devices send sync packets with X / Y but with a 0 presure to indicate
- // a pointer up. Drop this finger.
+ // Some devices send sync packets with X / Y but with a 0 pressure to indicate
+ // a pointer going up. Drop this finger.
continue;
}
outPointer.pressure = inPointer.absMTPressure;
diff --git a/libs/ui/tests/Android.mk b/libs/ui/tests/Android.mk
index 62f824f..aa017b9 100644
--- a/libs/ui/tests/Android.mk
+++ b/libs/ui/tests/Android.mk
@@ -7,6 +7,7 @@ ifneq ($(TARGET_SIMULATOR),true)
# Build the unit tests.
test_src_files := \
InputChannel_test.cpp \
+ InputReader_test.cpp \
InputDispatcher_test.cpp \
InputPublisherAndConsumer_test.cpp
diff --git a/libs/ui/tests/InputDispatcher_test.cpp b/libs/ui/tests/InputDispatcher_test.cpp
index 1dc6e46..8874dfe 100644
--- a/libs/ui/tests/InputDispatcher_test.cpp
+++ b/libs/ui/tests/InputDispatcher_test.cpp
@@ -4,15 +4,223 @@
#include <ui/InputDispatcher.h>
#include <gtest/gtest.h>
+#include <linux/input.h>
namespace android {
-class InputDispatcherTest : public testing::Test {
+// An arbitrary time value.
+static const nsecs_t ARBITRARY_TIME = 1234;
+
+// An arbitrary device id.
+static const int32_t DEVICE_ID = 1;
+
+// An arbitrary injector pid / uid pair that has permission to inject events.
+static const int32_t INJECTOR_PID = 999;
+static const int32_t INJECTOR_UID = 1001;
+
+
+// --- FakeInputDispatcherPolicy ---
+
+class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface {
+protected:
+ virtual ~FakeInputDispatcherPolicy() {
+ }
+
public:
+ FakeInputDispatcherPolicy() {
+ }
+
+private:
+ virtual void notifyConfigurationChanged(nsecs_t when) {
+ }
+
+ virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
+ const sp<InputChannel>& inputChannel) {
+ return 0;
+ }
+
+ virtual void notifyInputChannelBroken(const sp<InputChannel>& inputChannel) {
+ }
+
+ virtual nsecs_t getKeyRepeatTimeout() {
+ return 500 * 1000000LL;
+ }
+
+ virtual nsecs_t getKeyRepeatDelay() {
+ return 50 * 1000000LL;
+ }
+
+ virtual int32_t getMaxEventsPerSecond() {
+ return 60;
+ }
+
+ virtual void interceptKeyBeforeQueueing(nsecs_t when, int32_t deviceId,
+ int32_t action, int32_t& flags, int32_t keyCode, int32_t scanCode,
+ uint32_t& policyFlags) {
+ }
+
+ virtual void interceptGenericBeforeQueueing(nsecs_t when, uint32_t& policyFlags) {
+ }
+
+ virtual bool interceptKeyBeforeDispatching(const sp<InputChannel>& inputChannel,
+ const KeyEvent* keyEvent, uint32_t policyFlags) {
+ return false;
+ }
+
+ virtual void notifySwitch(nsecs_t when,
+ int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
+ }
+
+ virtual void pokeUserActivity(nsecs_t eventTime, int32_t eventType) {
+ }
+
+ virtual bool checkInjectEventsPermissionNonReentrant(
+ int32_t injectorPid, int32_t injectorUid) {
+ return false;
+ }
};
-TEST_F(InputDispatcherTest, Dummy) {
- // TODO
+
+// --- InputDispatcherTest ---
+
+class InputDispatcherTest : public testing::Test {
+protected:
+ sp<FakeInputDispatcherPolicy> mFakePolicy;
+ sp<InputDispatcher> mDispatcher;
+
+ virtual void SetUp() {
+ mFakePolicy = new FakeInputDispatcherPolicy();
+ mDispatcher = new InputDispatcher(mFakePolicy);
+ }
+
+ virtual void TearDown() {
+ mFakePolicy.clear();
+ mDispatcher.clear();
+ }
+};
+
+
+TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesKeyEvents) {
+ KeyEvent event;
+
+ // Rejects undefined key actions.
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
+ /*action*/ -1, 0,
+ AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ << "Should reject key events with undefined action.";
+
+ // Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
+ AKEY_EVENT_ACTION_MULTIPLE, 0,
+ AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME, ARBITRARY_TIME);
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ << "Should reject key events with ACTION_MULTIPLE.";
+}
+
+TEST_F(InputDispatcherTest, InjectInputEvent_ValidatesMotionEvents) {
+ MotionEvent event;
+ int32_t pointerIds[MAX_POINTERS + 1];
+ PointerCoords pointerCoords[MAX_POINTERS + 1];
+ for (int i = 0; i <= MAX_POINTERS; i++) {
+ pointerIds[i] = i;
+ }
+
+ // Rejects undefined motion actions.
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ /*action*/ -1, 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME,
+ /*pointerCount*/ 1, pointerIds, pointerCoords);
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ << "Should reject motion events with undefined action.";
+
+ // Rejects pointer down with invalid index.
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME,
+ /*pointerCount*/ 1, pointerIds, pointerCoords);
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ << "Should reject motion events with pointer down index too large.";
+
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ AMOTION_EVENT_ACTION_POINTER_DOWN | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME,
+ /*pointerCount*/ 1, pointerIds, pointerCoords);
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ << "Should reject motion events with pointer down index too small.";
+
+ // Rejects pointer up with invalid index.
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME,
+ /*pointerCount*/ 1, pointerIds, pointerCoords);
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ << "Should reject motion events with pointer up index too large.";
+
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ AMOTION_EVENT_ACTION_POINTER_UP | (-1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME,
+ /*pointerCount*/ 1, pointerIds, pointerCoords);
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ << "Should reject motion events with pointer up index too small.";
+
+ // Rejects motion events with invalid number of pointers.
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME,
+ /*pointerCount*/ 0, pointerIds, pointerCoords);
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ << "Should reject motion events with 0 pointers.";
+
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME,
+ /*pointerCount*/ MAX_POINTERS + 1, pointerIds, pointerCoords);
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ << "Should reject motion events with more than MAX_POINTERS pointers.";
+
+ // Rejects motion events with invalid pointer ids.
+ pointerIds[0] = -1;
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME,
+ /*pointerCount*/ 1, pointerIds, pointerCoords);
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ << "Should reject motion events with pointer ids less than 0.";
+
+ pointerIds[0] = MAX_POINTER_ID + 1;
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME,
+ /*pointerCount*/ 1, pointerIds, pointerCoords);
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ << "Should reject motion events with pointer ids greater than MAX_POINTER_ID.";
+
+ // Rejects motion events with duplicate pointer ids.
+ pointerIds[0] = 1;
+ pointerIds[1] = 1;
+ event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, AMETA_NONE, 0, 0, 0, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME,
+ /*pointerCount*/ 2, pointerIds, pointerCoords);
+ ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(&event,
+ INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0))
+ << "Should reject motion events with duplicate pointer ids.";
}
} // namespace android
diff --git a/libs/ui/tests/InputReader_test.cpp b/libs/ui/tests/InputReader_test.cpp
new file mode 100644
index 0000000..c19147f
--- /dev/null
+++ b/libs/ui/tests/InputReader_test.cpp
@@ -0,0 +1,3381 @@
+//
+// Copyright 2010 The Android Open Source Project
+//
+
+#include <ui/InputReader.h>
+#include <utils/List.h>
+#include <gtest/gtest.h>
+#include <math.h>
+
+namespace android {
+
+// An arbitrary time value.
+static const nsecs_t ARBITRARY_TIME = 1234;
+
+// Arbitrary display properties.
+static const int32_t DISPLAY_ID = 0;
+static const int32_t DISPLAY_WIDTH = 480;
+static const int32_t DISPLAY_HEIGHT = 800;
+
+// Error tolerance for floating point assertions.
+static const float EPSILON = 0.001f;
+
+template<typename T>
+static inline T min(T a, T b) {
+ return a < b ? a : b;
+}
+
+static inline float avg(float x, float y) {
+ return (x + y) / 2;
+}
+
+
+// --- FakeInputReaderPolicy ---
+
+class FakeInputReaderPolicy : public InputReaderPolicyInterface {
+ struct DisplayInfo {
+ int32_t width;
+ int32_t height;
+ int32_t orientation;
+ };
+
+ KeyedVector<int32_t, DisplayInfo> mDisplayInfos;
+ bool mFilterTouchEvents;
+ bool mFilterJumpyTouchEvents;
+ KeyedVector<String8, Vector<VirtualKeyDefinition> > mVirtualKeyDefinitions;
+ KeyedVector<String8, InputDeviceCalibration> mInputDeviceCalibrations;
+ Vector<String8> mExcludedDeviceNames;
+
+protected:
+ virtual ~FakeInputReaderPolicy() { }
+
+public:
+ FakeInputReaderPolicy() :
+ mFilterTouchEvents(false), mFilterJumpyTouchEvents(false) {
+ }
+
+ void removeDisplayInfo(int32_t displayId) {
+ mDisplayInfos.removeItem(displayId);
+ }
+
+ void setDisplayInfo(int32_t displayId, int32_t width, int32_t height, int32_t orientation) {
+ removeDisplayInfo(displayId);
+
+ DisplayInfo info;
+ info.width = width;
+ info.height = height;
+ info.orientation = orientation;
+ mDisplayInfos.add(displayId, info);
+ }
+
+ void setFilterTouchEvents(bool enabled) {
+ mFilterTouchEvents = enabled;
+ }
+
+ void setFilterJumpyTouchEvents(bool enabled) {
+ mFilterJumpyTouchEvents = enabled;
+ }
+
+ void addInputDeviceCalibration(const String8& deviceName,
+ const InputDeviceCalibration& calibration) {
+ mInputDeviceCalibrations.add(deviceName, calibration);
+ }
+
+ void addInputDeviceCalibrationProperty(const String8& deviceName,
+ const String8& key, const String8& value) {
+ ssize_t index = mInputDeviceCalibrations.indexOfKey(deviceName);
+ if (index < 0) {
+ index = mInputDeviceCalibrations.add(deviceName, InputDeviceCalibration());
+ }
+ mInputDeviceCalibrations.editValueAt(index).addProperty(key, value);
+ }
+
+ void addVirtualKeyDefinition(const String8& deviceName,
+ const VirtualKeyDefinition& definition) {
+ if (mVirtualKeyDefinitions.indexOfKey(deviceName) < 0) {
+ mVirtualKeyDefinitions.add(deviceName, Vector<VirtualKeyDefinition>());
+ }
+
+ mVirtualKeyDefinitions.editValueFor(deviceName).push(definition);
+ }
+
+ void addExcludedDeviceName(const String8& deviceName) {
+ mExcludedDeviceNames.push(deviceName);
+ }
+
+private:
+ virtual bool getDisplayInfo(int32_t displayId,
+ int32_t* width, int32_t* height, int32_t* orientation) {
+ ssize_t index = mDisplayInfos.indexOfKey(displayId);
+ if (index >= 0) {
+ const DisplayInfo& info = mDisplayInfos.valueAt(index);
+ if (width) {
+ *width = info.width;
+ }
+ if (height) {
+ *height = info.height;
+ }
+ if (orientation) {
+ *orientation = info.orientation;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ virtual bool filterTouchEvents() {
+ return mFilterTouchEvents;
+ }
+
+ virtual bool filterJumpyTouchEvents() {
+ return mFilterJumpyTouchEvents;
+ }
+
+ virtual void getVirtualKeyDefinitions(const String8& deviceName,
+ Vector<VirtualKeyDefinition>& outVirtualKeyDefinitions) {
+ ssize_t index = mVirtualKeyDefinitions.indexOfKey(deviceName);
+ if (index >= 0) {
+ outVirtualKeyDefinitions.appendVector(mVirtualKeyDefinitions.valueAt(index));
+ }
+ }
+
+ virtual void getInputDeviceCalibration(const String8& deviceName,
+ InputDeviceCalibration& outCalibration) {
+ ssize_t index = mInputDeviceCalibrations.indexOfKey(deviceName);
+ if (index >= 0) {
+ outCalibration = mInputDeviceCalibrations.valueAt(index);
+ }
+ }
+
+ virtual void getExcludedDeviceNames(Vector<String8>& outExcludedDeviceNames) {
+ outExcludedDeviceNames.appendVector(mExcludedDeviceNames);
+ }
+};
+
+
+// --- FakeInputDispatcher ---
+
+class FakeInputDispatcher : public InputDispatcherInterface {
+public:
+ struct NotifyConfigurationChangedArgs {
+ nsecs_t eventTime;
+ };
+
+ struct NotifyKeyArgs {
+ nsecs_t eventTime;
+ int32_t deviceId;
+ int32_t source;
+ uint32_t policyFlags;
+ int32_t action;
+ int32_t flags;
+ int32_t keyCode;
+ int32_t scanCode;
+ int32_t metaState;
+ nsecs_t downTime;
+ };
+
+ struct NotifyMotionArgs {
+ nsecs_t eventTime;
+ int32_t deviceId;
+ int32_t source;
+ uint32_t policyFlags;
+ int32_t action;
+ int32_t flags;
+ int32_t metaState;
+ int32_t edgeFlags;
+ uint32_t pointerCount;
+ Vector<int32_t> pointerIds;
+ Vector<PointerCoords> pointerCoords;
+ float xPrecision;
+ float yPrecision;
+ nsecs_t downTime;
+ };
+
+ struct NotifySwitchArgs {
+ nsecs_t when;
+ int32_t switchCode;
+ int32_t switchValue;
+ uint32_t policyFlags;
+ };
+
+private:
+ List<NotifyConfigurationChangedArgs> mNotifyConfigurationChangedArgs;
+ List<NotifyKeyArgs> mNotifyKeyArgs;
+ List<NotifyMotionArgs> mNotifyMotionArgs;
+ List<NotifySwitchArgs> mNotifySwitchArgs;
+
+protected:
+ virtual ~FakeInputDispatcher() { }
+
+public:
+ FakeInputDispatcher() {
+ }
+
+ void assertNotifyConfigurationChangedWasCalled(NotifyConfigurationChangedArgs* outArgs = NULL) {
+ ASSERT_FALSE(mNotifyConfigurationChangedArgs.empty())
+ << "Expected notifyConfigurationChanged() to have been called.";
+ if (outArgs) {
+ *outArgs = *mNotifyConfigurationChangedArgs.begin();
+ }
+ mNotifyConfigurationChangedArgs.erase(mNotifyConfigurationChangedArgs.begin());
+ }
+
+ void assertNotifyKeyWasCalled(NotifyKeyArgs* outArgs = NULL) {
+ ASSERT_FALSE(mNotifyKeyArgs.empty())
+ << "Expected notifyKey() to have been called.";
+ if (outArgs) {
+ *outArgs = *mNotifyKeyArgs.begin();
+ }
+ mNotifyKeyArgs.erase(mNotifyKeyArgs.begin());
+ }
+
+ void assertNotifyKeyWasNotCalled() {
+ ASSERT_TRUE(mNotifyKeyArgs.empty())
+ << "Expected notifyKey() to not have been called.";
+ }
+
+ void assertNotifyMotionWasCalled(NotifyMotionArgs* outArgs = NULL) {
+ ASSERT_FALSE(mNotifyMotionArgs.empty())
+ << "Expected notifyMotion() to have been called.";
+ if (outArgs) {
+ *outArgs = *mNotifyMotionArgs.begin();
+ }
+ mNotifyMotionArgs.erase(mNotifyMotionArgs.begin());
+ }
+
+ void assertNotifyMotionWasNotCalled() {
+ ASSERT_TRUE(mNotifyMotionArgs.empty())
+ << "Expected notifyMotion() to not have been called.";
+ }
+
+ void assertNotifySwitchWasCalled(NotifySwitchArgs* outArgs = NULL) {
+ ASSERT_FALSE(mNotifySwitchArgs.empty())
+ << "Expected notifySwitch() to have been called.";
+ if (outArgs) {
+ *outArgs = *mNotifySwitchArgs.begin();
+ }
+ mNotifySwitchArgs.erase(mNotifySwitchArgs.begin());
+ }
+
+private:
+ virtual void notifyConfigurationChanged(nsecs_t eventTime) {
+ NotifyConfigurationChangedArgs args;
+ args.eventTime = eventTime;
+ mNotifyConfigurationChangedArgs.push_back(args);
+ }
+
+ virtual void notifyKey(nsecs_t eventTime, int32_t deviceId, int32_t source,
+ uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
+ int32_t scanCode, int32_t metaState, nsecs_t downTime) {
+ NotifyKeyArgs args;
+ args.eventTime = eventTime;
+ args.deviceId = deviceId;
+ args.source = source;
+ args.policyFlags = policyFlags;
+ args.action = action;
+ args.flags = flags;
+ args.keyCode = keyCode;
+ args.scanCode = scanCode;
+ args.metaState = metaState;
+ args.downTime = downTime;
+ mNotifyKeyArgs.push_back(args);
+ }
+
+ virtual void notifyMotion(nsecs_t eventTime, int32_t deviceId, int32_t source,
+ uint32_t policyFlags, int32_t action, int32_t flags,
+ int32_t metaState, int32_t edgeFlags,
+ uint32_t pointerCount, const int32_t* pointerIds, const PointerCoords* pointerCoords,
+ float xPrecision, float yPrecision, nsecs_t downTime) {
+ NotifyMotionArgs args;
+ args.eventTime = eventTime;
+ args.deviceId = deviceId;
+ args.source = source;
+ args.policyFlags = policyFlags;
+ args.action = action;
+ args.flags = flags;
+ args.metaState = metaState;
+ args.edgeFlags = edgeFlags;
+ args.pointerCount = pointerCount;
+ args.pointerIds.clear();
+ args.pointerIds.appendArray(pointerIds, pointerCount);
+ args.pointerCoords.clear();
+ args.pointerCoords.appendArray(pointerCoords, pointerCount);
+ args.xPrecision = xPrecision;
+ args.yPrecision = yPrecision;
+ args.downTime = downTime;
+ mNotifyMotionArgs.push_back(args);
+ }
+
+ virtual void notifySwitch(nsecs_t when,
+ int32_t switchCode, int32_t switchValue, uint32_t policyFlags) {
+ NotifySwitchArgs args;
+ args.when = when;
+ args.switchCode = switchCode;
+ args.switchValue = switchValue;
+ args.policyFlags = policyFlags;
+ mNotifySwitchArgs.push_back(args);
+ }
+
+ virtual void dump(String8& dump) {
+ ADD_FAILURE() << "Should never be called by input reader.";
+ }
+
+ virtual void dispatchOnce() {
+ ADD_FAILURE() << "Should never be called by input reader.";
+ }
+
+ virtual int32_t injectInputEvent(const InputEvent* event,
+ int32_t injectorPid, int32_t injectorUid, int32_t syncMode, int32_t timeoutMillis) {
+ ADD_FAILURE() << "Should never be called by input reader.";
+ return INPUT_EVENT_INJECTION_FAILED;
+ }
+
+ virtual void setInputWindows(const Vector<InputWindow>& inputWindows) {
+ ADD_FAILURE() << "Should never be called by input reader.";
+ }
+
+ virtual void setFocusedApplication(const InputApplication* inputApplication) {
+ ADD_FAILURE() << "Should never be called by input reader.";
+ }
+
+ virtual void setInputDispatchMode(bool enabled, bool frozen) {
+ ADD_FAILURE() << "Should never be called by input reader.";
+ }
+
+ virtual bool transferTouchFocus(const sp<InputChannel>& fromChannel,
+ const sp<InputChannel>& toChannel) {
+ ADD_FAILURE() << "Should never be called by input reader.";
+ return 0;
+ }
+
+ virtual status_t registerInputChannel(const sp<InputChannel>& inputChannel, bool monitor) {
+ ADD_FAILURE() << "Should never be called by input reader.";
+ return 0;
+ }
+
+ virtual status_t unregisterInputChannel(const sp<InputChannel>& inputChannel) {
+ ADD_FAILURE() << "Should never be called by input reader.";
+ return 0;
+ }
+};
+
+
+// --- FakeEventHub ---
+
+class FakeEventHub : public EventHubInterface {
+ struct KeyInfo {
+ int32_t keyCode;
+ uint32_t flags;
+ };
+
+ struct Device {
+ String8 name;
+ uint32_t classes;
+ KeyedVector<int, RawAbsoluteAxisInfo> axes;
+ KeyedVector<int32_t, int32_t> keyCodeStates;
+ KeyedVector<int32_t, int32_t> scanCodeStates;
+ KeyedVector<int32_t, int32_t> switchStates;
+ KeyedVector<int32_t, KeyInfo> keys;
+
+ Device(const String8& name, uint32_t classes) :
+ name(name), classes(classes) {
+ }
+ };
+
+ KeyedVector<int32_t, Device*> mDevices;
+ Vector<String8> mExcludedDevices;
+ List<RawEvent> mEvents;
+
+protected:
+ virtual ~FakeEventHub() {
+ for (size_t i = 0; i < mDevices.size(); i++) {
+ delete mDevices.valueAt(i);
+ }
+ }
+
+public:
+ FakeEventHub() { }
+
+ void addDevice(int32_t deviceId, const String8& name, uint32_t classes) {
+ Device* device = new Device(name, classes);
+ mDevices.add(deviceId, device);
+
+ enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_ADDED, 0, 0, 0, 0);
+ }
+
+ void removeDevice(int32_t deviceId) {
+ delete mDevices.valueFor(deviceId);
+ mDevices.removeItem(deviceId);
+
+ enqueueEvent(ARBITRARY_TIME, deviceId, EventHubInterface::DEVICE_REMOVED, 0, 0, 0, 0);
+ }
+
+ void finishDeviceScan() {
+ enqueueEvent(ARBITRARY_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0, 0, 0);
+ }
+
+ void addAxis(int32_t deviceId, int axis,
+ int32_t minValue, int32_t maxValue, int flat, int fuzz) {
+ Device* device = getDevice(deviceId);
+
+ RawAbsoluteAxisInfo info;
+ info.valid = true;
+ info.minValue = minValue;
+ info.maxValue = maxValue;
+ info.flat = flat;
+ info.fuzz = fuzz;
+ device->axes.add(axis, info);
+ }
+
+ void setKeyCodeState(int32_t deviceId, int32_t keyCode, int32_t state) {
+ Device* device = getDevice(deviceId);
+ device->keyCodeStates.replaceValueFor(keyCode, state);
+ }
+
+ void setScanCodeState(int32_t deviceId, int32_t scanCode, int32_t state) {
+ Device* device = getDevice(deviceId);
+ device->scanCodeStates.replaceValueFor(scanCode, state);
+ }
+
+ void setSwitchState(int32_t deviceId, int32_t switchCode, int32_t state) {
+ Device* device = getDevice(deviceId);
+ device->switchStates.replaceValueFor(switchCode, state);
+ }
+
+ void addKey(int32_t deviceId, int32_t scanCode, int32_t keyCode, uint32_t flags) {
+ Device* device = getDevice(deviceId);
+ KeyInfo info;
+ info.keyCode = keyCode;
+ info.flags = flags;
+ device->keys.add(scanCode, info);
+ }
+
+ Vector<String8>& getExcludedDevices() {
+ return mExcludedDevices;
+ }
+
+ void enqueueEvent(nsecs_t when, int32_t deviceId, int32_t type,
+ int32_t scanCode, int32_t keyCode, int32_t value, uint32_t flags) {
+ RawEvent event;
+ event.when = when;
+ event.deviceId = deviceId;
+ event.type = type;
+ event.scanCode = scanCode;
+ event.keyCode = keyCode;
+ event.value = value;
+ event.flags = flags;
+ mEvents.push_back(event);
+ }
+
+ void assertQueueIsEmpty() {
+ ASSERT_EQ(size_t(0), mEvents.size())
+ << "Expected the event queue to be empty (fully consumed).";
+ }
+
+private:
+ Device* getDevice(int32_t deviceId) const {
+ ssize_t index = mDevices.indexOfKey(deviceId);
+ return index >= 0 ? mDevices.valueAt(index) : NULL;
+ }
+
+ virtual uint32_t getDeviceClasses(int32_t deviceId) const {
+ Device* device = getDevice(deviceId);
+ return device ? device->classes : 0;
+ }
+
+ virtual String8 getDeviceName(int32_t deviceId) const {
+ Device* device = getDevice(deviceId);
+ return device ? device->name : String8("unknown");
+ }
+
+ virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
+ RawAbsoluteAxisInfo* outAxisInfo) const {
+ Device* device = getDevice(deviceId);
+ if (device) {
+ ssize_t index = device->axes.indexOfKey(axis);
+ if (index >= 0) {
+ *outAxisInfo = device->axes.valueAt(index);
+ return OK;
+ }
+ }
+ return -1;
+ }
+
+ virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
+ int32_t* outKeycode, uint32_t* outFlags) const {
+ Device* device = getDevice(deviceId);
+ if (device) {
+ ssize_t index = device->keys.indexOfKey(scancode);
+ if (index >= 0) {
+ if (outKeycode) {
+ *outKeycode = device->keys.valueAt(index).keyCode;
+ }
+ if (outFlags) {
+ *outFlags = device->keys.valueAt(index).flags;
+ }
+ return OK;
+ }
+ }
+ return NAME_NOT_FOUND;
+ }
+
+ virtual void addExcludedDevice(const char* deviceName) {
+ mExcludedDevices.add(String8(deviceName));
+ }
+
+ virtual bool getEvent(RawEvent* outEvent) {
+ if (mEvents.empty()) {
+ return false;
+ }
+
+ *outEvent = *mEvents.begin();
+ mEvents.erase(mEvents.begin());
+ return true;
+ }
+
+ virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const {
+ Device* device = getDevice(deviceId);
+ if (device) {
+ ssize_t index = device->scanCodeStates.indexOfKey(scanCode);
+ if (index >= 0) {
+ return device->scanCodeStates.valueAt(index);
+ }
+ }
+ return AKEY_STATE_UNKNOWN;
+ }
+
+ virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const {
+ Device* device = getDevice(deviceId);
+ if (device) {
+ ssize_t index = device->keyCodeStates.indexOfKey(keyCode);
+ if (index >= 0) {
+ return device->keyCodeStates.valueAt(index);
+ }
+ }
+ return AKEY_STATE_UNKNOWN;
+ }
+
+ virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const {
+ Device* device = getDevice(deviceId);
+ if (device) {
+ ssize_t index = device->switchStates.indexOfKey(sw);
+ if (index >= 0) {
+ return device->switchStates.valueAt(index);
+ }
+ }
+ return AKEY_STATE_UNKNOWN;
+ }
+
+ virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
+ uint8_t* outFlags) const {
+ bool result = false;
+ Device* device = getDevice(deviceId);
+ if (device) {
+ for (size_t i = 0; i < numCodes; i++) {
+ for (size_t j = 0; j < device->keys.size(); j++) {
+ if (keyCodes[i] == device->keys.valueAt(j).keyCode) {
+ outFlags[i] = 1;
+ result = true;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ virtual bool hasLed(int32_t deviceId, int32_t led) const {
+ return false;
+ }
+
+ virtual void setLedState(int32_t deviceId, int32_t led, bool on) {
+ }
+
+ virtual void dump(String8& dump) {
+ }
+};
+
+
+// --- FakeInputReaderContext ---
+
+class FakeInputReaderContext : public InputReaderContext {
+ sp<EventHubInterface> mEventHub;
+ sp<InputReaderPolicyInterface> mPolicy;
+ sp<InputDispatcherInterface> mDispatcher;
+ int32_t mGlobalMetaState;
+ bool mUpdateGlobalMetaStateWasCalled;
+
+public:
+ FakeInputReaderContext(const sp<EventHubInterface>& eventHub,
+ const sp<InputReaderPolicyInterface>& policy,
+ const sp<InputDispatcherInterface>& dispatcher) :
+ mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
+ mGlobalMetaState(0) {
+ }
+
+ virtual ~FakeInputReaderContext() { }
+
+ void assertUpdateGlobalMetaStateWasCalled() {
+ ASSERT_TRUE(mUpdateGlobalMetaStateWasCalled)
+ << "Expected updateGlobalMetaState() to have been called.";
+ mUpdateGlobalMetaStateWasCalled = false;
+ }
+
+ void setGlobalMetaState(int32_t state) {
+ mGlobalMetaState = state;
+ }
+
+private:
+ virtual void updateGlobalMetaState() {
+ mUpdateGlobalMetaStateWasCalled = true;
+ }
+
+ virtual int32_t getGlobalMetaState() {
+ return mGlobalMetaState;
+ }
+
+ virtual EventHubInterface* getEventHub() {
+ return mEventHub.get();
+ }
+
+ virtual InputReaderPolicyInterface* getPolicy() {
+ return mPolicy.get();
+ }
+
+ virtual InputDispatcherInterface* getDispatcher() {
+ return mDispatcher.get();
+ }
+};
+
+
+// --- FakeInputMapper ---
+
+class FakeInputMapper : public InputMapper {
+ uint32_t mSources;
+ int32_t mKeyboardType;
+ int32_t mMetaState;
+ KeyedVector<int32_t, int32_t> mKeyCodeStates;
+ KeyedVector<int32_t, int32_t> mScanCodeStates;
+ KeyedVector<int32_t, int32_t> mSwitchStates;
+ Vector<int32_t> mSupportedKeyCodes;
+ RawEvent mLastEvent;
+
+ bool mConfigureWasCalled;
+ bool mResetWasCalled;
+ bool mProcessWasCalled;
+
+public:
+ FakeInputMapper(InputDevice* device, uint32_t sources) :
+ InputMapper(device),
+ mSources(sources), mKeyboardType(AINPUT_KEYBOARD_TYPE_NONE),
+ mMetaState(0),
+ mConfigureWasCalled(false), mResetWasCalled(false), mProcessWasCalled(false) {
+ }
+
+ virtual ~FakeInputMapper() { }
+
+ void setKeyboardType(int32_t keyboardType) {
+ mKeyboardType = keyboardType;
+ }
+
+ void setMetaState(int32_t metaState) {
+ mMetaState = metaState;
+ }
+
+ void assertConfigureWasCalled() {
+ ASSERT_TRUE(mConfigureWasCalled)
+ << "Expected configure() to have been called.";
+ mConfigureWasCalled = false;
+ }
+
+ void assertResetWasCalled() {
+ ASSERT_TRUE(mResetWasCalled)
+ << "Expected reset() to have been called.";
+ mResetWasCalled = false;
+ }
+
+ void assertProcessWasCalled(RawEvent* outLastEvent = NULL) {
+ ASSERT_TRUE(mProcessWasCalled)
+ << "Expected process() to have been called.";
+ if (outLastEvent) {
+ *outLastEvent = mLastEvent;
+ }
+ mProcessWasCalled = false;
+ }
+
+ void setKeyCodeState(int32_t keyCode, int32_t state) {
+ mKeyCodeStates.replaceValueFor(keyCode, state);
+ }
+
+ void setScanCodeState(int32_t scanCode, int32_t state) {
+ mScanCodeStates.replaceValueFor(scanCode, state);
+ }
+
+ void setSwitchState(int32_t switchCode, int32_t state) {
+ mSwitchStates.replaceValueFor(switchCode, state);
+ }
+
+ void addSupportedKeyCode(int32_t keyCode) {
+ mSupportedKeyCodes.add(keyCode);
+ }
+
+private:
+ virtual uint32_t getSources() {
+ return mSources;
+ }
+
+ virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo) {
+ InputMapper::populateDeviceInfo(deviceInfo);
+
+ if (mKeyboardType != AINPUT_KEYBOARD_TYPE_NONE) {
+ deviceInfo->setKeyboardType(mKeyboardType);
+ }
+ }
+
+ virtual void configure() {
+ mConfigureWasCalled = true;
+ }
+
+ virtual void reset() {
+ mResetWasCalled = true;
+ }
+
+ virtual void process(const RawEvent* rawEvent) {
+ mLastEvent = *rawEvent;
+ mProcessWasCalled = true;
+ }
+
+ virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
+ ssize_t index = mKeyCodeStates.indexOfKey(keyCode);
+ return index >= 0 ? mKeyCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
+ }
+
+ virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
+ ssize_t index = mScanCodeStates.indexOfKey(scanCode);
+ return index >= 0 ? mScanCodeStates.valueAt(index) : AKEY_STATE_UNKNOWN;
+ }
+
+ virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode) {
+ ssize_t index = mSwitchStates.indexOfKey(switchCode);
+ return index >= 0 ? mSwitchStates.valueAt(index) : AKEY_STATE_UNKNOWN;
+ }
+
+ virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+ const int32_t* keyCodes, uint8_t* outFlags) {
+ bool result = false;
+ for (size_t i = 0; i < numCodes; i++) {
+ for (size_t j = 0; j < mSupportedKeyCodes.size(); j++) {
+ if (keyCodes[i] == mSupportedKeyCodes[j]) {
+ outFlags[i] = 1;
+ result = true;
+ }
+ }
+ }
+ return result;
+ }
+
+ virtual int32_t getMetaState() {
+ return mMetaState;
+ }
+};
+
+
+// --- InstrumentedInputReader ---
+
+class InstrumentedInputReader : public InputReader {
+ InputDevice* mNextDevice;
+
+public:
+ InstrumentedInputReader(const sp<EventHubInterface>& eventHub,
+ const sp<InputReaderPolicyInterface>& policy,
+ const sp<InputDispatcherInterface>& dispatcher) :
+ InputReader(eventHub, policy, dispatcher) {
+ }
+
+ virtual ~InstrumentedInputReader() {
+ if (mNextDevice) {
+ delete mNextDevice;
+ }
+ }
+
+ void setNextDevice(InputDevice* device) {
+ mNextDevice = device;
+ }
+
+protected:
+ virtual InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
+ if (mNextDevice) {
+ InputDevice* device = mNextDevice;
+ mNextDevice = NULL;
+ return device;
+ }
+ return InputReader::createDevice(deviceId, name, classes);
+ }
+
+ friend class InputReaderTest;
+};
+
+
+// --- InputReaderTest ---
+
+class InputReaderTest : public testing::Test {
+protected:
+ sp<FakeInputDispatcher> mFakeDispatcher;
+ sp<FakeInputReaderPolicy> mFakePolicy;
+ sp<FakeEventHub> mFakeEventHub;
+ sp<InstrumentedInputReader> mReader;
+
+ virtual void SetUp() {
+ mFakeEventHub = new FakeEventHub();
+ mFakePolicy = new FakeInputReaderPolicy();
+ mFakeDispatcher = new FakeInputDispatcher();
+
+ mReader = new InstrumentedInputReader(mFakeEventHub, mFakePolicy, mFakeDispatcher);
+ }
+
+ virtual void TearDown() {
+ mReader.clear();
+
+ mFakeDispatcher.clear();
+ mFakePolicy.clear();
+ mFakeEventHub.clear();
+ }
+
+ void addDevice(int32_t deviceId, const String8& name, uint32_t classes) {
+ mFakeEventHub->addDevice(deviceId, name, classes);
+ mFakeEventHub->finishDeviceScan();
+ mReader->loopOnce();
+ mReader->loopOnce();
+ mFakeEventHub->assertQueueIsEmpty();
+ }
+
+ FakeInputMapper* addDeviceWithFakeInputMapper(int32_t deviceId,
+ const String8& name, uint32_t classes, uint32_t sources) {
+ InputDevice* device = new InputDevice(mReader.get(), deviceId, name);
+ FakeInputMapper* mapper = new FakeInputMapper(device, sources);
+ device->addMapper(mapper);
+ mReader->setNextDevice(device);
+ addDevice(deviceId, name, classes);
+ return mapper;
+ }
+};
+
+TEST_F(InputReaderTest, GetInputConfiguration_WhenNoDevices_ReturnsDefaults) {
+ InputConfiguration config;
+ mReader->getInputConfiguration(&config);
+
+ ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
+ ASSERT_EQ(InputConfiguration::NAVIGATION_NONAV, config.navigation);
+ ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
+}
+
+TEST_F(InputReaderTest, GetInputConfiguration_WhenAlphabeticKeyboardPresent_ReturnsQwertyKeyboard) {
+ ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("keyboard"),
+ INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY));
+
+ InputConfiguration config;
+ mReader->getInputConfiguration(&config);
+
+ ASSERT_EQ(InputConfiguration::KEYBOARD_QWERTY, config.keyboard);
+ ASSERT_EQ(InputConfiguration::NAVIGATION_NONAV, config.navigation);
+ ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
+}
+
+TEST_F(InputReaderTest, GetInputConfiguration_WhenTouchScreenPresent_ReturnsFingerTouchScreen) {
+ ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("touchscreen"),
+ INPUT_DEVICE_CLASS_TOUCHSCREEN));
+
+ InputConfiguration config;
+ mReader->getInputConfiguration(&config);
+
+ ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
+ ASSERT_EQ(InputConfiguration::NAVIGATION_NONAV, config.navigation);
+ ASSERT_EQ(InputConfiguration::TOUCHSCREEN_FINGER, config.touchScreen);
+}
+
+TEST_F(InputReaderTest, GetInputConfiguration_WhenTrackballPresent_ReturnsTrackballNavigation) {
+ ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("trackball"),
+ INPUT_DEVICE_CLASS_TRACKBALL));
+
+ InputConfiguration config;
+ mReader->getInputConfiguration(&config);
+
+ ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
+ ASSERT_EQ(InputConfiguration::NAVIGATION_TRACKBALL, config.navigation);
+ ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
+}
+
+TEST_F(InputReaderTest, GetInputConfiguration_WhenDPadPresent_ReturnsDPadNavigation) {
+ ASSERT_NO_FATAL_FAILURE(addDevice(0, String8("dpad"),
+ INPUT_DEVICE_CLASS_DPAD));
+
+ InputConfiguration config;
+ mReader->getInputConfiguration(&config);
+
+ ASSERT_EQ(InputConfiguration::KEYBOARD_NOKEYS, config.keyboard);
+ ASSERT_EQ(InputConfiguration::NAVIGATION_DPAD, config.navigation);
+ ASSERT_EQ(InputConfiguration::TOUCHSCREEN_NOTOUCH, config.touchScreen);
+}
+
+TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsValid) {
+ ASSERT_NO_FATAL_FAILURE(addDevice(1, String8("keyboard"),
+ INPUT_DEVICE_CLASS_KEYBOARD));
+
+ InputDeviceInfo info;
+ status_t result = mReader->getInputDeviceInfo(1, &info);
+
+ ASSERT_EQ(OK, result);
+ ASSERT_EQ(1, info.getId());
+ ASSERT_STREQ("keyboard", info.getName().string());
+ ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, info.getKeyboardType());
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, info.getSources());
+ ASSERT_EQ(size_t(0), info.getMotionRanges().size());
+}
+
+TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsInvalid) {
+ InputDeviceInfo info;
+ status_t result = mReader->getInputDeviceInfo(-1, &info);
+
+ ASSERT_EQ(NAME_NOT_FOUND, result);
+}
+
+TEST_F(InputReaderTest, GetInputDeviceInfo_WhenDeviceIdIsIgnored) {
+ addDevice(1, String8("ignored"), 0); // no classes so device will be ignored
+
+ InputDeviceInfo info;
+ status_t result = mReader->getInputDeviceInfo(1, &info);
+
+ ASSERT_EQ(NAME_NOT_FOUND, result);
+}
+
+TEST_F(InputReaderTest, GetInputDeviceIds) {
+ ASSERT_NO_FATAL_FAILURE(addDevice(1, String8("keyboard"),
+ INPUT_DEVICE_CLASS_KEYBOARD | INPUT_DEVICE_CLASS_ALPHAKEY));
+ ASSERT_NO_FATAL_FAILURE(addDevice(2, String8("trackball"),
+ INPUT_DEVICE_CLASS_TRACKBALL));
+
+ Vector<int32_t> ids;
+ mReader->getInputDeviceIds(ids);
+
+ ASSERT_EQ(size_t(2), ids.size());
+ ASSERT_EQ(1, ids[0]);
+ ASSERT_EQ(2, ids[1]);
+}
+
+TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
+ FakeInputMapper* mapper = NULL;
+ ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
+ INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD));
+ mapper->setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
+
+ ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(0,
+ AINPUT_SOURCE_ANY, AKEYCODE_A))
+ << "Should return unknown when the device id is >= 0 but unknown.";
+
+ ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(1,
+ AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
+ << "Should return unknown when the device id is valid but the sources are not supported by the device.";
+
+ ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(1,
+ AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
+ << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
+
+ ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(-1,
+ AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
+ << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
+
+ ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(-1,
+ AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
+ << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
+}
+
+TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) {
+ FakeInputMapper* mapper = NULL;
+ ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
+ INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD));
+ mapper->setScanCodeState(KEY_A, AKEY_STATE_DOWN);
+
+ ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(0,
+ AINPUT_SOURCE_ANY, KEY_A))
+ << "Should return unknown when the device id is >= 0 but unknown.";
+
+ ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(1,
+ AINPUT_SOURCE_TRACKBALL, KEY_A))
+ << "Should return unknown when the device id is valid but the sources are not supported by the device.";
+
+ ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(1,
+ AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
+ << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
+
+ ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(-1,
+ AINPUT_SOURCE_TRACKBALL, KEY_A))
+ << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
+
+ ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(-1,
+ AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
+ << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
+}
+
+TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) {
+ FakeInputMapper* mapper = NULL;
+ ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
+ INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD));
+ mapper->setSwitchState(SW_LID, AKEY_STATE_DOWN);
+
+ ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(0,
+ AINPUT_SOURCE_ANY, SW_LID))
+ << "Should return unknown when the device id is >= 0 but unknown.";
+
+ ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(1,
+ AINPUT_SOURCE_TRACKBALL, SW_LID))
+ << "Should return unknown when the device id is valid but the sources are not supported by the device.";
+
+ ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(1,
+ AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
+ << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
+
+ ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(-1,
+ AINPUT_SOURCE_TRACKBALL, SW_LID))
+ << "Should return unknown when the device id is < 0 but the sources are not supported by any device.";
+
+ ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(-1,
+ AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
+ << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
+}
+
+TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) {
+ FakeInputMapper* mapper = NULL;
+ ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
+ INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD));
+ mapper->addSupportedKeyCode(AKEYCODE_A);
+ mapper->addSupportedKeyCode(AKEYCODE_B);
+
+ const int32_t keyCodes[4] = { AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2 };
+ uint8_t flags[4] = { 0, 0, 0, 1 };
+
+ ASSERT_FALSE(mReader->hasKeys(0, AINPUT_SOURCE_ANY, 4, keyCodes, flags))
+ << "Should return false when device id is >= 0 but unknown.";
+ ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
+
+ flags[3] = 1;
+ ASSERT_FALSE(mReader->hasKeys(1, AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
+ << "Should return false when device id is valid but the sources are not supported by the device.";
+ ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
+
+ flags[3] = 1;
+ ASSERT_TRUE(mReader->hasKeys(1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
+ << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
+ ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
+
+ flags[3] = 1;
+ ASSERT_FALSE(mReader->hasKeys(-1, AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
+ << "Should return false when the device id is < 0 but the sources are not supported by any device.";
+ ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
+
+ flags[3] = 1;
+ ASSERT_TRUE(mReader->hasKeys(-1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
+ << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
+ ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
+}
+
+TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChanged) {
+ addDevice(1, String8("ignored"), INPUT_DEVICE_CLASS_KEYBOARD);
+
+ FakeInputDispatcher::NotifyConfigurationChangedArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyConfigurationChangedWasCalled(&args));
+ ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
+}
+
+TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) {
+ FakeInputMapper* mapper = NULL;
+ ASSERT_NO_FATAL_FAILURE(mapper = addDeviceWithFakeInputMapper(1, String8("fake"),
+ INPUT_DEVICE_CLASS_KEYBOARD, AINPUT_SOURCE_KEYBOARD));
+
+ mFakeEventHub->enqueueEvent(0, 1, EV_KEY, KEY_A, AKEYCODE_A, 1, POLICY_FLAG_WAKE);
+ mReader->loopOnce();
+ ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
+
+ RawEvent event;
+ ASSERT_NO_FATAL_FAILURE(mapper->assertProcessWasCalled(&event));
+ ASSERT_EQ(0, event.when);
+ ASSERT_EQ(1, event.deviceId);
+ ASSERT_EQ(EV_KEY, event.type);
+ ASSERT_EQ(KEY_A, event.scanCode);
+ ASSERT_EQ(AKEYCODE_A, event.keyCode);
+ ASSERT_EQ(1, event.value);
+ ASSERT_EQ(POLICY_FLAG_WAKE, event.flags);
+}
+
+
+// --- InputDeviceTest ---
+
+class InputDeviceTest : public testing::Test {
+protected:
+ static const char* DEVICE_NAME;
+ static const int32_t DEVICE_ID;
+
+ sp<FakeEventHub> mFakeEventHub;
+ sp<FakeInputReaderPolicy> mFakePolicy;
+ sp<FakeInputDispatcher> mFakeDispatcher;
+ FakeInputReaderContext* mFakeContext;
+
+ InputDevice* mDevice;
+
+ virtual void SetUp() {
+ mFakeEventHub = new FakeEventHub();
+ mFakePolicy = new FakeInputReaderPolicy();
+ mFakeDispatcher = new FakeInputDispatcher();
+ mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeDispatcher);
+
+ mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME));
+ }
+
+ virtual void TearDown() {
+ delete mDevice;
+
+ delete mFakeContext;
+ mFakeDispatcher.clear();
+ mFakePolicy.clear();
+ mFakeEventHub.clear();
+ }
+};
+
+const char* InputDeviceTest::DEVICE_NAME = "device";
+const int32_t InputDeviceTest::DEVICE_ID = 1;
+
+TEST_F(InputDeviceTest, ImmutableProperties) {
+ ASSERT_EQ(DEVICE_ID, mDevice->getId());
+ ASSERT_STREQ(DEVICE_NAME, mDevice->getName());
+}
+
+TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
+ // Configuration.
+ mDevice->configure();
+
+ // Metadata.
+ ASSERT_TRUE(mDevice->isIgnored());
+ ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mDevice->getSources());
+
+ InputDeviceInfo info;
+ mDevice->getDeviceInfo(&info);
+ ASSERT_EQ(DEVICE_ID, info.getId());
+ ASSERT_STREQ(DEVICE_NAME, info.getName().string());
+ ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NONE, info.getKeyboardType());
+ ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, info.getSources());
+
+ // State queries.
+ ASSERT_EQ(0, mDevice->getMetaState());
+
+ ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, 0))
+ << "Ignored device should return unknown key code state.";
+ ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 0))
+ << "Ignored device should return unknown scan code state.";
+ ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 0))
+ << "Ignored device should return unknown switch state.";
+
+ const int32_t keyCodes[2] = { AKEYCODE_A, AKEYCODE_B };
+ uint8_t flags[2] = { 0, 1 };
+ ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, 2, keyCodes, flags))
+ << "Ignored device should never mark any key codes.";
+ ASSERT_EQ(0, flags[0]) << "Flag for unsupported key should be unchanged.";
+ ASSERT_EQ(1, flags[1]) << "Flag for unsupported key should be unchanged.";
+
+ // Reset.
+ mDevice->reset();
+}
+
+TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRequestsToMappers) {
+ // Configuration.
+ InputDeviceCalibration calibration;
+ calibration.addProperty(String8("key"), String8("value"));
+ mFakePolicy->addInputDeviceCalibration(String8(DEVICE_NAME), calibration);
+
+ FakeInputMapper* mapper1 = new FakeInputMapper(mDevice, AINPUT_SOURCE_KEYBOARD);
+ mapper1->setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+ mapper1->setMetaState(AMETA_ALT_ON);
+ mapper1->addSupportedKeyCode(AKEYCODE_A);
+ mapper1->addSupportedKeyCode(AKEYCODE_B);
+ mapper1->setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
+ mapper1->setKeyCodeState(AKEYCODE_B, AKEY_STATE_UP);
+ mapper1->setScanCodeState(2, AKEY_STATE_DOWN);
+ mapper1->setScanCodeState(3, AKEY_STATE_UP);
+ mapper1->setSwitchState(4, AKEY_STATE_DOWN);
+ mDevice->addMapper(mapper1);
+
+ FakeInputMapper* mapper2 = new FakeInputMapper(mDevice, AINPUT_SOURCE_TOUCHSCREEN);
+ mapper2->setMetaState(AMETA_SHIFT_ON);
+ mDevice->addMapper(mapper2);
+
+ mDevice->configure();
+
+ String8 propertyValue;
+ ASSERT_TRUE(mDevice->getCalibration().tryGetProperty(String8("key"), propertyValue))
+ << "Device should have read calibration during configuration phase.";
+ ASSERT_STREQ("value", propertyValue.string());
+
+ ASSERT_NO_FATAL_FAILURE(mapper1->assertConfigureWasCalled());
+ ASSERT_NO_FATAL_FAILURE(mapper2->assertConfigureWasCalled());
+
+ // Metadata.
+ ASSERT_FALSE(mDevice->isIgnored());
+ ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), mDevice->getSources());
+
+ InputDeviceInfo info;
+ mDevice->getDeviceInfo(&info);
+ ASSERT_EQ(DEVICE_ID, info.getId());
+ ASSERT_STREQ(DEVICE_NAME, info.getName().string());
+ ASSERT_EQ(AINPUT_KEYBOARD_TYPE_ALPHABETIC, info.getKeyboardType());
+ ASSERT_EQ(uint32_t(AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TOUCHSCREEN), info.getSources());
+
+ // State queries.
+ ASSERT_EQ(AMETA_ALT_ON | AMETA_SHIFT_ON, mDevice->getMetaState())
+ << "Should query mappers and combine meta states.";
+
+ ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
+ << "Should return unknown key code state when source not supported.";
+ ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getScanCodeState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
+ << "Should return unknown scan code state when source not supported.";
+ ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
+ << "Should return unknown switch state when source not supported.";
+
+ ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getKeyCodeState(AINPUT_SOURCE_KEYBOARD, AKEYCODE_A))
+ << "Should query mapper when source is supported.";
+ ASSERT_EQ(AKEY_STATE_UP, mDevice->getScanCodeState(AINPUT_SOURCE_KEYBOARD, 3))
+ << "Should query mapper when source is supported.";
+ ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 4))
+ << "Should query mapper when source is supported.";
+
+ const int32_t keyCodes[4] = { AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2 };
+ uint8_t flags[4] = { 0, 0, 0, 1 };
+ ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
+ << "Should do nothing when source is unsupported.";
+ ASSERT_EQ(0, flags[0]) << "Flag should be unchanged when source is unsupported.";
+ ASSERT_EQ(0, flags[1]) << "Flag should be unchanged when source is unsupported.";
+ ASSERT_EQ(0, flags[2]) << "Flag should be unchanged when source is unsupported.";
+ ASSERT_EQ(1, flags[3]) << "Flag should be unchanged when source is unsupported.";
+
+ ASSERT_TRUE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, 4, keyCodes, flags))
+ << "Should query mapper when source is supported.";
+ ASSERT_EQ(1, flags[0]) << "Flag for supported key should be set.";
+ ASSERT_EQ(1, flags[1]) << "Flag for supported key should be set.";
+ ASSERT_EQ(0, flags[2]) << "Flag for unsupported key should be unchanged.";
+ ASSERT_EQ(1, flags[3]) << "Flag for unsupported key should be unchanged.";
+
+ // Event handling.
+ RawEvent event;
+ mDevice->process(&event);
+
+ ASSERT_NO_FATAL_FAILURE(mapper1->assertProcessWasCalled());
+ ASSERT_NO_FATAL_FAILURE(mapper2->assertProcessWasCalled());
+
+ // Reset.
+ mDevice->reset();
+
+ ASSERT_NO_FATAL_FAILURE(mapper1->assertResetWasCalled());
+ ASSERT_NO_FATAL_FAILURE(mapper2->assertResetWasCalled());
+}
+
+
+// --- InputMapperTest ---
+
+class InputMapperTest : public testing::Test {
+protected:
+ static const char* DEVICE_NAME;
+ static const int32_t DEVICE_ID;
+
+ sp<FakeEventHub> mFakeEventHub;
+ sp<FakeInputReaderPolicy> mFakePolicy;
+ sp<FakeInputDispatcher> mFakeDispatcher;
+ FakeInputReaderContext* mFakeContext;
+ InputDevice* mDevice;
+
+ virtual void SetUp() {
+ mFakeEventHub = new FakeEventHub();
+ mFakePolicy = new FakeInputReaderPolicy();
+ mFakeDispatcher = new FakeInputDispatcher();
+ mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeDispatcher);
+ mDevice = new InputDevice(mFakeContext, DEVICE_ID, String8(DEVICE_NAME));
+
+ mFakeEventHub->addDevice(DEVICE_ID, String8(DEVICE_NAME), 0);
+ }
+
+ virtual void TearDown() {
+ delete mDevice;
+ delete mFakeContext;
+ mFakeDispatcher.clear();
+ mFakePolicy.clear();
+ mFakeEventHub.clear();
+ }
+
+ void prepareCalibration(const char* key, const char* value) {
+ mFakePolicy->addInputDeviceCalibrationProperty(String8(DEVICE_NAME),
+ String8(key), String8(value));
+ }
+
+ void addMapperAndConfigure(InputMapper* mapper) {
+ mDevice->addMapper(mapper);
+ mDevice->configure();
+ }
+
+ static void process(InputMapper* mapper, nsecs_t when, int32_t deviceId, int32_t type,
+ int32_t scanCode, int32_t keyCode, int32_t value, uint32_t flags) {
+ RawEvent event;
+ event.when = when;
+ event.deviceId = deviceId;
+ event.type = type;
+ event.scanCode = scanCode;
+ event.keyCode = keyCode;
+ event.value = value;
+ event.flags = flags;
+ mapper->process(&event);
+ }
+
+ static void assertMotionRange(const InputDeviceInfo& info,
+ int32_t rangeType, float min, float max, float flat, float fuzz) {
+ const InputDeviceInfo::MotionRange* range = info.getMotionRange(rangeType);
+ ASSERT_TRUE(range != NULL) << "Range: " << rangeType;
+ ASSERT_NEAR(min, range->min, EPSILON) << "Range: " << rangeType;
+ ASSERT_NEAR(max, range->max, EPSILON) << "Range: " << rangeType;
+ ASSERT_NEAR(flat, range->flat, EPSILON) << "Range: " << rangeType;
+ ASSERT_NEAR(fuzz, range->fuzz, EPSILON) << "Range: " << rangeType;
+ }
+
+ static void assertPointerCoords(const PointerCoords& coords,
+ float x, float y, float pressure, float size,
+ float touchMajor, float touchMinor, float toolMajor, float toolMinor,
+ float orientation) {
+ ASSERT_NEAR(x, coords.x, 1);
+ ASSERT_NEAR(y, coords.y, 1);
+ ASSERT_NEAR(pressure, coords.pressure, EPSILON);
+ ASSERT_NEAR(size, coords.size, EPSILON);
+ ASSERT_NEAR(touchMajor, coords.touchMajor, 1);
+ ASSERT_NEAR(touchMinor, coords.touchMinor, 1);
+ ASSERT_NEAR(toolMajor, coords.toolMajor, 1);
+ ASSERT_NEAR(toolMinor, coords.toolMinor, 1);
+ ASSERT_NEAR(orientation, coords.orientation, EPSILON);
+ }
+};
+
+const char* InputMapperTest::DEVICE_NAME = "device";
+const int32_t InputMapperTest::DEVICE_ID = 1;
+
+
+// --- SwitchInputMapperTest ---
+
+class SwitchInputMapperTest : public InputMapperTest {
+protected:
+};
+
+TEST_F(SwitchInputMapperTest, GetSources) {
+ SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
+ addMapperAndConfigure(mapper);
+
+ ASSERT_EQ(uint32_t(0), mapper->getSources());
+}
+
+TEST_F(SwitchInputMapperTest, GetSwitchState) {
+ SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
+ addMapperAndConfigure(mapper);
+
+ mFakeEventHub->setSwitchState(DEVICE_ID, SW_LID, 1);
+ ASSERT_EQ(1, mapper->getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
+
+ mFakeEventHub->setSwitchState(DEVICE_ID, SW_LID, 0);
+ ASSERT_EQ(0, mapper->getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
+}
+
+TEST_F(SwitchInputMapperTest, Process) {
+ SwitchInputMapper* mapper = new SwitchInputMapper(mDevice);
+ addMapperAndConfigure(mapper);
+
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SW, SW_LID, 0, 1, 0);
+
+ FakeInputDispatcher::NotifySwitchArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifySwitchWasCalled(&args));
+ ASSERT_EQ(ARBITRARY_TIME, args.when);
+ ASSERT_EQ(SW_LID, args.switchCode);
+ ASSERT_EQ(1, args.switchValue);
+ ASSERT_EQ(uint32_t(0), args.policyFlags);
+}
+
+
+// --- KeyboardInputMapperTest ---
+
+class KeyboardInputMapperTest : public InputMapperTest {
+protected:
+ void testDPadKeyRotation(KeyboardInputMapper* mapper,
+ int32_t originalScanCode, int32_t originalKeyCode, int32_t rotatedKeyCode);
+};
+
+void KeyboardInputMapperTest::testDPadKeyRotation(KeyboardInputMapper* mapper,
+ int32_t originalScanCode, int32_t originalKeyCode, int32_t rotatedKeyCode) {
+ FakeInputDispatcher::NotifyKeyArgs args;
+
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, originalKeyCode, 1, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+ ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
+ ASSERT_EQ(originalScanCode, args.scanCode);
+ ASSERT_EQ(rotatedKeyCode, args.keyCode);
+
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, originalScanCode, originalKeyCode, 0, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+ ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+ ASSERT_EQ(originalScanCode, args.scanCode);
+ ASSERT_EQ(rotatedKeyCode, args.keyCode);
+}
+
+
+TEST_F(KeyboardInputMapperTest, GetSources) {
+ KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, -1,
+ AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+ addMapperAndConfigure(mapper);
+
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, mapper->getSources());
+}
+
+TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) {
+ KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, -1,
+ AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+ addMapperAndConfigure(mapper);
+
+ // Key down.
+ process(mapper, ARBITRARY_TIME, DEVICE_ID,
+ EV_KEY, KEY_HOME, AKEYCODE_HOME, 1, POLICY_FLAG_WAKE);
+ FakeInputDispatcher::NotifyKeyArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+ ASSERT_EQ(DEVICE_ID, args.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+ ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
+ ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
+ ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
+ ASSERT_EQ(KEY_HOME, args.scanCode);
+ ASSERT_EQ(AMETA_NONE, args.metaState);
+ ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
+ ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
+ ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+
+ // Key up.
+ process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
+ EV_KEY, KEY_HOME, AKEYCODE_HOME, 0, POLICY_FLAG_WAKE);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+ ASSERT_EQ(DEVICE_ID, args.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+ ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
+ ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+ ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
+ ASSERT_EQ(KEY_HOME, args.scanCode);
+ ASSERT_EQ(AMETA_NONE, args.metaState);
+ ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
+ ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
+ ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+}
+
+TEST_F(KeyboardInputMapperTest, Reset_WhenKeysAreNotDown_DoesNotSynthesizeKeyUp) {
+ KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, -1,
+ AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+ addMapperAndConfigure(mapper);
+
+ // Key down.
+ process(mapper, ARBITRARY_TIME, DEVICE_ID,
+ EV_KEY, KEY_HOME, AKEYCODE_HOME, 1, POLICY_FLAG_WAKE);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+ // Key up.
+ process(mapper, ARBITRARY_TIME, DEVICE_ID,
+ EV_KEY, KEY_HOME, AKEYCODE_HOME, 0, POLICY_FLAG_WAKE);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+ // Reset. Since no keys still down, should not synthesize any key ups.
+ mapper->reset();
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
+}
+
+TEST_F(KeyboardInputMapperTest, Reset_WhenKeysAreDown_SynthesizesKeyUps) {
+ KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, -1,
+ AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+ addMapperAndConfigure(mapper);
+
+ // Metakey down.
+ process(mapper, ARBITRARY_TIME, DEVICE_ID,
+ EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 1, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+ // Key down.
+ process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
+ EV_KEY, KEY_A, AKEYCODE_A, 1, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+ // Reset. Since two keys are still down, should synthesize two key ups in reverse order.
+ mapper->reset();
+
+ FakeInputDispatcher::NotifyKeyArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+ ASSERT_EQ(DEVICE_ID, args.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+ ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+ ASSERT_EQ(AKEYCODE_A, args.keyCode);
+ ASSERT_EQ(KEY_A, args.scanCode);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+ ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
+ ASSERT_EQ(uint32_t(0), args.policyFlags);
+ ASSERT_EQ(ARBITRARY_TIME + 1, args.downTime);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+ ASSERT_EQ(DEVICE_ID, args.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+ ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+ ASSERT_EQ(AKEYCODE_SHIFT_LEFT, args.keyCode);
+ ASSERT_EQ(KEY_LEFTSHIFT, args.scanCode);
+ ASSERT_EQ(AMETA_NONE, args.metaState);
+ ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM, args.flags);
+ ASSERT_EQ(uint32_t(0), args.policyFlags);
+ ASSERT_EQ(ARBITRARY_TIME + 1, args.downTime);
+
+ // And that's it.
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
+}
+
+TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) {
+ KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, -1,
+ AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+ addMapperAndConfigure(mapper);
+
+ // Initial metastate.
+ ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
+
+ // Metakey down.
+ process(mapper, ARBITRARY_TIME, DEVICE_ID,
+ EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 1, 0);
+ FakeInputDispatcher::NotifyKeyArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
+ ASSERT_NO_FATAL_FAILURE(mFakeContext->assertUpdateGlobalMetaStateWasCalled());
+
+ // Key down.
+ process(mapper, ARBITRARY_TIME + 1, DEVICE_ID,
+ EV_KEY, KEY_A, AKEYCODE_A, 1, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
+
+ // Key up.
+ process(mapper, ARBITRARY_TIME + 2, DEVICE_ID,
+ EV_KEY, KEY_A, AKEYCODE_A, 0, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper->getMetaState());
+
+ // Metakey up.
+ process(mapper, ARBITRARY_TIME + 3, DEVICE_ID,
+ EV_KEY, KEY_LEFTSHIFT, AKEYCODE_SHIFT_LEFT, 0, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+ ASSERT_EQ(AMETA_NONE, args.metaState);
+ ASSERT_EQ(AMETA_NONE, mapper->getMetaState());
+ ASSERT_NO_FATAL_FAILURE(mFakeContext->assertUpdateGlobalMetaStateWasCalled());
+}
+
+TEST_F(KeyboardInputMapperTest, Process_WhenNotAttachedToDisplay_ShouldNotRotateDPad) {
+ KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, -1,
+ AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+ addMapperAndConfigure(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
+}
+
+TEST_F(KeyboardInputMapperTest, Process_WhenAttachedToDisplay_ShouldRotateDPad) {
+ KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, DISPLAY_ID,
+ AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+ addMapperAndConfigure(mapper);
+
+ mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ DISPLAY_WIDTH, DISPLAY_HEIGHT,
+ InputReaderPolicyInterface::ROTATION_0);
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_UP));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_RIGHT));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_DOWN));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_LEFT));
+
+ mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ DISPLAY_WIDTH, DISPLAY_HEIGHT,
+ InputReaderPolicyInterface::ROTATION_90);
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN));
+
+ mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ DISPLAY_WIDTH, DISPLAY_HEIGHT,
+ InputReaderPolicyInterface::ROTATION_180);
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_DOWN));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_LEFT));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_UP));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_RIGHT));
+
+ mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ DISPLAY_WIDTH, DISPLAY_HEIGHT,
+ InputReaderPolicyInterface::ROTATION_270);
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_UP, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_RIGHT));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_RIGHT, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_DOWN));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_DOWN, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_LEFT));
+ ASSERT_NO_FATAL_FAILURE(testDPadKeyRotation(mapper,
+ KEY_LEFT, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_UP));
+
+ // Special case: if orientation changes while key is down, we still emit the same keycode
+ // in the key up as we did in the key down.
+ FakeInputDispatcher::NotifyKeyArgs args;
+
+ mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ DISPLAY_WIDTH, DISPLAY_HEIGHT,
+ InputReaderPolicyInterface::ROTATION_270);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, AKEYCODE_DPAD_UP, 1, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+ ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
+ ASSERT_EQ(KEY_UP, args.scanCode);
+ ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
+
+ mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ DISPLAY_WIDTH, DISPLAY_HEIGHT,
+ InputReaderPolicyInterface::ROTATION_180);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, KEY_UP, AKEYCODE_DPAD_UP, 0, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+ ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+ ASSERT_EQ(KEY_UP, args.scanCode);
+ ASSERT_EQ(AKEYCODE_DPAD_RIGHT, args.keyCode);
+}
+
+TEST_F(KeyboardInputMapperTest, GetKeyCodeState) {
+ KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, -1,
+ AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+ addMapperAndConfigure(mapper);
+
+ mFakeEventHub->setKeyCodeState(DEVICE_ID, AKEYCODE_A, 1);
+ ASSERT_EQ(1, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
+
+ mFakeEventHub->setKeyCodeState(DEVICE_ID, AKEYCODE_A, 0);
+ ASSERT_EQ(0, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
+}
+
+TEST_F(KeyboardInputMapperTest, GetScanCodeState) {
+ KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, -1,
+ AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+ addMapperAndConfigure(mapper);
+
+ mFakeEventHub->setScanCodeState(DEVICE_ID, KEY_A, 1);
+ ASSERT_EQ(1, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
+
+ mFakeEventHub->setScanCodeState(DEVICE_ID, KEY_A, 0);
+ ASSERT_EQ(0, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
+}
+
+TEST_F(KeyboardInputMapperTest, MarkSupportedKeyCodes) {
+ KeyboardInputMapper* mapper = new KeyboardInputMapper(mDevice, -1,
+ AINPUT_SOURCE_KEYBOARD, AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+ addMapperAndConfigure(mapper);
+
+ mFakeEventHub->addKey(DEVICE_ID, KEY_A, AKEYCODE_A, 0);
+
+ const int32_t keyCodes[2] = { AKEYCODE_A, AKEYCODE_B };
+ uint8_t flags[2] = { 0, 0 };
+ ASSERT_TRUE(mapper->markSupportedKeyCodes(AINPUT_SOURCE_ANY, 1, keyCodes, flags));
+ ASSERT_TRUE(flags[0]);
+ ASSERT_FALSE(flags[1]);
+}
+
+
+// --- TrackballInputMapperTest ---
+
+class TrackballInputMapperTest : public InputMapperTest {
+protected:
+ static const int32_t TRACKBALL_MOVEMENT_THRESHOLD;
+
+ void testMotionRotation(TrackballInputMapper* mapper,
+ int32_t originalX, int32_t originalY, int32_t rotatedX, int32_t rotatedY);
+};
+
+const int32_t TrackballInputMapperTest::TRACKBALL_MOVEMENT_THRESHOLD = 6;
+
+void TrackballInputMapperTest::testMotionRotation(TrackballInputMapper* mapper,
+ int32_t originalX, int32_t originalY, int32_t rotatedX, int32_t rotatedY) {
+ FakeInputDispatcher::NotifyMotionArgs args;
+
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, originalX, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, originalY, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+ float(rotatedX) / TRACKBALL_MOVEMENT_THRESHOLD,
+ float(rotatedY) / TRACKBALL_MOVEMENT_THRESHOLD,
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+}
+
+TEST_F(TrackballInputMapperTest, GetSources) {
+ TrackballInputMapper* mapper = new TrackballInputMapper(mDevice, -1);
+ addMapperAndConfigure(mapper);
+
+ ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, mapper->getSources());
+}
+
+TEST_F(TrackballInputMapperTest, PopulateDeviceInfo) {
+ TrackballInputMapper* mapper = new TrackballInputMapper(mDevice, -1);
+ addMapperAndConfigure(mapper);
+
+ InputDeviceInfo info;
+ mapper->populateDeviceInfo(&info);
+
+ ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_X,
+ -1.0f, 1.0f, 0.0f, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD));
+ ASSERT_NO_FATAL_FAILURE(assertMotionRange(info, AINPUT_MOTION_RANGE_Y,
+ -1.0f, 1.0f, 0.0f, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD));
+}
+
+TEST_F(TrackballInputMapperTest, Process_ShouldSetAllFieldsAndIncludeGlobalMetaState) {
+ TrackballInputMapper* mapper = new TrackballInputMapper(mDevice, -1);
+ addMapperAndConfigure(mapper);
+
+ mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+
+ FakeInputDispatcher::NotifyMotionArgs args;
+
+ // Button press.
+ // Mostly testing non x/y behavior here so we don't need to check again elsewhere.
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
+ ASSERT_EQ(DEVICE_ID, args.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, args.source);
+ ASSERT_EQ(uint32_t(0), args.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
+ ASSERT_EQ(0, args.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+ ASSERT_EQ(0, args.edgeFlags);
+ ASSERT_EQ(uint32_t(1), args.pointerCount);
+ ASSERT_EQ(0, args.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+ 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+ ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.xPrecision);
+ ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.yPrecision);
+ ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+
+ // Button release. Should have same down time.
+ process(mapper, ARBITRARY_TIME + 1, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(ARBITRARY_TIME + 1, args.eventTime);
+ ASSERT_EQ(DEVICE_ID, args.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TRACKBALL, args.source);
+ ASSERT_EQ(uint32_t(0), args.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
+ ASSERT_EQ(0, args.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+ ASSERT_EQ(0, args.edgeFlags);
+ ASSERT_EQ(uint32_t(1), args.pointerCount);
+ ASSERT_EQ(0, args.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+ ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.xPrecision);
+ ASSERT_EQ(TRACKBALL_MOVEMENT_THRESHOLD, args.yPrecision);
+ ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+}
+
+TEST_F(TrackballInputMapperTest, Process_ShouldHandleIndependentXYUpdates) {
+ TrackballInputMapper* mapper = new TrackballInputMapper(mDevice, -1);
+ addMapperAndConfigure(mapper);
+
+ FakeInputDispatcher::NotifyMotionArgs args;
+
+ // Motion in X but not Y.
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 1, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+ 1.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+
+ // Motion in Y but not X.
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, -2, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
+ ASSERT_NEAR(0.0f, args.pointerCoords[0].x, EPSILON);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+ 0.0f, -2.0f / TRACKBALL_MOVEMENT_THRESHOLD, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+}
+
+TEST_F(TrackballInputMapperTest, Process_ShouldHandleIndependentButtonUpdates) {
+ TrackballInputMapper* mapper = new TrackballInputMapper(mDevice, -1);
+ addMapperAndConfigure(mapper);
+
+ FakeInputDispatcher::NotifyMotionArgs args;
+
+ // Button press without following sync.
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+ 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+
+ // Button release without following sync.
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+}
+
+TEST_F(TrackballInputMapperTest, Process_ShouldHandleCombinedXYAndButtonUpdates) {
+ TrackballInputMapper* mapper = new TrackballInputMapper(mDevice, -1);
+ addMapperAndConfigure(mapper);
+
+ FakeInputDispatcher::NotifyMotionArgs args;
+
+ // Combined X, Y and Button.
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 1, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, -2, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+ 1.0f / TRACKBALL_MOVEMENT_THRESHOLD, -2.0f / TRACKBALL_MOVEMENT_THRESHOLD,
+ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+
+ // Move X, Y a bit while pressed.
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_X, 0, 2, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_REL, REL_Y, 0, 1, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, args.action);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+ 2.0f / TRACKBALL_MOVEMENT_THRESHOLD, 1.0f / TRACKBALL_MOVEMENT_THRESHOLD,
+ 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+
+ // Release Button.
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+}
+
+TEST_F(TrackballInputMapperTest, Reset_WhenButtonIsNotDown_ShouldNotSynthesizeButtonUp) {
+ TrackballInputMapper* mapper = new TrackballInputMapper(mDevice, -1);
+ addMapperAndConfigure(mapper);
+
+ FakeInputDispatcher::NotifyMotionArgs args;
+
+ // Button press.
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+
+ // Button release.
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 0, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+
+ // Reset. Should not synthesize button up since button is not pressed.
+ mapper->reset();
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
+}
+
+TEST_F(TrackballInputMapperTest, Reset_WhenButtonIsDown_ShouldSynthesizeButtonUp) {
+ TrackballInputMapper* mapper = new TrackballInputMapper(mDevice, -1);
+ addMapperAndConfigure(mapper);
+
+ FakeInputDispatcher::NotifyMotionArgs args;
+
+ // Button press.
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_MOUSE, 0, 1, 0);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+
+ // Reset. Should synthesize button up.
+ mapper->reset();
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_UP, args.action);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f));
+}
+
+TEST_F(TrackballInputMapperTest, Process_WhenNotAttachedToDisplay_ShouldNotRotateMotions) {
+ TrackballInputMapper* mapper = new TrackballInputMapper(mDevice, -1);
+ addMapperAndConfigure(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, 1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, 1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 1, 0));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, 1, -1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, 0, -1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, -1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, -1, 0));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, 1));
+}
+
+TEST_F(TrackballInputMapperTest, Process_WhenAttachedToDisplay_ShouldRotateMotions) {
+ TrackballInputMapper* mapper = new TrackballInputMapper(mDevice, DISPLAY_ID);
+ addMapperAndConfigure(mapper);
+
+ mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ DISPLAY_WIDTH, DISPLAY_HEIGHT,
+ InputReaderPolicyInterface::ROTATION_0);
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, 1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, 1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 1, 0));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, 1, -1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, 0, -1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, -1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, -1, 0));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, 1));
+
+ mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ DISPLAY_WIDTH, DISPLAY_HEIGHT,
+ InputReaderPolicyInterface::ROTATION_90);
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 1, 0));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, 1, -1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 0, -1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, -1, -1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, -1, 0));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, -1, 1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 0, 1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, 1, 1));
+
+ mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ DISPLAY_WIDTH, DISPLAY_HEIGHT,
+ InputReaderPolicyInterface::ROTATION_180);
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, 0, -1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, -1, -1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, -1, 0));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, -1, 1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, 0, 1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, 1, 1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 1, 0));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, 1, -1));
+
+ mFakePolicy->setDisplayInfo(DISPLAY_ID,
+ DISPLAY_WIDTH, DISPLAY_HEIGHT,
+ InputReaderPolicyInterface::ROTATION_270);
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, 1, -1, 0));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 1, -1, 1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, 0, 0, 1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 1, -1, 1, 1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, 0, -1, 1, 0));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, -1, 1, -1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 0, 0, -1));
+ ASSERT_NO_FATAL_FAILURE(testMotionRotation(mapper, -1, 1, -1, -1));
+}
+
+
+// --- TouchInputMapperTest ---
+
+class TouchInputMapperTest : public InputMapperTest {
+protected:
+ static const int32_t RAW_X_MIN;
+ static const int32_t RAW_X_MAX;
+ static const int32_t RAW_Y_MIN;
+ static const int32_t RAW_Y_MAX;
+ static const int32_t RAW_TOUCH_MIN;
+ static const int32_t RAW_TOUCH_MAX;
+ static const int32_t RAW_TOOL_MIN;
+ static const int32_t RAW_TOOL_MAX;
+ static const int32_t RAW_PRESSURE_MIN;
+ static const int32_t RAW_PRESSURE_MAX;
+ static const int32_t RAW_ORIENTATION_MIN;
+ static const int32_t RAW_ORIENTATION_MAX;
+ static const int32_t RAW_ID_MIN;
+ static const int32_t RAW_ID_MAX;
+ static const float X_PRECISION;
+ static const float Y_PRECISION;
+
+ static const VirtualKeyDefinition VIRTUAL_KEYS[2];
+
+ enum Axes {
+ POSITION = 1 << 0,
+ TOUCH = 1 << 1,
+ TOOL = 1 << 2,
+ PRESSURE = 1 << 3,
+ ORIENTATION = 1 << 4,
+ MINOR = 1 << 5,
+ ID = 1 << 6,
+ };
+
+ void prepareDisplay(int32_t orientation);
+ void prepareVirtualKeys();
+ int32_t toRawX(float displayX);
+ int32_t toRawY(float displayY);
+ float toDisplayX(int32_t rawX);
+ float toDisplayY(int32_t rawY);
+};
+
+const int32_t TouchInputMapperTest::RAW_X_MIN = 25;
+const int32_t TouchInputMapperTest::RAW_X_MAX = 1020;
+const int32_t TouchInputMapperTest::RAW_Y_MIN = 30;
+const int32_t TouchInputMapperTest::RAW_Y_MAX = 1010;
+const int32_t TouchInputMapperTest::RAW_TOUCH_MIN = 0;
+const int32_t TouchInputMapperTest::RAW_TOUCH_MAX = 31;
+const int32_t TouchInputMapperTest::RAW_TOOL_MIN = 0;
+const int32_t TouchInputMapperTest::RAW_TOOL_MAX = 15;
+const int32_t TouchInputMapperTest::RAW_PRESSURE_MIN = RAW_TOUCH_MIN;
+const int32_t TouchInputMapperTest::RAW_PRESSURE_MAX = RAW_TOUCH_MAX;
+const int32_t TouchInputMapperTest::RAW_ORIENTATION_MIN = -7;
+const int32_t TouchInputMapperTest::RAW_ORIENTATION_MAX = 7;
+const int32_t TouchInputMapperTest::RAW_ID_MIN = 0;
+const int32_t TouchInputMapperTest::RAW_ID_MAX = 9;
+const float TouchInputMapperTest::X_PRECISION = float(RAW_X_MAX - RAW_X_MIN) / DISPLAY_WIDTH;
+const float TouchInputMapperTest::Y_PRECISION = float(RAW_Y_MAX - RAW_Y_MIN) / DISPLAY_HEIGHT;
+
+const VirtualKeyDefinition TouchInputMapperTest::VIRTUAL_KEYS[2] = {
+ { KEY_HOME, 60, DISPLAY_HEIGHT + 15, 20, 20 },
+ { KEY_MENU, DISPLAY_HEIGHT - 60, DISPLAY_WIDTH + 15, 20, 20 },
+};
+
+void TouchInputMapperTest::prepareDisplay(int32_t orientation) {
+ mFakePolicy->setDisplayInfo(DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT, orientation);
+}
+
+void TouchInputMapperTest::prepareVirtualKeys() {
+ mFakePolicy->addVirtualKeyDefinition(String8(DEVICE_NAME), VIRTUAL_KEYS[0]);
+ mFakePolicy->addVirtualKeyDefinition(String8(DEVICE_NAME), VIRTUAL_KEYS[1]);
+ mFakeEventHub->addKey(DEVICE_ID, KEY_HOME, AKEYCODE_HOME, POLICY_FLAG_WAKE);
+ mFakeEventHub->addKey(DEVICE_ID, KEY_MENU, AKEYCODE_MENU, POLICY_FLAG_WAKE);
+}
+
+int32_t TouchInputMapperTest::toRawX(float displayX) {
+ return int32_t(displayX * (RAW_X_MAX - RAW_X_MIN) / DISPLAY_WIDTH + RAW_X_MIN);
+}
+
+int32_t TouchInputMapperTest::toRawY(float displayY) {
+ return int32_t(displayY * (RAW_Y_MAX - RAW_Y_MIN) / DISPLAY_HEIGHT + RAW_Y_MIN);
+}
+
+float TouchInputMapperTest::toDisplayX(int32_t rawX) {
+ return float(rawX - RAW_X_MIN) * DISPLAY_WIDTH / (RAW_X_MAX - RAW_X_MIN);
+}
+
+float TouchInputMapperTest::toDisplayY(int32_t rawY) {
+ return float(rawY - RAW_Y_MIN) * DISPLAY_HEIGHT / (RAW_Y_MAX - RAW_Y_MIN);
+}
+
+
+// --- SingleTouchInputMapperTest ---
+
+class SingleTouchInputMapperTest : public TouchInputMapperTest {
+protected:
+ void prepareAxes(int axes);
+
+ void processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y);
+ void processMove(SingleTouchInputMapper* mapper, int32_t x, int32_t y);
+ void processUp(SingleTouchInputMapper* mappery);
+ void processPressure(SingleTouchInputMapper* mapper, int32_t pressure);
+ void processToolMajor(SingleTouchInputMapper* mapper, int32_t toolMajor);
+ void processSync(SingleTouchInputMapper* mapper);
+};
+
+void SingleTouchInputMapperTest::prepareAxes(int axes) {
+ if (axes & POSITION) {
+ mFakeEventHub->addAxis(DEVICE_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
+ mFakeEventHub->addAxis(DEVICE_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
+ }
+ if (axes & PRESSURE) {
+ mFakeEventHub->addAxis(DEVICE_ID, ABS_PRESSURE, RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0);
+ }
+ if (axes & TOOL) {
+ mFakeEventHub->addAxis(DEVICE_ID, ABS_TOOL_WIDTH, RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0);
+ }
+}
+
+void SingleTouchInputMapperTest::processDown(SingleTouchInputMapper* mapper, int32_t x, int32_t y) {
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_TOUCH, 0, 1, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_X, 0, x, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_Y, 0, y, 0);
+}
+
+void SingleTouchInputMapperTest::processMove(SingleTouchInputMapper* mapper, int32_t x, int32_t y) {
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_X, 0, x, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_Y, 0, y, 0);
+}
+
+void SingleTouchInputMapperTest::processUp(SingleTouchInputMapper* mapper) {
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_KEY, BTN_TOUCH, 0, 0, 0);
+}
+
+void SingleTouchInputMapperTest::processPressure(
+ SingleTouchInputMapper* mapper, int32_t pressure) {
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_PRESSURE, 0, pressure, 0);
+}
+
+void SingleTouchInputMapperTest::processToolMajor(
+ SingleTouchInputMapper* mapper, int32_t toolMajor) {
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_TOOL_WIDTH, 0, toolMajor, 0);
+}
+
+void SingleTouchInputMapperTest::processSync(SingleTouchInputMapper* mapper) {
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
+}
+
+
+TEST_F(SingleTouchInputMapperTest, GetSources_WhenNotAttachedToADisplay_ReturnsTouchPad) {
+ SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice, -1);
+ prepareAxes(POSITION);
+ addMapperAndConfigure(mapper);
+
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper->getSources());
+}
+
+TEST_F(SingleTouchInputMapperTest, GetSources_WhenAttachedToADisplay_ReturnsTouchScreen) {
+ SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice, DISPLAY_ID);
+ prepareAxes(POSITION);
+ addMapperAndConfigure(mapper);
+
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper->getSources());
+}
+
+TEST_F(SingleTouchInputMapperTest, GetKeyCodeState) {
+ SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice, DISPLAY_ID);
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
+ prepareAxes(POSITION);
+ prepareVirtualKeys();
+ addMapperAndConfigure(mapper);
+
+ // Unknown key.
+ ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
+
+ // Virtual key is down.
+ int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
+ int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
+ processDown(mapper, x, y);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+ ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
+
+ // Virtual key is up.
+ processUp(mapper);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+ ASSERT_EQ(AKEY_STATE_UP, mapper->getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_HOME));
+}
+
+TEST_F(SingleTouchInputMapperTest, GetScanCodeState) {
+ SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice, DISPLAY_ID);
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
+ prepareAxes(POSITION);
+ prepareVirtualKeys();
+ addMapperAndConfigure(mapper);
+
+ // Unknown key.
+ ASSERT_EQ(AKEY_STATE_UNKNOWN, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
+
+ // Virtual key is down.
+ int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
+ int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
+ processDown(mapper, x, y);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+ ASSERT_EQ(AKEY_STATE_VIRTUAL, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
+
+ // Virtual key is up.
+ processUp(mapper);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+ ASSERT_EQ(AKEY_STATE_UP, mapper->getScanCodeState(AINPUT_SOURCE_ANY, KEY_HOME));
+}
+
+TEST_F(SingleTouchInputMapperTest, MarkSupportedKeyCodes) {
+ SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice, DISPLAY_ID);
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
+ prepareAxes(POSITION);
+ prepareVirtualKeys();
+ addMapperAndConfigure(mapper);
+
+ const int32_t keys[2] = { AKEYCODE_HOME, AKEYCODE_A };
+ uint8_t flags[2] = { 0, 0 };
+ ASSERT_TRUE(mapper->markSupportedKeyCodes(AINPUT_SOURCE_ANY, 2, keys, flags));
+ ASSERT_TRUE(flags[0]);
+ ASSERT_FALSE(flags[1]);
+}
+
+TEST_F(SingleTouchInputMapperTest, Reset_WhenVirtualKeysAreDown_SendsUp) {
+ // Note: Ideally we should send cancels but the implementation is more straightforward
+ // with up and this will only happen if a device is forcibly removed.
+ SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice, DISPLAY_ID);
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
+ prepareAxes(POSITION);
+ prepareVirtualKeys();
+ addMapperAndConfigure(mapper);
+
+ mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+
+ // Press virtual key.
+ int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
+ int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
+ processDown(mapper, x, y);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+ // Reset. Since key is down, synthesize key up.
+ mapper->reset();
+
+ FakeInputDispatcher::NotifyKeyArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+ //ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
+ ASSERT_EQ(DEVICE_ID, args.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+ ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
+ ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+ ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
+ ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
+ ASSERT_EQ(KEY_HOME, args.scanCode);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+ ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+}
+
+TEST_F(SingleTouchInputMapperTest, Reset_WhenNothingIsPressed_NothingMuchHappens) {
+ SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice, DISPLAY_ID);
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
+ prepareAxes(POSITION);
+ prepareVirtualKeys();
+ addMapperAndConfigure(mapper);
+
+ // Press virtual key.
+ int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
+ int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
+ processDown(mapper, x, y);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+ // Release virtual key.
+ processUp(mapper);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled());
+
+ // Reset. Since no key is down, nothing happens.
+ mapper->reset();
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
+}
+
+TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndReleasedNormally_SendsKeyDownAndKeyUp) {
+ SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice, DISPLAY_ID);
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
+ prepareAxes(POSITION);
+ prepareVirtualKeys();
+ addMapperAndConfigure(mapper);
+
+ mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+
+ FakeInputDispatcher::NotifyKeyArgs args;
+
+ // Press virtual key.
+ int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
+ int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
+ processDown(mapper, x, y);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+ ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
+ ASSERT_EQ(DEVICE_ID, args.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+ ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
+ ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, args.action);
+ ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
+ ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
+ ASSERT_EQ(KEY_HOME, args.scanCode);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+ ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+
+ // Release virtual key.
+ processUp(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&args));
+ ASSERT_EQ(ARBITRARY_TIME, args.eventTime);
+ ASSERT_EQ(DEVICE_ID, args.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, args.source);
+ ASSERT_EQ(POLICY_FLAG_VIRTUAL, args.policyFlags);
+ ASSERT_EQ(AKEY_EVENT_ACTION_UP, args.action);
+ ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, args.flags);
+ ASSERT_EQ(AKEYCODE_HOME, args.keyCode);
+ ASSERT_EQ(KEY_HOME, args.scanCode);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
+ ASSERT_EQ(ARBITRARY_TIME, args.downTime);
+
+ // Should not have sent any motions.
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
+}
+
+TEST_F(SingleTouchInputMapperTest, Process_WhenVirtualKeyIsPressedAndMovedOutOfBounds_SendsKeyDownAndKeyCancel) {
+ SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice, DISPLAY_ID);
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
+ prepareAxes(POSITION);
+ prepareVirtualKeys();
+ addMapperAndConfigure(mapper);
+
+ mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+
+ FakeInputDispatcher::NotifyKeyArgs keyArgs;
+
+ // Press virtual key.
+ int32_t x = toRawX(VIRTUAL_KEYS[0].centerX);
+ int32_t y = toRawY(VIRTUAL_KEYS[0].centerY);
+ processDown(mapper, x, y);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&keyArgs));
+ ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
+ ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
+ ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
+ ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY, keyArgs.flags);
+ ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
+ ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
+ ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
+
+ // Move out of bounds. This should generate a cancel and a pointer down since we moved
+ // into the display area.
+ y -= 100;
+ processMove(mapper, x, y);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasCalled(&keyArgs));
+ ASSERT_EQ(ARBITRARY_TIME, keyArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, keyArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyArgs.source);
+ ASSERT_EQ(POLICY_FLAG_VIRTUAL, keyArgs.policyFlags);
+ ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
+ ASSERT_EQ(AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
+ | AKEY_EVENT_FLAG_CANCELED, keyArgs.flags);
+ ASSERT_EQ(AKEYCODE_HOME, keyArgs.keyCode);
+ ASSERT_EQ(KEY_HOME, keyArgs.scanCode);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, keyArgs.metaState);
+ ASSERT_EQ(ARBITRARY_TIME, keyArgs.downTime);
+
+ FakeInputDispatcher::NotifyMotionArgs motionArgs;
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+ ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
+ ASSERT_EQ(0, motionArgs.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.edgeFlags);
+ ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+ ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+ ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+ // Keep moving out of bounds. Should generate a pointer move.
+ y -= 50;
+ processMove(mapper, x, y);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+ ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(0, motionArgs.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.edgeFlags);
+ ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+ ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+ ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+ // Release out of bounds. Should generate a pointer up.
+ processUp(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+ ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
+ ASSERT_EQ(0, motionArgs.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.edgeFlags);
+ ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+ ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+ ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+ // Should not have sent any more keys or motions.
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
+}
+
+TEST_F(SingleTouchInputMapperTest, Process_WhenTouchStartsOutsideDisplayAndMovesIn_SendsDownAsTouchEntersDisplay) {
+ SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice, DISPLAY_ID);
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
+ prepareAxes(POSITION);
+ prepareVirtualKeys();
+ addMapperAndConfigure(mapper);
+
+ mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+
+ FakeInputDispatcher::NotifyMotionArgs motionArgs;
+
+ // Initially go down out of bounds.
+ int32_t x = -10;
+ int32_t y = -10;
+ processDown(mapper, x, y);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
+
+ // Move into the display area. Should generate a pointer down.
+ x = 50;
+ y = 75;
+ processMove(mapper, x, y);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+ ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
+ ASSERT_EQ(0, motionArgs.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.edgeFlags);
+ ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+ ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+ ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+ // Release. Should generate a pointer up.
+ processUp(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+ ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
+ ASSERT_EQ(0, motionArgs.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.edgeFlags);
+ ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+ ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+ ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+ // Should not have sent any more keys or motions.
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
+}
+
+TEST_F(SingleTouchInputMapperTest, Process_NormalSingleTouchGesture) {
+ SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice, DISPLAY_ID);
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
+ prepareAxes(POSITION);
+ prepareVirtualKeys();
+ addMapperAndConfigure(mapper);
+
+ mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+
+ FakeInputDispatcher::NotifyMotionArgs motionArgs;
+
+ // Down.
+ int32_t x = 100;
+ int32_t y = 125;
+ processDown(mapper, x, y);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+ ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
+ ASSERT_EQ(0, motionArgs.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.edgeFlags);
+ ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+ ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+ ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+ // Move.
+ x += 50;
+ y += 75;
+ processMove(mapper, x, y);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+ ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(0, motionArgs.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.edgeFlags);
+ ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+ ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+ ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+ // Up.
+ processUp(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+ ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
+ ASSERT_EQ(0, motionArgs.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.edgeFlags);
+ ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+ ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x), toDisplayY(y), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+ ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+ // Should not have sent any more keys or motions.
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
+}
+
+TEST_F(SingleTouchInputMapperTest, Process_Rotation) {
+ SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice, DISPLAY_ID);
+ prepareAxes(POSITION);
+ addMapperAndConfigure(mapper);
+
+ FakeInputDispatcher::NotifyMotionArgs args;
+
+ // Rotation 0.
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
+ processDown(mapper, toRawX(50), toRawY(75));
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_NEAR(50, args.pointerCoords[0].x, 1);
+ ASSERT_NEAR(75, args.pointerCoords[0].y, 1);
+
+ processUp(mapper);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
+
+ // Rotation 90.
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_90);
+ processDown(mapper, toRawX(50), toRawY(75));
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_NEAR(75, args.pointerCoords[0].x, 1);
+ ASSERT_NEAR(DISPLAY_WIDTH - 50, args.pointerCoords[0].y, 1);
+
+ processUp(mapper);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
+
+ // Rotation 180.
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_180);
+ processDown(mapper, toRawX(50), toRawY(75));
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_NEAR(DISPLAY_WIDTH - 50, args.pointerCoords[0].x, 1);
+ ASSERT_NEAR(DISPLAY_HEIGHT - 75, args.pointerCoords[0].y, 1);
+
+ processUp(mapper);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
+
+ // Rotation 270.
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_270);
+ processDown(mapper, toRawX(50), toRawY(75));
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_NEAR(DISPLAY_HEIGHT - 75, args.pointerCoords[0].x, 1);
+ ASSERT_NEAR(50, args.pointerCoords[0].y, 1);
+
+ processUp(mapper);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled());
+}
+
+TEST_F(SingleTouchInputMapperTest, Process_AllAxes_DefaultCalibration) {
+ SingleTouchInputMapper* mapper = new SingleTouchInputMapper(mDevice, DISPLAY_ID);
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
+ prepareAxes(POSITION | PRESSURE | TOOL);
+ addMapperAndConfigure(mapper);
+
+ // These calculations are based on the input device calibration documentation.
+ int32_t rawX = 100;
+ int32_t rawY = 200;
+ int32_t rawPressure = 10;
+ int32_t rawToolMajor = 12;
+
+ float x = toDisplayX(rawX);
+ float y = toDisplayY(rawY);
+ float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
+ float size = float(rawToolMajor) / RAW_TOOL_MAX;
+ float tool = min(DISPLAY_WIDTH, DISPLAY_HEIGHT) * size;
+ float touch = min(tool * pressure, tool);
+
+ processDown(mapper, rawX, rawY);
+ processPressure(mapper, rawPressure);
+ processToolMajor(mapper, rawToolMajor);
+ processSync(mapper);
+
+ FakeInputDispatcher::NotifyMotionArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+ x, y, pressure, size, touch, touch, tool, tool, 0));
+}
+
+
+// --- MultiTouchInputMapperTest ---
+
+class MultiTouchInputMapperTest : public TouchInputMapperTest {
+protected:
+ void prepareAxes(int axes);
+
+ void processPosition(MultiTouchInputMapper* mapper, int32_t x, int32_t y);
+ void processTouchMajor(MultiTouchInputMapper* mapper, int32_t touchMajor);
+ void processTouchMinor(MultiTouchInputMapper* mapper, int32_t touchMinor);
+ void processToolMajor(MultiTouchInputMapper* mapper, int32_t toolMajor);
+ void processToolMinor(MultiTouchInputMapper* mapper, int32_t toolMinor);
+ void processOrientation(MultiTouchInputMapper* mapper, int32_t orientation);
+ void processPressure(MultiTouchInputMapper* mapper, int32_t pressure);
+ void processId(MultiTouchInputMapper* mapper, int32_t id);
+ void processMTSync(MultiTouchInputMapper* mapper);
+ void processSync(MultiTouchInputMapper* mapper);
+};
+
+void MultiTouchInputMapperTest::prepareAxes(int axes) {
+ if (axes & POSITION) {
+ mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
+ mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
+ }
+ if (axes & TOUCH) {
+ mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0);
+ if (axes & MINOR) {
+ mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TOUCH_MINOR,
+ RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0);
+ }
+ }
+ if (axes & TOOL) {
+ mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0);
+ if (axes & MINOR) {
+ mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_WIDTH_MINOR,
+ RAW_TOOL_MAX, RAW_TOOL_MAX, 0, 0);
+ }
+ }
+ if (axes & ORIENTATION) {
+ mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_ORIENTATION,
+ RAW_ORIENTATION_MIN, RAW_ORIENTATION_MAX, 0, 0);
+ }
+ if (axes & PRESSURE) {
+ mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_PRESSURE,
+ RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0);
+ }
+ if (axes & ID) {
+ mFakeEventHub->addAxis(DEVICE_ID, ABS_MT_TRACKING_ID,
+ RAW_ID_MIN, RAW_ID_MAX, 0, 0);
+ }
+}
+
+void MultiTouchInputMapperTest::processPosition(
+ MultiTouchInputMapper* mapper, int32_t x, int32_t y) {
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_POSITION_X, 0, x, 0);
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_POSITION_Y, 0, y, 0);
+}
+
+void MultiTouchInputMapperTest::processTouchMajor(
+ MultiTouchInputMapper* mapper, int32_t touchMajor) {
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOUCH_MAJOR, 0, touchMajor, 0);
+}
+
+void MultiTouchInputMapperTest::processTouchMinor(
+ MultiTouchInputMapper* mapper, int32_t touchMinor) {
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TOUCH_MINOR, 0, touchMinor, 0);
+}
+
+void MultiTouchInputMapperTest::processToolMajor(
+ MultiTouchInputMapper* mapper, int32_t toolMajor) {
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_WIDTH_MAJOR, 0, toolMajor, 0);
+}
+
+void MultiTouchInputMapperTest::processToolMinor(
+ MultiTouchInputMapper* mapper, int32_t toolMinor) {
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_WIDTH_MINOR, 0, toolMinor, 0);
+}
+
+void MultiTouchInputMapperTest::processOrientation(
+ MultiTouchInputMapper* mapper, int32_t orientation) {
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_ORIENTATION, 0, orientation, 0);
+}
+
+void MultiTouchInputMapperTest::processPressure(
+ MultiTouchInputMapper* mapper, int32_t pressure) {
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_PRESSURE, 0, pressure, 0);
+}
+
+void MultiTouchInputMapperTest::processId(
+ MultiTouchInputMapper* mapper, int32_t id) {
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_ABS, ABS_MT_TRACKING_ID, 0, id, 0);
+}
+
+void MultiTouchInputMapperTest::processMTSync(MultiTouchInputMapper* mapper) {
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_MT_REPORT, 0, 0, 0);
+}
+
+void MultiTouchInputMapperTest::processSync(MultiTouchInputMapper* mapper) {
+ process(mapper, ARBITRARY_TIME, DEVICE_ID, EV_SYN, SYN_REPORT, 0, 0, 0);
+}
+
+
+TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithoutTrackingIds) {
+ MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice, DISPLAY_ID);
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
+ prepareAxes(POSITION);
+ prepareVirtualKeys();
+ addMapperAndConfigure(mapper);
+
+ mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+
+ FakeInputDispatcher::NotifyMotionArgs motionArgs;
+
+ // Two fingers down at once.
+ int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
+ processPosition(mapper, x1, y1);
+ processMTSync(mapper);
+ processPosition(mapper, x2, y2);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+ ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
+ ASSERT_EQ(0, motionArgs.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.edgeFlags);
+ ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+ ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+ ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+ ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ motionArgs.action);
+ ASSERT_EQ(0, motionArgs.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.edgeFlags);
+ ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+ ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_EQ(1, motionArgs.pointerIds[1]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+ toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+ ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+ // Move.
+ x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
+ processPosition(mapper, x1, y1);
+ processMTSync(mapper);
+ processPosition(mapper, x2, y2);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+ ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(0, motionArgs.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.edgeFlags);
+ ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+ ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_EQ(1, motionArgs.pointerIds[1]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+ toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+ ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+ // First finger up.
+ x2 += 15; y2 -= 20;
+ processPosition(mapper, x2, y2);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+ ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ motionArgs.action);
+ ASSERT_EQ(0, motionArgs.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.edgeFlags);
+ ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+ ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_EQ(1, motionArgs.pointerIds[1]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+ toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+ ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+ ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(0, motionArgs.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.edgeFlags);
+ ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+ ASSERT_EQ(1, motionArgs.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+ ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+ // Move.
+ x2 += 20; y2 -= 25;
+ processPosition(mapper, x2, y2);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+ ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(0, motionArgs.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.edgeFlags);
+ ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+ ASSERT_EQ(1, motionArgs.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+ ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+ // New finger down.
+ int32_t x3 = 700, y3 = 300;
+ processPosition(mapper, x2, y2);
+ processMTSync(mapper);
+ processPosition(mapper, x3, y3);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+ ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ motionArgs.action);
+ ASSERT_EQ(0, motionArgs.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.edgeFlags);
+ ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+ ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_EQ(1, motionArgs.pointerIds[1]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+ toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+ ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+ // Second finger up.
+ x3 += 30; y3 -= 20;
+ processPosition(mapper, x3, y3);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+ ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ motionArgs.action);
+ ASSERT_EQ(0, motionArgs.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.edgeFlags);
+ ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+ ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_EQ(1, motionArgs.pointerIds[1]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+ toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+ ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+ ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(0, motionArgs.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.edgeFlags);
+ ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+ ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+ ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+ // Last finger up.
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.eventTime);
+ ASSERT_EQ(DEVICE_ID, motionArgs.deviceId);
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, motionArgs.source);
+ ASSERT_EQ(uint32_t(0), motionArgs.policyFlags);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
+ ASSERT_EQ(0, motionArgs.flags);
+ ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, motionArgs.metaState);
+ ASSERT_EQ(0, motionArgs.edgeFlags);
+ ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+ ASSERT_EQ(0, motionArgs.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NEAR(X_PRECISION, motionArgs.xPrecision, EPSILON);
+ ASSERT_NEAR(Y_PRECISION, motionArgs.yPrecision, EPSILON);
+ ASSERT_EQ(ARBITRARY_TIME, motionArgs.downTime);
+
+ // Should not have sent any more keys or motions.
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
+}
+
+TEST_F(MultiTouchInputMapperTest, Process_NormalMultiTouchGesture_WithTrackingIds) {
+ MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice, DISPLAY_ID);
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
+ prepareAxes(POSITION | ID);
+ prepareVirtualKeys();
+ addMapperAndConfigure(mapper);
+
+ mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+
+ FakeInputDispatcher::NotifyMotionArgs motionArgs;
+
+ // Two fingers down at once.
+ int32_t x1 = 100, y1 = 125, x2 = 300, y2 = 500;
+ processPosition(mapper, x1, y1);
+ processId(mapper, 1);
+ processMTSync(mapper);
+ processPosition(mapper, x2, y2);
+ processId(mapper, 2);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
+ ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+ ASSERT_EQ(1, motionArgs.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ motionArgs.action);
+ ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+ ASSERT_EQ(1, motionArgs.pointerIds[0]);
+ ASSERT_EQ(2, motionArgs.pointerIds[1]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+ toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+
+ // Move.
+ x1 += 10; y1 += 15; x2 += 5; y2 -= 10;
+ processPosition(mapper, x1, y1);
+ processId(mapper, 1);
+ processMTSync(mapper);
+ processPosition(mapper, x2, y2);
+ processId(mapper, 2);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+ ASSERT_EQ(1, motionArgs.pointerIds[0]);
+ ASSERT_EQ(2, motionArgs.pointerIds[1]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+ toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+
+ // First finger up.
+ x2 += 15; y2 -= 20;
+ processPosition(mapper, x2, y2);
+ processId(mapper, 2);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ motionArgs.action);
+ ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+ ASSERT_EQ(1, motionArgs.pointerIds[0]);
+ ASSERT_EQ(2, motionArgs.pointerIds[1]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x1), toDisplayY(y1), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+ toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+ ASSERT_EQ(2, motionArgs.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+
+ // Move.
+ x2 += 20; y2 -= 25;
+ processPosition(mapper, x2, y2);
+ processId(mapper, 2);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+ ASSERT_EQ(2, motionArgs.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+
+ // New finger down.
+ int32_t x3 = 700, y3 = 300;
+ processPosition(mapper, x2, y2);
+ processId(mapper, 2);
+ processMTSync(mapper);
+ processPosition(mapper, x3, y3);
+ processId(mapper, 3);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ motionArgs.action);
+ ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+ ASSERT_EQ(2, motionArgs.pointerIds[0]);
+ ASSERT_EQ(3, motionArgs.pointerIds[1]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+ toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
+
+ // Second finger up.
+ x3 += 30; y3 -= 20;
+ processPosition(mapper, x3, y3);
+ processId(mapper, 3);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_UP | (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ motionArgs.action);
+ ASSERT_EQ(size_t(2), motionArgs.pointerCount);
+ ASSERT_EQ(2, motionArgs.pointerIds[0]);
+ ASSERT_EQ(3, motionArgs.pointerIds[1]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x2), toDisplayY(y2), 1, 0, 0, 0, 0, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1],
+ toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+ ASSERT_EQ(3, motionArgs.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
+
+ // Last finger up.
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
+ ASSERT_EQ(size_t(1), motionArgs.pointerCount);
+ ASSERT_EQ(3, motionArgs.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0],
+ toDisplayX(x3), toDisplayY(y3), 1, 0, 0, 0, 0, 0, 0));
+
+ // Should not have sent any more keys or motions.
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyKeyWasNotCalled());
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasNotCalled());
+}
+
+TEST_F(MultiTouchInputMapperTest, Process_AllAxes_WithDefaultCalibration) {
+ MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice, DISPLAY_ID);
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
+ prepareAxes(POSITION | TOUCH | TOOL | PRESSURE | ORIENTATION | ID | MINOR);
+ addMapperAndConfigure(mapper);
+
+ // These calculations are based on the input device calibration documentation.
+ int32_t rawX = 100;
+ int32_t rawY = 200;
+ int32_t rawTouchMajor = 7;
+ int32_t rawTouchMinor = 6;
+ int32_t rawToolMajor = 9;
+ int32_t rawToolMinor = 8;
+ int32_t rawPressure = 11;
+ int32_t rawOrientation = 3;
+ int32_t id = 5;
+
+ float x = toDisplayX(rawX);
+ float y = toDisplayY(rawY);
+ float pressure = float(rawPressure) / RAW_PRESSURE_MAX;
+ float size = avg(rawToolMajor, rawToolMinor) / RAW_TOOL_MAX;
+ float toolMajor = float(min(DISPLAY_WIDTH, DISPLAY_HEIGHT)) * rawToolMajor / RAW_TOOL_MAX;
+ float toolMinor = float(min(DISPLAY_WIDTH, DISPLAY_HEIGHT)) * rawToolMinor / RAW_TOOL_MAX;
+ float touchMajor = min(toolMajor * pressure, toolMajor);
+ float touchMinor = min(toolMinor * pressure, toolMinor);
+ float orientation = float(rawOrientation) / RAW_ORIENTATION_MAX * M_PI_2;
+
+ processPosition(mapper, rawX, rawY);
+ processTouchMajor(mapper, rawTouchMajor);
+ processTouchMinor(mapper, rawTouchMinor);
+ processToolMajor(mapper, rawToolMajor);
+ processToolMinor(mapper, rawToolMinor);
+ processPressure(mapper, rawPressure);
+ processOrientation(mapper, rawOrientation);
+ processId(mapper, id);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ FakeInputDispatcher::NotifyMotionArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(id, args.pointerIds[0]);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+ x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor, orientation));
+}
+
+TEST_F(MultiTouchInputMapperTest, Process_TouchAndToolAxes_GeometricCalibration) {
+ MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice, DISPLAY_ID);
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
+ prepareAxes(POSITION | TOUCH | TOOL | MINOR);
+ prepareCalibration("touch.touchSize.calibration", "geometric");
+ prepareCalibration("touch.toolSize.calibration", "geometric");
+ addMapperAndConfigure(mapper);
+
+ // These calculations are based on the input device calibration documentation.
+ int32_t rawX = 100;
+ int32_t rawY = 200;
+ int32_t rawTouchMajor = 140;
+ int32_t rawTouchMinor = 120;
+ int32_t rawToolMajor = 180;
+ int32_t rawToolMinor = 160;
+
+ float x = toDisplayX(rawX);
+ float y = toDisplayY(rawY);
+ float pressure = float(rawTouchMajor) / RAW_TOUCH_MAX;
+ float size = avg(rawToolMajor, rawToolMinor) / RAW_TOOL_MAX;
+ float scale = avg(float(DISPLAY_WIDTH) / (RAW_X_MAX - RAW_X_MIN),
+ float(DISPLAY_HEIGHT) / (RAW_Y_MAX - RAW_Y_MIN));
+ float toolMajor = float(rawToolMajor) * scale;
+ float toolMinor = float(rawToolMinor) * scale;
+ float touchMajor = min(float(rawTouchMajor) * scale, toolMajor);
+ float touchMinor = min(float(rawTouchMinor) * scale, toolMinor);
+
+ processPosition(mapper, rawX, rawY);
+ processTouchMajor(mapper, rawTouchMajor);
+ processTouchMinor(mapper, rawTouchMinor);
+ processToolMajor(mapper, rawToolMajor);
+ processToolMinor(mapper, rawToolMinor);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ FakeInputDispatcher::NotifyMotionArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+ x, y, pressure, size, touchMajor, touchMinor, toolMajor, toolMinor, 0));
+}
+
+TEST_F(MultiTouchInputMapperTest, Process_TouchToolPressureSizeAxes_SummedLinearCalibration) {
+ MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice, DISPLAY_ID);
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
+ prepareAxes(POSITION | TOUCH | TOOL);
+ prepareCalibration("touch.touchSize.calibration", "pressure");
+ prepareCalibration("touch.toolSize.calibration", "linear");
+ prepareCalibration("touch.toolSize.linearScale", "10");
+ prepareCalibration("touch.toolSize.linearBias", "160");
+ prepareCalibration("touch.toolSize.isSummed", "1");
+ prepareCalibration("touch.pressure.calibration", "amplitude");
+ prepareCalibration("touch.pressure.source", "touch");
+ prepareCalibration("touch.pressure.scale", "0.01");
+ addMapperAndConfigure(mapper);
+
+ // These calculations are based on the input device calibration documentation.
+ // Note: We only provide a single common touch/tool value because the device is assumed
+ // not to emit separate values for each pointer (isSummed = 1).
+ int32_t rawX = 100;
+ int32_t rawY = 200;
+ int32_t rawX2 = 150;
+ int32_t rawY2 = 250;
+ int32_t rawTouchMajor = 60;
+ int32_t rawToolMajor = 5;
+
+ float x = toDisplayX(rawX);
+ float y = toDisplayY(rawY);
+ float x2 = toDisplayX(rawX2);
+ float y2 = toDisplayY(rawY2);
+ float pressure = float(rawTouchMajor) * 0.01f;
+ float size = float(rawToolMajor) / RAW_TOOL_MAX;
+ float tool = (float(rawToolMajor) * 10.0f + 160.0f) / 2;
+ float touch = min(tool * pressure, tool);
+
+ processPosition(mapper, rawX, rawY);
+ processTouchMajor(mapper, rawTouchMajor);
+ processToolMajor(mapper, rawToolMajor);
+ processMTSync(mapper);
+ processPosition(mapper, rawX2, rawY2);
+ processTouchMajor(mapper, rawTouchMajor);
+ processToolMajor(mapper, rawToolMajor);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ FakeInputDispatcher::NotifyMotionArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, args.action);
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
+ args.action);
+ ASSERT_EQ(size_t(2), args.pointerCount);
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+ x, y, pressure, size, touch, touch, tool, tool, 0));
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[1],
+ x2, y2, pressure, size, touch, touch, tool, tool, 0));
+}
+
+TEST_F(MultiTouchInputMapperTest, Process_TouchToolPressureSizeAxes_AreaCalibration) {
+ MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice, DISPLAY_ID);
+ prepareDisplay(InputReaderPolicyInterface::ROTATION_0);
+ prepareAxes(POSITION | TOUCH | TOOL);
+ prepareCalibration("touch.touchSize.calibration", "pressure");
+ prepareCalibration("touch.toolSize.calibration", "area");
+ prepareCalibration("touch.toolSize.areaScale", "22");
+ prepareCalibration("touch.toolSize.areaBias", "1");
+ prepareCalibration("touch.toolSize.linearScale", "9.2");
+ prepareCalibration("touch.toolSize.linearBias", "3");
+ prepareCalibration("touch.pressure.calibration", "amplitude");
+ prepareCalibration("touch.pressure.source", "touch");
+ prepareCalibration("touch.pressure.scale", "0.01");
+ addMapperAndConfigure(mapper);
+
+ // These calculations are based on the input device calibration documentation.
+ int32_t rawX = 100;
+ int32_t rawY = 200;
+ int32_t rawTouchMajor = 60;
+ int32_t rawToolMajor = 5;
+
+ float x = toDisplayX(rawX);
+ float y = toDisplayY(rawY);
+ float pressure = float(rawTouchMajor) * 0.01f;
+ float size = float(rawToolMajor) / RAW_TOOL_MAX;
+ float tool = sqrtf(float(rawToolMajor) * 22.0f + 1.0f) * 9.2f + 3.0f;
+ float touch = min(tool * pressure, tool);
+
+ processPosition(mapper, rawX, rawY);
+ processTouchMajor(mapper, rawTouchMajor);
+ processToolMajor(mapper, rawToolMajor);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ FakeInputDispatcher::NotifyMotionArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeDispatcher->assertNotifyMotionWasCalled(&args));
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0],
+ x, y, pressure, size, touch, touch, tool, tool, 0));
+}
+
+} // namespace android
diff --git a/libs/utils/ZipFileRO.cpp b/libs/utils/ZipFileRO.cpp
index 5ff1f8f..4261196 100644
--- a/libs/utils/ZipFileRO.cpp
+++ b/libs/utils/ZipFileRO.cpp
@@ -412,10 +412,18 @@ void ZipFileRO::addToHash(const char* str, int strLen, unsigned int hash)
/*
* Find a matching entry.
*
- * Returns 0 if not found.
+ * Returns NULL if not found.
*/
ZipEntryRO ZipFileRO::findEntryByName(const char* fileName) const
{
+ /*
+ * If the ZipFileRO instance is not initialized, the entry number will
+ * end up being garbage since mHashTableSize is -1.
+ */
+ if (mHashTableSize <= 0) {
+ return NULL;
+ }
+
int nameLen = strlen(fileName);
unsigned int hash = computeHash(fileName, nameLen);
int ent = hash & (mHashTableSize-1);
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 6aa1ae6..23f34d2 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -58,6 +58,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
@@ -1112,18 +1113,16 @@ public class AudioService extends IAudioService.Stub {
new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
mBluetoothHeadset = (BluetoothHeadset) proxy;
- Set<BluetoothDevice> deviceSet = mBluetoothHeadset.getConnectedDevices();
- if (deviceSet.size() > 0) {
- BluetoothDevice[] devices =
- deviceSet.toArray(new BluetoothDevice[deviceSet.size()]);
- mBluetoothHeadsetDevice = devices[0];
+ List<BluetoothDevice> deviceList = mBluetoothHeadset.getConnectedDevices();
+ if (deviceList.size() > 0) {
+ mBluetoothHeadsetDevice = deviceList.get(0);
} else {
mBluetoothHeadsetDevice = null;
}
}
public void onServiceDisconnected(int profile) {
if (mBluetoothHeadset != null) {
- Set<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices();
+ List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices();
if (devices.size() == 0) {
mBluetoothHeadsetDevice = null;
clearAllScoClients();
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index 57cafd4..27b28ee 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -131,6 +131,7 @@ static void captureCallback(void* user,
samplingrate,
0,
jArray);
+ env->DeleteLocalRef(jArray);
}
}
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 40801a2..f975217 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -24,6 +24,7 @@ enum {
ENABLE_GRAPHIC_BUFFERS,
USE_BUFFER,
USE_GRAPHIC_BUFFER,
+ STORE_META_DATA_IN_BUFFERS,
ALLOC_BUFFER,
ALLOC_BUFFER_WITH_BACKUP,
FREE_BUFFER,
@@ -276,6 +277,19 @@ public:
return err;
}
+ virtual status_t storeMetaDataInBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(port_index);
+ data.writeInt32((uint32_t)enable);
+ remote()->transact(STORE_META_DATA_IN_BUFFERS, data, &reply);
+
+ status_t err = reply.readInt32();
+ return err;
+ }
+
virtual status_t allocateBuffer(
node_id node, OMX_U32 port_index, size_t size,
buffer_id *buffer, void **buffer_data) {
@@ -634,6 +648,20 @@ status_t BnOMX::onTransact(
return NO_ERROR;
}
+ case STORE_META_DATA_IN_BUFFERS:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ OMX_U32 port_index = data.readInt32();
+ OMX_BOOL enable = (OMX_BOOL)data.readInt32();
+
+ status_t err = storeMetaDataInBuffers(node, port_index, enable);
+ reply->writeInt32(err);
+
+ return NO_ERROR;
+ }
+
case ALLOC_BUFFER:
{
CHECK_INTERFACE(IOMX, data, reply);
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index 83b75ad..5a6c96f9 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -62,6 +62,9 @@ public:
virtual status_t enableGraphicBuffers(
node_id node, OMX_U32 port_index, OMX_BOOL enable);
+ virtual status_t storeMetaDataInBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable);
+
virtual status_t useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
buffer_id *buffer);
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index 8c7c562..86c102c 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -50,6 +50,7 @@ struct OMXNodeInstance {
status_t setConfig(OMX_INDEXTYPE index, const void *params, size_t size);
status_t enableGraphicBuffers(OMX_U32 portIndex, OMX_BOOL enable);
+ status_t storeMetaDataInBuffers(OMX_U32 portIndex, OMX_BOOL enable);
status_t useBuffer(
OMX_U32 portIndex, const sp<IMemory> &params,
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index d89f54b..f9f638f 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -294,6 +294,11 @@ status_t OMX::enableGraphicBuffers(
return findInstance(node)->enableGraphicBuffers(port_index, enable);
}
+status_t OMX::storeMetaDataInBuffers(
+ node_id node, OMX_U32 port_index, OMX_BOOL enable) {
+ return findInstance(node)->storeMetaDataInBuffers(port_index, enable);
+}
+
status_t OMX::useBuffer(
node_id node, OMX_U32 port_index, const sp<IMemory> &params,
buffer_id *buffer) {
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index ba4d765..9b6d441 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -284,6 +284,37 @@ status_t OMXNodeInstance::enableGraphicBuffers(
return OK;
}
+status_t OMXNodeInstance::storeMetaDataInBuffers(
+ OMX_U32 portIndex,
+ OMX_BOOL enable) {
+ Mutex::Autolock autolock(mLock);
+
+ OMX_INDEXTYPE index;
+ OMX_STRING name = const_cast<OMX_STRING>(
+ "OMX.google.android.index.storeMetaDataInBuffers");
+
+ OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
+ if (err != OMX_ErrorNone) {
+ LOGE("OMX_GetExtensionIndex %s failed", name);
+ return StatusFromOMXError(err);
+ }
+
+ StoreMetaDataInBuffersParams params;
+ memset(&params, 0, sizeof(params));
+ params.nSize = sizeof(params);
+
+ // Version: 1.0.0.0
+ params.nVersion.s.nVersionMajor = 1;
+
+ params.nPortIndex = portIndex;
+ params.bStoreMetaData = enable;
+ if ((err = OMX_SetParameter(mHandle, index, &params)) != OMX_ErrorNone) {
+ LOGE("OMX_SetParameter() failed for StoreMetaDataInBuffers: 0x%08x", err);
+ return UNKNOWN_ERROR;
+ }
+ return err;
+}
+
status_t OMXNodeInstance::useBuffer(
OMX_U32 portIndex, const sp<IMemory> &params,
OMX::buffer_id *buffer) {
diff --git a/native/copy-to-ndk.sh b/native/copy-to-ndk.sh
index 4f5a16a..6470892 100644
--- a/native/copy-to-ndk.sh
+++ b/native/copy-to-ndk.sh
@@ -10,7 +10,7 @@ copyndkheaders() {
local DST_HEADERS=$NDK_PLATFORMS/$CURR_PLATFORM
local SRC_LIB_ANDROID=$ANDROID_PRODUCT_OUT/system/lib/libandroid.so
- local DST_LIB_ANDROID=$NDK_PLATFORMS/$CURR_PLATFORM/arch-arm/usr/lib/libandroid.so
+ local DST_LIB_ANDROID=$NDK_PLATFORMS/$CURR_PLATFORM/arch-arm/lib/libandroid.so
local didsomething=""
@@ -20,9 +20,9 @@ copyndkheaders() {
local src=$SRC_HEADERS/$i
local changed=""
for j in $ALL_PLATFORMS; do
- local dst=$NDK_PLATFORMS/$j/arch-arm/usr/include/android/$i
+ local dst=$NDK_PLATFORMS/$j/include/android/$i
if [ "$changed" == "" -a -e $dst ]; then
- #echo "Exists: $dst"
+ echo "Exists: $dst"
if diff $src $dst >/dev/null; then
echo "$i: has not changed from $j" >/dev/null
changed="false"
@@ -34,13 +34,13 @@ copyndkheaders() {
done
if [ "$changed" == "true" -o "$changed" == "" ]; then
echo "Updating: $i"
- cp $src $NDK_PLATFORMS/$CURR_PLATFORM/arch-arm/usr/include/android/$i
+ cp $src $NDK_PLATFORMS/$CURR_PLATFORM/include/android/$i
didsomething="true"
fi
done
if diff $SRC_LIB_ANDROID $DST_LIB_ANDROID >/dev/null; then
- echo "libandroid.so: has not changed" >/dev/null
+ echo "libandroid.so: has not changed"
else
echo "Updating: $DST_LIB_ANDROID"
cp $SRC_LIB_ANDROID $DST_LIB_ANDROID
diff --git a/native/include/android/input.h b/native/include/android/input.h
index d190e49..729dd2e 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -336,6 +336,8 @@ enum {
AINPUT_SOURCE_MOUSE = 0x00002000 | AINPUT_SOURCE_CLASS_POINTER,
AINPUT_SOURCE_TRACKBALL = 0x00010000 | AINPUT_SOURCE_CLASS_NAVIGATION,
AINPUT_SOURCE_TOUCHPAD = 0x00100000 | AINPUT_SOURCE_CLASS_POSITION,
+
+ AINPUT_SOURCE_ANY = 0xffffff00,
};
/*
diff --git a/native/include/android/native_activity.h b/native/include/android/native_activity.h
index a8f11c9..d89bc8b 100644
--- a/native/include/android/native_activity.h
+++ b/native/include/android/native_activity.h
@@ -223,18 +223,34 @@ typedef void ANativeActivity_createFunc(ANativeActivity* activity,
/**
* The name of the function that NativeInstance looks for when launching its
- * native code.
+ * native code. This is the default function that is used, you can specify
+ * "android.app.func_name" string meta-data in your manifest to use a different
+ * function.
*/
extern ANativeActivity_createFunc ANativeActivity_onCreate;
/**
* Finish the given activity. Its finish() method will be called, causing it
- * to be stopped and destroyed.
+ * to be stopped and destroyed. Note that this method can be called from
+ * *any* thread; it will send a message to the main thread of the process
+ * where the Java finish call will take place.
*/
void ANativeActivity_finish(ANativeActivity* activity);
+/**
+ * Change the window format of the given activity. Calls getWindow().setFormat()
+ * of the given activity. Note that this method can be called from
+ * *any* thread; it will send a message to the main thread of the process
+ * where the Java finish call will take place.
+ */
void ANativeActivity_setWindowFormat(ANativeActivity* activity, int32_t format);
+/**
+ * Change the window flags of the given activity. Calls getWindow().setFlags()
+ * of the given activity. Note that this method can be called from
+ * *any* thread; it will send a message to the main thread of the process
+ * where the Java finish call will take place. See window.h for flag constants.
+ */
void ANativeActivity_setWindowFlags(ANativeActivity* activity,
uint32_t addFlags, uint32_t removeFlags);
@@ -247,6 +263,12 @@ enum {
ANATIVEACTIVITY_SHOW_SOFT_INPUT_FORCED = 0x0002,
};
+/**
+ * Show the IME while in the given activity. Calls InputMethodManager.showSoftInput()
+ * for the given activity. Note that this method can be called from
+ * *any* thread; it will send a message to the main thread of the process
+ * where the Java finish call will take place.
+ */
void ANativeActivity_showSoftInput(ANativeActivity* activity, uint32_t flags);
/**
@@ -258,6 +280,12 @@ enum {
ANATIVEACTIVITY_HIDE_SOFT_INPUT_NOT_ALWAYS = 0x0002,
};
+/**
+ * Hide the IME while in the given activity. Calls InputMethodManager.hideSoftInput()
+ * for the given activity. Note that this method can be called from
+ * *any* thread; it will send a message to the main thread of the process
+ * where the Java finish call will take place.
+ */
void ANativeActivity_hideSoftInput(ANativeActivity* activity, uint32_t flags);
#ifdef __cplusplus
diff --git a/packages/SystemUI/res/anim/notification_dnd_off.xml b/packages/SystemUI/res/anim/notification_dnd_off.xml
new file mode 100644
index 0000000..4e88855
--- /dev/null
+++ b/packages/SystemUI/res/anim/notification_dnd_off.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ >
+ <translate android:fromXDelta="100%p" android:toXDelta="0"
+ android:duration="@android:integer/config_longAnimTime"
+ android:interpolator="@anim/hydraulic_brake_interpolator"
+ />
+</set>
diff --git a/packages/SystemUI/res/anim/notification_dnd_on.xml b/packages/SystemUI/res/anim/notification_dnd_on.xml
new file mode 100644
index 0000000..309943b
--- /dev/null
+++ b/packages/SystemUI/res/anim/notification_dnd_on.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ >
+ <translate android:toXDelta="100%p" android:fromXDelta="0"
+ android:duration="@android:integer/config_longAnimTime"
+ android:interpolator="@anim/hydraulic_brake_interpolator"
+ />
+</set>
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png
deleted file mode 100644
index 6c5a79b..0000000
--- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_avail.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_avail.png
new file mode 100644
index 0000000..9123fef
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_avail.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_avail_open.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_avail_open.png
new file mode 100644
index 0000000..8e56f2a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_avail_open.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_dnd.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_dnd.png
new file mode 100644
index 0000000..80cf99c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_dnd.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_none.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_none.png
new file mode 100644
index 0000000..e0d018b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_none.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_none_open.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_none_open.png
new file mode 100644
index 0000000..5db8c9c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_noti_none_open.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_back_default.png b/packages/SystemUI/res/drawable-mdpi/status_bar_back_default.png
index 5c57802..f99a66d 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_back_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_back_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_back_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_back_pressed.png
index a2527b3..94a0649 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_back_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_back_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_home_default.png b/packages/SystemUI/res/drawable-mdpi/status_bar_home_default.png
index f219ded..7e8ade5 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_home_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_home_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_home_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_home_pressed.png
index 9e64fe8..7e8ade5 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_home_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_home_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_recent_default.png b/packages/SystemUI/res/drawable-mdpi/status_bar_recent_default.png
index 4dd8dc7..7de67b0 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_recent_default.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_recent_default.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_recent_pressed.png b/packages/SystemUI/res/drawable-mdpi/status_bar_recent_pressed.png
index 350a3e9..7de67b0 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_recent_pressed.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_recent_pressed.png
Binary files differ
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar.xml b/packages/SystemUI/res/layout-xlarge/status_bar.xml
index 8824028..429fdf2 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar.xml
@@ -28,26 +28,27 @@
>
<ImageView
- android:id="@+id/expand"
+ android:id="@+id/notificationTrigger"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_sysbar_open"
+ android:layout_height="match_parent"
+ android:layout_alignParentRight="true"
+ android:layout_marginLeft="6dip"
+ android:src="@drawable/ic_sysbar_noti_none"
android:background="@drawable/ic_sysbar_icon_bg"
- android:paddingLeft="6dip"
+ android:gravity="center"
/>
<LinearLayout
android:id="@+id/notificationButtons"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_toRightOf="@+id/expand"
- android:layout_toLeftOf="@+id/systemInfo"
+ android:layout_toLeftOf="@+id/notificationTrigger"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="gone"
>
- <TextView android:id="@+id/do_not_disturb"
+ <TextView android:id="@+id/clear_all_button"
style="?android:attr/textAppearance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -57,10 +58,10 @@
android:layout_marginRight="10dip"
android:padding="6dip"
android:textSize="14sp"
- android:text="@string/status_bar_do_not_disturb_button"
+ android:text="@string/status_bar_clear_all_button"
/>
- <TextView android:id="@+id/clear_all_button"
+ <TextView android:id="@+id/do_not_disturb"
style="?android:attr/textAppearance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -70,7 +71,7 @@
android:layout_marginRight="10dip"
android:padding="6dip"
android:textSize="14sp"
- android:text="@string/status_bar_clear_all_button"
+ android:text="@string/status_bar_do_not_disturb_button"
/>
</LinearLayout>
@@ -79,26 +80,10 @@
android:id="@+id/notificationIcons"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_toRightOf="@+id/expand"
- android:layout_toLeftOf="@+id/systemInfo"
+ android:layout_toLeftOf="@+id/notificationTrigger"
android:gravity="center_vertical"
android:orientation="horizontal"
>
- <view
- class="com.android.systemui.statusbar.tablet.NotificationIconArea$IconLayout"
- android:id="@+id/icons"
- android:layout_width="wrap_content"
- android:layout_height="@*android:dimen/status_bar_icon_size"
- android:layout_marginLeft="8dip"
- />
- <view
- class="com.android.systemui.statusbar.tablet.NotificationIconArea$DraggerView"
- android:id="@+id/handle"
- android:layout_width="32dip"
- android:layout_height="match_parent"
- android:background="@drawable/sysbar_hidenotification_handle"
- android:layout_marginLeft="8dip"
- />
<com.android.systemui.statusbar.tablet.InputMethodButton
android:id="@+id/imeButton"
android:layout_width="wrap_content"
@@ -106,7 +91,14 @@
android:layout_marginLeft="8dip"
android:src="@drawable/ic_sysbar_ime_default"
android:background="@drawable/ic_sysbar_icon_bg"
- android:visibility="visible"
+ android:visibility="invisible"
+ />
+ <view
+ class="com.android.systemui.statusbar.tablet.NotificationIconArea$IconLayout"
+ android:id="@+id/icons"
+ android:layout_width="wrap_content"
+ android:layout_height="@*android:dimen/status_bar_icon_size"
+ android:layout_marginLeft="8dip"
/>
</com.android.systemui.statusbar.tablet.NotificationIconArea>
@@ -115,8 +107,8 @@
android:id="@+id/ticker"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_alignParentLeft="true"
- android:layout_toLeftOf="@+id/systemInfo"
+ android:layout_alignParentRight="true"
+ android:layout_toRightOf="@+id/systemInfo"
android:paddingLeft="6dip"
android:gravity="center_vertical"
android:animateLayoutChanges="true"
@@ -132,16 +124,53 @@
android:id="@+id/navigationArea"
android:layout_width="wrap_content"
android:layout_height="match_parent"
- android:layout_alignParentRight="true"
+ android:layout_alignParentLeft="true"
android:orientation="horizontal"
>
+
+ <com.android.systemui.statusbar.KeyButtonView android:id="@+id/back"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:paddingLeft="15dip"
+ android:paddingRight="15dip"
+ android:src="@drawable/status_bar_back"
+ android:background="@drawable/ic_sysbar_icon_bg"
+ systemui:keyCode="4"
+ />
+ <com.android.systemui.statusbar.KeyButtonView android:id="@+id/home"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:paddingLeft="15dip"
+ android:paddingRight="15dip"
+ android:src="@drawable/ic_sysbar_home"
+ android:background="@drawable/ic_sysbar_icon_bg"
+ systemui:keyCode="3"
+ />
+ <ImageButton android:id="@+id/recent"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:src="@drawable/ic_sysbar_recent"
+ android:background="@drawable/ic_sysbar_icon_bg"
+ android:paddingLeft="15dip"
+ android:paddingRight="15dip"
+ />
+ <com.android.systemui.statusbar.KeyButtonView android:id="@+id/menu"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:paddingLeft="15dip"
+ android:paddingRight="15dip"
+ android:src="@drawable/ic_sysbar_menu"
+ android:background="@drawable/ic_sysbar_icon_bg"
+ systemui:keyCode="82"
+ android:visibility="invisible"
+ />
<com.android.systemui.statusbar.tablet.ShirtPocket
android:id="@+id/pocket"
android:layout_width="71dip"
android:layout_height="match_parent"
android:background="@drawable/ic_sysbar_icon_bg"
- android:paddingLeft="4dip"
- android:paddingRight="4dip"
+ android:paddingLeft="15dip"
+ android:paddingRight="15dip"
android:animateLayoutChanges="true"
android:clickable="true"
android:descendantFocusability="blocksDescendants"
@@ -156,42 +185,6 @@
android:gravity="center"
/>
</com.android.systemui.statusbar.tablet.ShirtPocket>
- <com.android.systemui.statusbar.KeyButtonView android:id="@+id/menu"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_menu"
- android:background="@drawable/ic_sysbar_icon_bg"
- android:paddingLeft="4dip"
- android:paddingRight="4dip"
- systemui:keyCode="82"
- android:visibility="invisible"
- />
- <ImageButton android:id="@+id/recent"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:src="@drawable/ic_sysbar_recent"
- android:background="@drawable/ic_sysbar_icon_bg"
- android:paddingLeft="4dip"
- android:paddingRight="4dip"
- />
- <com.android.systemui.statusbar.KeyButtonView android:id="@+id/home"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:paddingLeft="4dip"
- android:paddingRight="4dip"
- android:src="@drawable/ic_sysbar_home"
- android:background="@drawable/ic_sysbar_icon_bg"
- systemui:keyCode="3"
- />
- <com.android.systemui.statusbar.KeyButtonView android:id="@+id/back"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:paddingLeft="4dip"
- android:paddingRight="4dip"
- android:src="@drawable/ic_sysbar_back"
- android:background="@drawable/ic_sysbar_icon_bg"
- systemui:keyCode="4"
- />
</LinearLayout>
</RelativeLayout>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
new file mode 100644
index 0000000..ff59db0
--- /dev/null
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Vymazat"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Žádná oznámení"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Probíhající"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Oznámení"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"Prosím připojte dobíjecí zařízení"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"Baterie je vybitá:"</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"Zbývá <xliff:g id="NUMBER">%d%%</xliff:g> nebo méně."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Využití baterie"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
new file mode 100644
index 0000000..9389617
--- /dev/null
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Ryd"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ingen meddelelser"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"I gang"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meddelelser"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"Forbind oplader"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"Batteriet er ved at være fladt:"</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"<xliff:g id="NUMBER">%d%%</xliff:g> eller mindre tilbage."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Batteriforbrug"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
new file mode 100644
index 0000000..3ea65d9
--- /dev/null
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Löschen"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Keine Benachrichtigungen"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktuell"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Benachrichtigungen"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"Ladegerät anschließen"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"Akku ist fast leer."</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"<xliff:g id="NUMBER">%d%%</xliff:g> oder weniger verbleiben."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Akkuverbrauch"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
new file mode 100644
index 0000000..cba1047
--- /dev/null
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Εκκαθάριση"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Δεν υπάρχουν ειδοποιήσεις"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Εν εξελίξει"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Ειδοποιήσεις"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"Συνδέστε τον φορτιστή"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"Η στάθμη της μπαταρίας είναι χαμηλή:"</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"Απομένει <xliff:g id="NUMBER">%d%%</xliff:g> ή λιγότερο."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Χρήση μπαταρίας"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..56dead5
--- /dev/null
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Borrar"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"No hay notificaciones"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Continuo"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificaciones"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"Conecta el cargador"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"Hay poca batería:"</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"Restan <xliff:g id="NUMBER">%d%%</xliff:g> o menos."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Uso de la batería"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
new file mode 100644
index 0000000..4ebe492
--- /dev/null
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Borrar"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"No tienes notificaciones"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Entrante"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificaciones"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"Conecta el cargador"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"Se está agotando la batería:"</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"<xliff:g id="NUMBER">%d%%</xliff:g> o menos disponible"</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Uso de la batería"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
new file mode 100644
index 0000000..7aff506
--- /dev/null
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Effacer"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Aucune notification"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"En cours"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifications"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"Branchez le chargeur"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"Le niveau de la batterie est bas :"</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"Maximum <xliff:g id="NUMBER">%d%%</xliff:g> restants."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Utilisation de la batterie"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
new file mode 100644
index 0000000..496a82e
--- /dev/null
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Cancella"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Nessuna notifica"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"In corso"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notifiche"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"Collegare il caricabatterie"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"Batteria quasi scarica:"</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"<xliff:g id="NUMBER">%d%%</xliff:g> rimanente o meno."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Utilizzo batteria"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
new file mode 100644
index 0000000..24c018b
--- /dev/null
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"通知を消去"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"通知なし"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"実行中"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"充電してください"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"電池が残り少なくなっています:"</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"残り<xliff:g id="NUMBER">%d%%</xliff:g>未満です。"</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"電池使用量"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
new file mode 100644
index 0000000..0b6649d
--- /dev/null
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"지우기"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"알림 없음"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"진행 중"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"알림"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"충전기를 연결하세요."</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"배터리 전원이 부족합니다."</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"잔여 배터리가 <xliff:g id="NUMBER">%d%%</xliff:g> 이하입니다."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"배터리 사용량"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
new file mode 100644
index 0000000..5684e57
--- /dev/null
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Fjern"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Ingen varslinger"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Aktiviteter"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Varslinger"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"Koble til en lader"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"Batteriet er nesten tomt:"</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"mindre enn <xliff:g id="NUMBER">%d%%</xliff:g> igjen."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Batteribruk"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
new file mode 100644
index 0000000..cd10b29
--- /dev/null
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Wissen"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Geen meldingen"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Actief"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meldingen"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"Sluit de oplader aan"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"De accu raakt op:"</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"<xliff:g id="NUMBER">%d%%</xliff:g> of minder resterend."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Accugebruik"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
new file mode 100644
index 0000000..70f3ad2
--- /dev/null
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Wyczyść"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Brak powiadomień"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Bieżące"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Powiadomienia"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"Podłącz ładowarkę"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"Bateria się rozładowuje:"</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"Pozostało: <xliff:g id="NUMBER">%d%%</xliff:g> lub mniej."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Użycie baterii"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..492063a
--- /dev/null
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Limpar"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Sem notificações"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Em curso"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificações"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"Ligue o carregador"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"A bateria está a ficar fraca:"</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"Restam <xliff:g id="NUMBER">%d%%</xliff:g> ou menos."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Utilização da bateria"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
new file mode 100644
index 0000000..08effa7
--- /dev/null
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Limpar"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Sem notificações"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Em andamento"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Notificações"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"Conecte o carregador"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"A bateria está ficando baixa:"</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"<xliff:g id="NUMBER">%d%%</xliff:g> ou menos restante(s)."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Uso da bateria"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
new file mode 100644
index 0000000..7c5bcf7
--- /dev/null
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Очистить"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Нет уведомлений"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Текущие"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Уведомления"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"Подключите зарядное устройство"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"Батарея разряжена:"</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"Осталось <xliff:g id="NUMBER">%d%%</xliff:g> или меньше."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Расход заряда батареи"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
new file mode 100644
index 0000000..1127c9d
--- /dev/null
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Ta bort"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Inga aviseringar"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Pågående"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Meddelanden"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"Anslut laddaren"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"Batteriet håller på att ta slut:"</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"<xliff:g id="NUMBER">%d%%</xliff:g> eller mindre kvar."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Batteriförbrukning"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
new file mode 100644
index 0000000..dd66d82
--- /dev/null
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"Temizle"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Bildirim yok"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"Sürüyor"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"Bildirimler"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"Lütfen şarj cihazını takın"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"Pil tükeniyor:"</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"<xliff:g id="NUMBER">%d%%</xliff:g> veya daha az kaldı."</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"Pil kullanımı"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..cda0317
--- /dev/null
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"清除"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"无通知"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"正在进行的"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"请连接充电器"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"电量所剩不多:"</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"电量剩余 <xliff:g id="NUMBER">%d%%</xliff:g> 或更少。"</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"电量使用情况"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..503087b
--- /dev/null
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * 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.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- no translation found for app_label (4489004083283879149) -->
+ <skip />
+ <string name="status_bar_clear_all_button" msgid="7774721344716731603">"清除"</string>
+ <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"沒有通知"</string>
+ <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"進行中"</string>
+ <string name="status_bar_latest_events_title" msgid="6594767438577593172">"通知"</string>
+ <string name="battery_low_title" msgid="7923774589611311406">"請連接充電器"</string>
+ <string name="battery_low_subtitle" msgid="7388781709819722764">"電池電量即將不足:"</string>
+ <string name="battery_low_percent_format" msgid="696154104579022959">"還剩 <xliff:g id="NUMBER">%d%%</xliff:g> 以下。"</string>
+ <string name="battery_low_why" msgid="7279169609518386372">"電池使用狀況"</string>
+</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java
index 7c7d74c..2b4f9d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationIconArea.java
@@ -32,13 +32,11 @@ public class NotificationIconArea extends LinearLayout {
private static final String TAG = "NotificationIconArea";
IconLayout mIconLayout;
- DraggerView mDraggerView;
public NotificationIconArea(Context context, AttributeSet attrs) {
super(context, attrs);
mIconLayout = (IconLayout)findViewById(R.id.icons);
- mDraggerView = (DraggerView) findViewById(R.id.handle);
}
static class IconLayout extends LinearLayout {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
index 6426e7e..d11aba6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarService.java
@@ -77,7 +77,7 @@ public class TabletStatusBarService extends StatusBarService {
private NotificationData mNotns = new NotificationData();
TabletStatusBarView mStatusBarView;
- View mNotificationTrigger;
+ ImageView mNotificationTrigger;
NotificationIconArea mNotificationIconArea;
View mNotificationButtons;
View mSystemInfo;
@@ -132,7 +132,7 @@ public class TabletStatusBarService extends StatusBarService {
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
PixelFormat.TRANSLUCENT);
- lp.gravity = Gravity.BOTTOM | Gravity.LEFT;
+ lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
lp.setTitle("NotificationPanel");
lp.windowAnimations = com.android.internal.R.style.Animation_SlidingCard;
@@ -192,7 +192,7 @@ public class TabletStatusBarService extends StatusBarService {
mCurtains.setOnLongClickListener(on);
// the button to open the notification area
- mNotificationTrigger = sb.findViewById(R.id.expand);
+ mNotificationTrigger = (ImageView) sb.findViewById(R.id.notificationTrigger);
mNotificationTrigger.setOnClickListener(mOnClickListener);
// the more notifications icon
@@ -222,6 +222,7 @@ public class TabletStatusBarService extends StatusBarService {
// set the initial view visibility
setAreThereNotifications();
+ refreshNotificationTrigger();
// Add the windows
addPanelWindows();
@@ -253,6 +254,7 @@ public class TabletStatusBarService extends StatusBarService {
R.anim.notification_icons_out);
setViewVisibility(mNotificationButtons, View.VISIBLE,
R.anim.notification_buttons_in);
+ refreshNotificationTrigger();
}
break;
case MSG_CLOSE_NOTIFICATION_PANEL:
@@ -263,6 +265,7 @@ public class TabletStatusBarService extends StatusBarService {
R.anim.notification_icons_in);
setViewVisibility(mNotificationButtons, View.GONE,
R.anim.notification_buttons_out);
+ refreshNotificationTrigger();
}
break;
case MSG_OPEN_SYSTEM_PANEL:
@@ -276,6 +279,22 @@ public class TabletStatusBarService extends StatusBarService {
}
}
}
+
+ public void refreshNotificationTrigger() {
+ if (mNotificationTrigger == null) return;
+
+ int resId;
+ boolean panel = (mNotificationPanel != null
+ && mNotificationPanel.getVisibility() == View.VISIBLE);
+ if (!mNotificationsOn) {
+ resId = R.drawable.ic_sysbar_noti_dnd;
+ } else if (mNotns.size() > 0) {
+ resId = panel ? R.drawable.ic_sysbar_noti_avail_open : R.drawable.ic_sysbar_noti_avail;
+ } else {
+ resId = panel ? R.drawable.ic_sysbar_noti_none_open : R.drawable.ic_sysbar_noti_none;
+ }
+ mNotificationTrigger.setImageResource(resId);
+ }
public void setBatteryMeter(int level, boolean plugged) {
if (DEBUG) Slog.d(TAG, "battery=" + level + (plugged ? " - plugged" : " - unplugged"));
@@ -598,21 +617,30 @@ public class TabletStatusBarService extends StatusBarService {
// system process is dead if we're here.
}
animateCollapse();
+ refreshNotificationTrigger();
}
void onClickDoNotDisturb() {
mNotificationsOn = !mNotificationsOn;
+ mIconLayout.setVisibility(mNotificationsOn ? View.VISIBLE : View.INVISIBLE); // TODO: animation
animateCollapse();
+ refreshNotificationTrigger();
}
public void onClickNotificationTrigger() {
if (DEBUG) Slog.d(TAG, "clicked notification icons");
if ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0) {
- int msg = (mNotificationPanel.getVisibility() == View.GONE)
- ? MSG_OPEN_NOTIFICATION_PANEL
- : MSG_CLOSE_NOTIFICATION_PANEL;
- mHandler.removeMessages(msg);
- mHandler.sendEmptyMessage(msg);
+ if (!mNotificationsOn) {
+ mNotificationsOn = true;
+ mIconLayout.setVisibility(View.VISIBLE); // TODO: animation
+ refreshNotificationTrigger();
+ } else {
+ int msg = (mNotificationPanel.getVisibility() == View.GONE)
+ ? MSG_OPEN_NOTIFICATION_PANEL
+ : MSG_CLOSE_NOTIFICATION_PANEL;
+ mHandler.removeMessages(msg);
+ mHandler.sendEmptyMessage(msg);
+ }
}
}
@@ -757,6 +785,8 @@ public class TabletStatusBarService extends StatusBarService {
for (int i=0; i<N; i++) {
mPile.addView(mNotns.get(N-i-1).row);
}
+
+ refreshNotificationTrigger();
}
private boolean inflateViews(NotificationData.Entry entry, ViewGroup parent) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index db5f6c1..39224ba 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -58,6 +58,7 @@ import android.util.Config;
import android.util.EventLog;
import android.util.Log;
import android.util.SparseArray;
+import android.util.TypedValue;
import android.view.ActionMode;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
@@ -83,6 +84,7 @@ import android.view.animation.AnimationUtils;
import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
+import android.widget.PopupWindow;
import android.widget.ProgressBar;
import android.widget.TextView;
@@ -1700,6 +1702,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private ActionMode mActionMode;
private ActionBarContextView mActionModeView;
+ private PopupWindow mActionModePopup;
public DecorView(Context context, int featureId) {
super(context);
@@ -2019,9 +2022,18 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (mActionModeView == null) {
if (hasFeature(FEATURE_ACTION_MODE_OVERLAY)) {
mActionModeView = new ActionBarContextView(mContext);
- FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
- MATCH_PARENT, WRAP_CONTENT);
- addView(mActionModeView, params);
+ mActionModePopup = new PopupWindow(mContext);
+ mActionModePopup.setLayoutInScreenEnabled(true);
+ mActionModePopup.setClippingEnabled(false);
+ mActionModePopup.setContentView(mActionModeView);
+ mActionModePopup.setWidth(MATCH_PARENT);
+
+ TypedValue heightValue = new TypedValue();
+ mContext.getTheme().resolveAttribute(
+ com.android.internal.R.attr.actionBarSize, heightValue, false);
+ final int height = TypedValue.complexToDimensionPixelSize(heightValue.data,
+ mContext.getResources().getDisplayMetrics());
+ mActionModePopup.setHeight(height);
} else {
ViewStub stub = (ViewStub) findViewById(
com.android.internal.R.id.action_mode_bar_stub);
@@ -2038,6 +2050,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
mActionModeView.initForMode(mode);
mActionModeView.setVisibility(View.VISIBLE);
mActionMode = mode;
+ if (mActionModePopup != null) {
+ mActionModePopup.showAtLocation(this,
+ Gravity.TOP | Gravity.FILL_HORIZONTAL, 0, 0);
+ }
} else {
mActionMode = null;
}
@@ -2250,6 +2266,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
public void onDestroyActionMode(ActionMode mode) {
mWrapped.onDestroyActionMode(mode);
+ if (mActionModePopup != null) {
+ mActionModePopup.dismiss();
+ } else if (mActionModeView != null) {
+ mActionModeView.setVisibility(GONE);
+ }
if (mActionModeView != null) {
mActionModeView.removeAllViews();
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 2bfdc29..535f07f 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -151,7 +151,10 @@ sp<ICamera> CameraService::connect(
LOGE("Fail to open camera hardware (id=%d)", cameraId);
return NULL;
}
- client = new Client(this, cameraClient, hardware, cameraId, callingPid);
+ CameraInfo info;
+ HAL_getCameraInfo(cameraId, &info);
+ client = new Client(this, cameraClient, hardware, cameraId, info.facing,
+ callingPid);
mClient[cameraId] = client;
LOG1("CameraService::connect X");
return client;
@@ -293,7 +296,7 @@ void CameraService::playSound(sound_kind kind) {
CameraService::Client::Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
const sp<CameraHardwareInterface>& hardware,
- int cameraId, int clientPid) {
+ int cameraId, int cameraFacing, int clientPid) {
int callingPid = getCallingPid();
LOG1("Client::Client E (pid %d)", callingPid);
@@ -301,6 +304,7 @@ CameraService::Client::Client(const sp<CameraService>& cameraService,
mCameraClient = cameraClient;
mHardware = hardware;
mCameraId = cameraId;
+ mCameraFacing = cameraFacing;
mClientPid = clientPid;
mUseOverlay = mHardware->useOverlay();
mMsgEnabled = 0;
@@ -318,8 +322,7 @@ CameraService::Client::Client(const sp<CameraService>& cameraService,
// Callback is disabled by default
mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
- mOrientation = 0;
- mPreviewWindowFlag = 0;
+ mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
mOrientationChanged = false;
mPlayShutterSound = true;
cameraService->setCameraBusy(cameraId);
@@ -509,7 +512,7 @@ status_t CameraService::Client::setPreviewDisplay(const sp<Surface>& surface) {
result = setOverlay();
} else if (mPreviewWindow != 0) {
native_window_set_buffers_transform(mPreviewWindow.get(),
- mPreviewWindowFlag);
+ mOrientation);
result = mHardware->setPreviewWindow(mPreviewWindow);
}
}
@@ -637,7 +640,7 @@ status_t CameraService::Client::startPreviewMode() {
} else {
if (mPreviewWindow != 0) {
native_window_set_buffers_transform(mPreviewWindow.get(),
- mPreviewWindowFlag);
+ mOrientation);
}
mHardware->setPreviewWindow(mPreviewWindow);
result = mHardware->startPreview();
@@ -844,26 +847,10 @@ status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t a
if (mHardware->previewEnabled()) {
return INVALID_OPERATION;
}
- switch (arg1) {
- case 0:
- orientation = ISurface::BufferHeap::ROT_0;
- mPreviewWindowFlag = 0;
- break;
- case 90:
- orientation = ISurface::BufferHeap::ROT_90;
- mPreviewWindowFlag = NATIVE_WINDOW_TRANSFORM_ROT_90;
- break;
- case 180:
- orientation = ISurface::BufferHeap::ROT_180;
- mPreviewWindowFlag = NATIVE_WINDOW_TRANSFORM_ROT_180;
- break;
- case 270:
- orientation = ISurface::BufferHeap::ROT_270;
- mPreviewWindowFlag = NATIVE_WINDOW_TRANSFORM_ROT_270;
- break;
- default:
- return BAD_VALUE;
- }
+ // Mirror the preview if the camera is front-facing.
+ orientation = getOrientation(arg1, mCameraFacing == CAMERA_FACING_FRONT);
+ if (orientation == -1) return BAD_VALUE;
+
if (mOrientation != orientation) {
mOrientation = orientation;
if (mOverlayRef != 0) mOrientationChanged = true;
@@ -1226,6 +1213,28 @@ void CameraService::Client::copyFrameAndPostCopiedFrame(
client->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
}
+int CameraService::Client::getOrientation(int degrees, bool mirror) {
+ if (!mirror) {
+ if (degrees == 0) return 0;
+ else if (degrees == 90) return HAL_TRANSFORM_ROT_90;
+ else if (degrees == 180) return HAL_TRANSFORM_ROT_180;
+ else if (degrees == 270) return HAL_TRANSFORM_ROT_270;
+ } else { // Do mirror (horizontal flip)
+ if (degrees == 0) { // FLIP_H and ROT_0
+ return HAL_TRANSFORM_FLIP_H;
+ } else if (degrees == 90) { // FLIP_H and ROT_90
+ return HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90;
+ } else if (degrees == 180) { // FLIP_H and ROT_180
+ return HAL_TRANSFORM_FLIP_V;
+ } else if (degrees == 270) { // FLIP_H and ROT_270
+ return HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90;
+ }
+ }
+ LOGE("Invalid setDisplayOrientation degrees=%d", degrees);
+ return -1;
+}
+
+
// ----------------------------------------------------------------------------
static const int kDumpLockRetries = 50;
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index b5b85bc..60e0d04 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -117,6 +117,7 @@ private:
const sp<ICameraClient>& cameraClient,
const sp<CameraHardwareInterface>& hardware,
int cameraId,
+ int cameraFacing,
int clientPid);
~Client();
@@ -165,6 +166,8 @@ private:
const sp<IMemoryHeap>& heap,
size_t offset, size_t size);
+ int getOrientation(int orientation, bool mirror);
+
// these are initialized in the constructor.
sp<CameraService> mCameraService; // immutable after constructor
sp<ICameraClient> mCameraClient;
@@ -180,7 +183,6 @@ private:
int mOrientation; // Current display orientation
// True if display orientation has been changed. This is only used in overlay.
int mOrientationChanged;
- int mPreviewWindowFlag;
bool mPlayShutterSound;
// Ensures atomicity among the public methods
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index c50a01e..7c758a2 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -7166,7 +7166,9 @@ class PackageManagerService extends IPackageManager.Stub {
pw.print(" resourcePath="); pw.println(ps.resourcePathString);
pw.print(" nativeLibraryPath="); pw.println(ps.nativeLibraryPathString);
pw.print(" obbPath="); pw.println(ps.obbPathString);
+ pw.print(" versionCode="); pw.println(ps.versionCode);
if (ps.pkg != null) {
+ pw.print(" versionName="); pw.println(ps.pkg.mVersionName);
pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir);
pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion);
if (ps.pkg.mOperationPending) {
@@ -7224,8 +7226,6 @@ class PackageManagerService extends IPackageManager.Stub {
pw.print(" pkgFlags=0x"); pw.print(Integer.toHexString(ps.pkgFlags));
pw.print(" installStatus="); pw.print(ps.installStatus);
pw.print(" enabled="); pw.println(ps.enabled);
- pw.print(" versionCode="); pw.print(ps.versionCode);
- pw.print(" versionName="); pw.println(ps.pkg.mVersionName);
if (ps.disabledComponents.size() > 0) {
pw.println(" disabledComponents:");
for (String s : ps.disabledComponents) {
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 76588eb..b3e9f9d 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -1794,8 +1794,12 @@ class PowerManagerService extends IPowerManager.Stub
private void updateLightsLocked(int newState, int forceState) {
final int oldState = mPowerState;
- newState = applyButtonState(newState);
- newState = applyKeyboardState(newState);
+ if ((newState & SCREEN_ON_BIT) != 0) {
+ // Only turn on the buttons or keyboard if the screen is also on.
+ // We should never see the buttons on but not the screen.
+ newState = applyButtonState(newState);
+ newState = applyKeyboardState(newState);
+ }
final int realDifference = (newState ^ oldState);
final int difference = realDifference | forceState;
if (difference == 0) {
@@ -1898,6 +1902,16 @@ class PowerManagerService extends IPowerManager.Stub
INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue);
}
+ if (mSpew) {
+ Slog.d(TAG, "offMask=0x" + Integer.toHexString(offMask)
+ + " dimMask=0x" + Integer.toHexString(dimMask)
+ + " onMask=0x" + Integer.toHexString(onMask)
+ + " difference=0x" + Integer.toHexString(difference)
+ + " realDifference=0x" + Integer.toHexString(realDifference)
+ + " forceState=0x" + Integer.toHexString(forceState)
+ );
+ }
+
if (offMask != 0) {
if (mSpew) Slog.i(TAG, "Setting brightess off: " + offMask);
setLightBrightness(offMask, Power.BRIGHTNESS_OFF);
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index f5b7ca9..747af26 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -357,7 +357,6 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
if (!checkNotifyPermission("notifyDataActivity()" )) {
return;
}
- handleRemoveListLocked();
synchronized (mRecords) {
mDataActivity = state;
for (Record r : mRecords) {
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 7258729..9bc24d2 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -552,6 +552,7 @@ public class WindowManagerService extends IWindowManager.Stub
mInputManager.unregisterInputChannel(mServerChannel);
InputQueue.unregisterInputChannel(mClientChannel);
mClientChannel.dispose();
+ mServerChannel.dispose();
mClientChannel = null;
mServerChannel = null;
}
@@ -624,7 +625,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
if (DEBUG_DRAG) {
- Slog.d(TAG, "sending DRAG_STARTED to new window " + newWin);
+ Slog.d(TAG, "need to send DRAG_STARTED to new window " + newWin);
}
sendDragStartedLw(newWin, mCurrentX, mCurrentY, mDataDescription);
}
@@ -6242,8 +6243,14 @@ public class WindowManagerService extends IWindowManager.Stub
mDragState.register();
mInputMonitor.updateInputWindowsLw();
- mInputManager.transferTouchFocus(callingWin.mInputChannel,
- mDragState.mServerChannel);
+ if (!mInputManager.transferTouchFocus(callingWin.mInputChannel,
+ mDragState.mServerChannel)) {
+ Slog.e(TAG, "Unable to transfer touch focus");
+ mDragState.unregister();
+ mDragState = null;
+ mInputMonitor.updateInputWindowsLw();
+ return false;
+ }
mDragState.mData = data;
mDragState.mCurrentX = touchX;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index b0ace2f..8d36e4f 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -6676,6 +6676,9 @@ public final class ActivityManagerService extends ActivityManagerNative
if (info.violationNumThisLoop != 0) {
sb.append("Loop-Violation-Number: ").append(info.violationNumThisLoop).append("\n");
}
+ if (info.numAnimationsRunning != 0) {
+ sb.append("Animations-Running: ").append(info.numAnimationsRunning).append("\n");
+ }
if (info != null && info.durationMillis != -1) {
sb.append("Duration-Millis: ").append(info.durationMillis).append("\n");
}
@@ -7152,7 +7155,7 @@ public final class ActivityManagerService extends ActivityManagerNative
} else if (adj >= SECONDARY_SERVER_ADJ) {
currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
} else if (adj >= HEAVY_WEIGHT_APP_ADJ) {
- currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_HEAVY_WEIGHT;
+ currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
} else if (adj >= PERCEPTIBLE_APP_ADJ) {
currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
} else if (adj >= VISIBLE_APP_ADJ) {
@@ -7284,7 +7287,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
return;
} else if ("service".equals(cmd)) {
- dumpService(fd, pw, args, opti, dumpAll);
+ dumpService(fd, pw, args, opti);
return;
} else if ("services".equals(cmd) || "s".equals(cmd)) {
synchronized (this) {
@@ -7643,8 +7646,7 @@ public final class ActivityManagerService extends ActivityManagerNative
* - the first arg isn't the flattened component name of an existing service:
* dump all services whose component contains the first arg as a substring
*/
- protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args,
- int opti, boolean dumpAll) {
+ protected void dumpService(FileDescriptor fd, PrintWriter pw, String[] args, int opti) {
String[] newArgs;
String componentNameString;
ServiceRecord r;
@@ -7664,7 +7666,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (r != null) {
- dumpService(fd, pw, r, newArgs, dumpAll);
+ dumpService(fd, pw, r, newArgs);
} else {
ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>();
synchronized (this) {
@@ -7676,7 +7678,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
for (int i=0; i<services.size(); i++) {
- dumpService(fd, pw, services.get(i), newArgs, dumpAll);
+ dumpService(fd, pw, services.get(i), newArgs);
}
}
}
@@ -7685,16 +7687,10 @@ public final class ActivityManagerService extends ActivityManagerNative
* Invokes IApplicationThread.dumpService() on the thread of the specified service if
* there is a thread associated with the service.
*/
- private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args,
- boolean dumpAll) {
- pw.println(" Service " + r.name.flattenToString());
- if (dumpAll) {
- synchronized (this) {
- pw.print(" * "); pw.println(r);
- r.dump(pw, " ");
- }
- pw.println("");
- }
+ private void dumpService(FileDescriptor fd, PrintWriter pw, ServiceRecord r, String[] args) {
+ pw.println("------------------------------------------------------------"
+ + "-------------------");
+ pw.println("APP SERVICE: " + r.name.flattenToString());
if (r.app != null && r.app.thread != null) {
try {
// flush anything that is already in the PrintWriter since the thread is going
diff --git a/services/java/com/android/server/location/GpsLocationProvider.java b/services/java/com/android/server/location/GpsLocationProvider.java
index 4a6b5f4..755a228 100755
--- a/services/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/java/com/android/server/location/GpsLocationProvider.java
@@ -1451,23 +1451,30 @@ public class GpsLocationProvider implements LocationProviderInterface {
mContext.getSystemService(Context.TELEPHONY_SERVICE);
if (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) {
GsmCellLocation gsm_cell = (GsmCellLocation) phone.getCellLocation();
- if ((gsm_cell != null) && (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM)
- && (phone.getNetworkOperator().length() > 3)) {
+ if ((gsm_cell != null) && (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_GSM) &&
+ (phone.getNetworkOperator() != null) &&
+ (phone.getNetworkOperator().length() > 3)) {
int type;
int mcc = Integer.parseInt(phone.getNetworkOperator().substring(0,3));
int mnc = Integer.parseInt(phone.getNetworkOperator().substring(3));
- if (phone.getNetworkType() == TelephonyManager.NETWORK_TYPE_UMTS)
+ int networkType = phone.getNetworkType();
+ if (networkType == TelephonyManager.NETWORK_TYPE_UMTS
+ || networkType == TelephonyManager.NETWORK_TYPE_HSDPA
+ || networkType == TelephonyManager.NETWORK_TYPE_HSUPA
+ || networkType == TelephonyManager.NETWORK_TYPE_HSPA) {
type = AGPS_REF_LOCATION_TYPE_UMTS_CELLID;
- else
+ } else {
type = AGPS_REF_LOCATION_TYPE_GSM_CELLID;
+ }
native_agps_set_ref_location_cellid(type, mcc, mnc,
gsm_cell.getLac(), gsm_cell.getCid());
- }
- else
+ } else {
Log.e(TAG,"Error getting cell location info.");
+ }
}
- else
+ else {
Log.e(TAG,"CDMA not supported.");
+ }
}
private void sendMessage(int message, int arg, Object obj) {
diff --git a/tests/DpiTest/AndroidManifest.xml b/tests/DpiTest/AndroidManifest.xml
index 68ecc6e..a4d8c79 100644
--- a/tests/DpiTest/AndroidManifest.xml
+++ b/tests/DpiTest/AndroidManifest.xml
@@ -18,6 +18,12 @@
package="com.google.android.test.dpi">
<uses-sdk android:minSdkVersion="3" android:targetSdkVersion="3" />
<supports-screens android:smallScreens="true" />
+ <compatible-screens>
+ <screen android:screenSize="small" android:screenDensity="ldpi" />
+ <screen android:screenSize="small" android:screenDensity="xhdpi" />
+ <screen android:screenSize="large" android:screenDensity="hdpi" />
+ <screen android:screenSize="xlarge" android:screenDensity="mdpi" />
+ </compatible-screens>
<application android:label="DpiTest">
<activity android:name="DpiTestActivity">
<intent-filter>
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 4469e68..e9833c9 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -334,13 +334,15 @@ enum {
REQ_FIVE_WAY_NAV_ATTR = 0x01010232,
TARGET_SDK_VERSION_ATTR = 0x01010270,
TEST_ONLY_ATTR = 0x01010272,
- DENSITY_ATTR = 0x0101026c,
+ ANY_DENSITY_ATTR = 0x0101026c,
GL_ES_VERSION_ATTR = 0x01010281,
SMALL_SCREEN_ATTR = 0x01010284,
NORMAL_SCREEN_ATTR = 0x01010285,
LARGE_SCREEN_ATTR = 0x01010286,
XLARGE_SCREEN_ATTR = 0x010102bf,
REQUIRED_ATTR = 0x0101028e,
+ SCREEN_SIZE_ATTR = 0x010102ca,
+ SCREEN_DENSITY_ATTR = 0x010102cb,
};
const char *getComponentName(String8 &pkgName, String8 &componentName) {
@@ -357,6 +359,42 @@ const char *getComponentName(String8 &pkgName, String8 &componentName) {
return retStr.string();
}
+static void printCompatibleScreens(ResXMLTree& tree) {
+ size_t len;
+ ResXMLTree::event_code_t code;
+ int depth = 0;
+ bool first = true;
+ printf("compatible-screens:");
+ while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
+ if (code == ResXMLTree::END_TAG) {
+ depth--;
+ if (depth < 0) {
+ break;
+ }
+ continue;
+ }
+ if (code != ResXMLTree::START_TAG) {
+ continue;
+ }
+ depth++;
+ String8 tag(tree.getElementName(&len));
+ if (tag == "screen") {
+ int32_t screenSize = getIntegerAttribute(tree,
+ SCREEN_SIZE_ATTR, NULL, -1);
+ int32_t screenDensity = getIntegerAttribute(tree,
+ SCREEN_DENSITY_ATTR, NULL, -1);
+ if (screenSize > 0 && screenDensity > 0) {
+ if (!first) {
+ printf(",");
+ }
+ first = false;
+ printf("'%d/%d'", screenSize, screenDensity);
+ }
+ }
+ }
+ printf("\n");
+}
+
/*
* Handle the "dump" command, to extract select data from an archive.
*/
@@ -575,6 +613,7 @@ int doDump(Bundle* bundle)
int normalScreen = 1;
int largeScreen = 1;
int xlargeScreen = 1;
+ int anyDensity = 1;
String8 pkg;
String8 activityName;
String8 activityLabel;
@@ -742,14 +781,6 @@ int doDump(Bundle* bundle)
printf(" reqFiveWayNav='%d'", reqFiveWayNav);
}
printf("\n");
- } else if (tag == "supports-density") {
- int32_t dens = getIntegerAttribute(tree, DENSITY_ATTR, &error);
- if (error != "") {
- fprintf(stderr, "ERROR getting 'android:density' attribute: %s\n",
- error.string());
- goto bail;
- }
- printf("supports-density:'%d'\n", dens);
} else if (tag == "supports-screens") {
smallScreen = getIntegerAttribute(tree,
SMALL_SCREEN_ATTR, NULL, 1);
@@ -759,6 +790,8 @@ int doDump(Bundle* bundle)
LARGE_SCREEN_ATTR, NULL, 1);
xlargeScreen = getIntegerAttribute(tree,
XLARGE_SCREEN_ATTR, NULL, 1);
+ anyDensity = getIntegerAttribute(tree,
+ ANY_DENSITY_ATTR, NULL, 1);
} else if (tag == "uses-feature") {
String8 name = getAttribute(tree, NAME_ATTR, &error);
@@ -883,6 +916,9 @@ int doDump(Bundle* bundle)
error.string());
goto bail;
}
+ } else if (tag == "compatible-screens") {
+ printCompatibleScreens(tree);
+ depth--;
}
} else if (depth == 3 && withinApplication) {
withinActivity = false;
@@ -1109,6 +1145,9 @@ int doDump(Bundle* bundle)
// Introduced in Honeycomb.
xlargeScreen = targetSdk >= 10 ? -1 : 0;
}
+ if (anyDensity > 0) {
+ anyDensity = targetSdk >= 4 ? -1 : 0;
+ }
printf("supports-screens:");
if (smallScreen != 0) printf(" 'small'");
if (normalScreen != 0) printf(" 'normal'");
@@ -1116,6 +1155,8 @@ int doDump(Bundle* bundle)
if (xlargeScreen != 0) printf(" 'xlarge'");
printf("\n");
+ printf("supports-any-density: '%s'\n", anyDensity ? "true" : "false");
+
printf("locales:");
Vector<String8> locales;
res.getLocales(&locales);
diff --git a/tools/layoutlib/bridge/.classpath b/tools/layoutlib/bridge/.classpath
index 175a98b..70140d8 100644
--- a/tools/layoutlib/bridge/.classpath
+++ b/tools/layoutlib/bridge/.classpath
@@ -4,7 +4,7 @@
<classpathentry kind="src" path="tests"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
- <classpathentry combineaccessrules="false" kind="src" path="/layoutlib_api"/>
+ <classpathentry kind="var" path="ANDROID_SRC/prebuilt/common/layoutlib_api/layoutlib_api-prebuilt.jar"/>
<classpathentry kind="var" path="ANDROID_SRC/prebuilt/common/kxml2/kxml2-2.3.0.jar" sourcepath="/ANDROID_SRC/dalvik/libcore/xml/src/main/java"/>
<classpathentry kind="var" path="ANDROID_OUT_FRAMEWORK/layoutlib.jar" sourcepath="/ANDROID_SRC/frameworks/base/core/java"/>
<classpathentry kind="var" path="ANDROID_OUT_FRAMEWORK/ninepatch.jar" sourcepath="/ANDROID_SRC/development/tools/ninepatch/src"/>
diff --git a/tools/layoutlib/bridge/Android.mk b/tools/layoutlib/bridge/Android.mk
index b2010d5..b7a602a 100644
--- a/tools/layoutlib/bridge/Android.mk
+++ b/tools/layoutlib/bridge/Android.mk
@@ -20,7 +20,7 @@ LOCAL_SRC_FILES := $(call all-java-files-under,src)
LOCAL_JAVA_LIBRARIES := \
kxml2-2.3.0 \
- layoutlib_api \
+ layoutlib_api-prebuilt \
ninepatch
LOCAL_STATIC_JAVA_LIBRARIES := temp_layoutlib
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
index 590923f..a9ede26 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
@@ -96,6 +96,7 @@ public class AsmGenerator {
methods.add(methodName);
}
for (String className : createInfo.getDelegateClassNatives()) {
+ className = binaryToInternalClassName(className);
Set<String> methods = mDelegateMethods.get(className);
if (methods == null) {
methods = new HashSet<String>();
@@ -312,6 +313,11 @@ public class AsmGenerator {
rv = new RenameClassAdapter(cw, className, newName);
}
+ ClassVisitor cv = new TransformClassAdapter(mLog, mStubMethods,
+ mDeleteReturns.get(className),
+ newName, rv,
+ stubNativesOnly, stubNativesOnly || hasNativeMethods);
+
Set<String> delegateMethods = mDelegateMethods.get(className);
if (delegateMethods != null && !delegateMethods.isEmpty()) {
// If delegateMethods only contains one entry ALL_NATIVES and the class is
@@ -319,14 +325,10 @@ public class AsmGenerator {
if (hasNativeMethods ||
!(delegateMethods.size() == 1 &&
delegateMethods.contains(DelegateClassAdapter.ALL_NATIVES))) {
- rv = new DelegateClassAdapter(mLog, rv, className, delegateMethods);
+ cv = new DelegateClassAdapter(mLog, cv, className, delegateMethods);
}
}
- TransformClassAdapter cv = new TransformClassAdapter(mLog, mStubMethods,
- mDeleteReturns.get(className),
- newName, rv,
- stubNativesOnly, stubNativesOnly || hasNativeMethods);
cr.accept(cv, 0 /* flags */);
return cw.toByteArray();
}
diff --git a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
index 9ad2e6e..7d80796 100644
--- a/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
+++ b/tools/layoutlib/create/tests/com/android/tools/layoutlib/create/DelegateClassAdapterTest.java
@@ -28,11 +28,8 @@ import org.junit.Before;
import org.junit.Test;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.util.TraceClassVisitor;
import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -178,24 +175,26 @@ public class DelegateClassAdapterTest {
};
cl2.testModifiedInstance();
- } catch (Throwable t) {
- // For debugging, dump the bytecode of the class in case of unexpected error.
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- TraceClassVisitor tcv = new TraceClassVisitor(pw);
-
- ClassReader cr2 = new ClassReader(bytes);
- cr2.accept(tcv, 0 /* flags */);
-
- String msg = "\n" + t.getClass().getCanonicalName();
- if (t.getMessage() != null) {
- msg += ": " + t.getMessage();
- }
- msg = msg + "\nBytecode dump:\n" + sw.toString();
-
- // Re-throw exception with new message
- RuntimeException ex = new RuntimeException(msg, t);
- throw ex;
+ // This code block is useful for debugging. However to make it work you need to
+ // pull in the org.objectweb.asm.util.TraceClassVisitor class and associated
+ // utilities which are found in the ASM source jar.
+ //
+ // } catch (Throwable t) {
+ // For debugging, dump the bytecode of the class in case of unexpected error.
+ // StringWriter sw = new StringWriter();
+ // PrintWriter pw = new PrintWriter(sw);
+ // TraceClassVisitor tcv = new TraceClassVisitor(pw);
+ // ClassReader cr2 = new ClassReader(bytes);
+ // cr2.accept(tcv, 0 /* flags */);
+ // String msg = "\n" + t.getClass().getCanonicalName();
+ // if (t.getMessage() != null) {
+ // msg += ": " + t.getMessage();
+ // }
+ // msg = msg + "\nBytecode dump:\n" + sw.toString();
+ // // Re-throw exception with new message
+ // RuntimeException ex = new RuntimeException(msg, t);
+ // throw ex;
+ } finally {
}
}
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 65b910b..e3deeb3 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -79,7 +79,6 @@ import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Pattern;
@@ -1297,14 +1296,14 @@ public class WifiStateMachine extends HierarchicalStateMachine {
*/
private boolean shouldDisableCoexistenceMode() {
if (mBluetoothHeadset == null) return true;
- Set<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices();
+ List<BluetoothDevice> devices = mBluetoothHeadset.getConnectedDevices();
return (devices.size() != 0 ? false : true);
}
private void checkIsBluetoothPlaying() {
boolean isBluetoothPlaying = false;
if (mBluetoothA2dp != null) {
- Set<BluetoothDevice> connected = mBluetoothA2dp.getConnectedDevices();
+ List<BluetoothDevice> connected = mBluetoothA2dp.getConnectedDevices();
for (BluetoothDevice device : connected) {
if (mBluetoothA2dp.isA2dpPlaying(device)) {