summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--api/current.xml898
-rw-r--r--awt/com/android/internal/awt/AndroidGraphics2D.java4
-rw-r--r--camera/libcameraservice/Android.mk10
-rw-r--r--camera/libcameraservice/CameraService.cpp60
-rw-r--r--camera/libcameraservice/CameraService.h2
-rw-r--r--camera/tests/CameraServiceTest/Android.mk12
-rwxr-xr-xcmds/am/am1
-rwxr-xr-xcmds/bmgr/bmgr1
-rw-r--r--cmds/bootanimation/Android.mk8
-rwxr-xr-xcmds/ime/ime1
-rw-r--r--cmds/installd/commands.c156
-rw-r--r--cmds/installd/installd.h1
-rwxr-xr-xcmds/pm/pm1
-rw-r--r--cmds/zipalign/Android.mk25
-rw-r--r--core/java/android/app/ApplicationErrorReport.java2
-rw-r--r--core/java/android/app/ContextImpl.java5
-rw-r--r--core/java/android/bluetooth/BluetoothClass.java8
-rw-r--r--core/java/android/bluetooth/BluetoothHid.java279
-rw-r--r--core/java/android/bluetooth/BluetoothUuid.java8
-rw-r--r--core/java/android/bluetooth/IBluetoothHid.aidl32
-rwxr-xr-x[-rw-r--r--]core/java/android/content/res/Resources.java142
-rw-r--r--core/java/android/hardware/Camera.java402
-rw-r--r--core/java/android/hardware/CameraSwitch.java80
-rw-r--r--core/java/android/hardware/HtcFrontFacingCamera.java14
-rw-r--r--core/java/android/net/ConnectivityManager.java3
-rw-r--r--core/java/android/net/NetworkInfo.java9
-rw-r--r--core/java/android/net/Proxy.java80
-rw-r--r--core/java/android/net/http/Headers.java9
-rw-r--r--core/java/android/os/Debug.java17
-rw-r--r--core/java/android/preference/ListPreference.java48
-rw-r--r--core/java/android/provider/Settings.java394
-rw-r--r--core/java/android/provider/Telephony.java4
-rw-r--r--core/java/android/server/BluetoothA2dpService.java43
-rw-r--r--core/java/android/server/BluetoothEventLoop.java19
-rw-r--r--core/java/android/server/BluetoothHidService.java462
-rw-r--r--core/java/android/server/BluetoothService.java10
-rw-r--r--core/java/android/text/Layout.java51
-rw-r--r--core/java/android/text/SpannableStringBuilder.java6
-rw-r--r--core/java/android/text/StaticLayout.java16
-rw-r--r--core/java/android/text/Styled.java8
-rw-r--r--core/java/android/text/format/Time.java90
-rw-r--r--core/java/android/view/HapticFeedbackConstants.java6
-rw-r--r--core/java/android/view/RawInputEvent.java1
-rw-r--r--core/java/android/view/ViewRoot.java3
-rwxr-xr-xcore/java/android/view/WindowOrientationListener.java90
-rw-r--r--core/java/android/webkit/WebSettings.java8
-rw-r--r--core/java/android/webkit/WebView.java35
-rw-r--r--core/java/android/widget/TabHost.java26
-rw-r--r--core/java/android/widget/TextView.java2
-rw-r--r--core/java/com/android/internal/app/AlertController.java1
-rw-r--r--core/java/com/android/internal/app/ShutdownThread.java47
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java12
-rw-r--r--core/java/com/android/internal/os/SamplingProfilerIntegration.java3
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java86
-rw-r--r--core/java/com/android/internal/widget/LockPatternView.java82
-rw-r--r--core/java/com/google/android/mms/pdu/PduParser.java94
-rw-r--r--core/jni/Android.mk9
-rw-r--r--core/jni/AndroidRuntime.cpp15
-rw-r--r--core/jni/android/graphics/Canvas.cpp2
-rw-r--r--core/jni/android_hardware_Camera.cpp3
-rw-r--r--core/jni/android_net_NetUtils.cpp25
-rw-r--r--core/jni/android_net_wifi_Wifi.cpp54
-rw-r--r--core/jni/android_server_BluetoothEventLoop.cpp15
-rw-r--r--core/jni/android_server_BluetoothHidService.cpp335
-rw-r--r--core/res/res/layout/keyguard_screen_tab_unlock.xml64
-rw-r--r--core/res/res/layout/keyguard_screen_tab_unlock_land.xml60
-rw-r--r--core/res/res/layout/keyguard_screen_unlock_landscape.xml7
-rw-r--r--core/res/res/layout/keyguard_screen_unlock_portrait.xml11
-rw-r--r--core/res/res/layout/recent_apps_dialog.xml1
-rw-r--r--core/res/res/layout/recent_apps_dialog_12.xml129
-rw-r--r--core/res/res/layout/recent_apps_dialog_15.xml141
-rw-r--r--core/res/res/layout/recent_apps_icon_12.xml40
-rw-r--r--core/res/res/layout/recent_apps_icon_15.xml40
-rw-r--r--core/res/res/layout/status_bar_expanded.xml2
-rw-r--r--core/res/res/layout/status_bar_tracking.xml2
-rw-r--r--core/res/res/values-de/strings.xml15
-rw-r--r--core/res/res/values-he-rIL/donottranslate-cldr.xml149
-rw-r--r--core/res/res/values-it/strings.xml7
-rw-r--r--core/res/res/values-ja/strings.xml4
-rw-r--r--core/res/res/values/arrays.xml3
-rw-r--r--core/res/res/values/config.xml6
-rw-r--r--core/res/res/values/donottranslate-cldr.xml1
-rw-r--r--core/res/res/values/strings.xml15
-rw-r--r--core/tests/coretests/src/android/preference/ListPreferenceTest.java45
-rw-r--r--docs/html/resources/articles/painless-threading.jd2
-rw-r--r--graphics/java/android/graphics/Canvas.java328
-rw-r--r--graphics/java/android/graphics/Color.java2
-rw-r--r--graphics/jni/Android.mk8
-rw-r--r--include/camera/CameraParameters.h53
-rw-r--r--include/media/AudioRecord.h6
-rw-r--r--include/media/MediaPlayerInterface.h1
-rw-r--r--include/media/MediaProfiles.h5
-rw-r--r--include/ui/EventHub.h3
-rw-r--r--include/ui/Overlay.h2
-rw-r--r--include/utils/Asset.h6
-rw-r--r--libs/camera/Android.mk12
-rw-r--r--libs/camera/CameraParameters.cpp64
-rw-r--r--libs/surfaceflinger/Android.mk8
-rw-r--r--libs/surfaceflinger/Layer.cpp12
-rw-r--r--libs/surfaceflinger/LayerBase.cpp42
-rw-r--r--libs/surfaceflinger/SurfaceFlinger.cpp15
-rw-r--r--libs/surfaceflinger/SurfaceFlinger.h5
-rw-r--r--libs/surfaceflinger_client/Android.mk11
-rw-r--r--libs/ui/Android.mk21
-rw-r--r--libs/ui/EventHub.cpp5
-rw-r--r--libs/ui/Overlay.cpp7
-rw-r--r--libs/utils/ResourceTypes.cpp2
-rw-r--r--location/java/android/location/Address.java6
-rw-r--r--media/java/android/media/AudioManager.java7
-rw-r--r--media/java/android/media/CamcorderProfile.java8
-rw-r--r--media/java/android/media/EncoderCapabilities.java1
-rw-r--r--media/java/android/media/MediaFile.java4
-rw-r--r--media/java/android/media/MediaRecorder.java2
-rw-r--r--media/java/android/media/Ringtone.java3
-rw-r--r--media/jni/Android.mk10
-rw-r--r--media/jni/android_media_MediaProfiles.cpp2
-rw-r--r--media/libmedia/Android.mk8
-rw-r--r--media/libmedia/MediaProfiles.cpp5
-rw-r--r--media/libmediaplayerservice/Android.mk13
-rw-r--r--media/libmediaplayerservice/FLACPlayer.cpp577
-rw-r--r--media/libmediaplayerservice/FLACPlayer.h100
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp9
-rw-r--r--media/libstagefright/Android.mk14
-rw-r--r--media/libstagefright/StagefrightMediaScanner.cpp80
-rw-r--r--media/libstagefright/colorconversion/Android.mk10
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/OpenvpnService.java423
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/VpnDaemons.java2
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/VpnService.java46
-rw-r--r--packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java8
-rw-r--r--services/java/com/android/server/ConnectivityService.java6
-rw-r--r--services/java/com/android/server/InputDevice.java280
-rw-r--r--services/java/com/android/server/KeyInputQueue.java117
-rwxr-xr-xservices/java/com/android/server/NotificationManagerService.java9
-rw-r--r--services/java/com/android/server/PackageManagerService.java4
-rw-r--r--services/java/com/android/server/PowerManagerService.java7
-rw-r--r--services/java/com/android/server/ProcessStats.java32
-rw-r--r--services/java/com/android/server/SystemServer.java8
-rw-r--r--services/java/com/android/server/ThrottleService.java7
-rwxr-xr-xservices/java/com/android/server/VibratorService.java17
-rw-r--r--services/java/com/android/server/WindowManagerService.java121
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java21
-rw-r--r--services/java/com/android/server/am/AppWaitingForDebuggerDialog.java3
-rw-r--r--services/java/com/android/server/am/FactoryErrorDialog.java4
-rw-r--r--services/java/com/android/server/status/IconData.java67
-rw-r--r--services/java/com/android/server/status/StatusBarIcon.java93
-rw-r--r--services/java/com/android/server/status/StatusBarPolicy.java62
-rw-r--r--services/java/com/android/server/status/StatusBarService.java188
-rw-r--r--services/java/com/android/server/status/TickerView.java21
-rw-r--r--services/java/com/android/server/status/TrackingPatternView.java27
-rw-r--r--telephony/java/android/telephony/PhoneNumberUtils.java35
-rw-r--r--telephony/java/com/android/internal/telephony/AdnRecordCache.java19
-rw-r--r--telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java3
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java3
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java8
-rw-r--r--telephony/java/com/android/internal/telephony/gsm/SIMRecords.java7
-rwxr-xr-x[-rw-r--r--]telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java25
-rw-r--r--tests/CoreTests/android/AndroidManifest.xml1
-rw-r--r--tests/CoreTests/android/core/HttpHeaderTest.java62
-rw-r--r--tests/CoreTests/android/core/ProxyTest.java93
-rw-r--r--tools/aapt/ResourceTable.cpp46
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Canvas.java159
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Paint.java2
-rw-r--r--vpn/java/android/net/vpn/OpenvpnProfile.java251
-rw-r--r--vpn/java/android/net/vpn/VpnManager.java2
-rw-r--r--vpn/java/android/net/vpn/VpnType.java3
-rw-r--r--wifi/java/android/net/wifi/WifiNative.java6
-rw-r--r--wifi/java/android/net/wifi/WifiStateTracker.java73
168 files changed, 8203 insertions, 765 deletions
diff --git a/Android.mk b/Android.mk
index 6e1bdc5..df7d8a0 100644
--- a/Android.mk
+++ b/Android.mk
@@ -100,6 +100,7 @@ LOCAL_SRC_FILES += \
core/java/android/bluetooth/IBluetoothA2dp.aidl \
core/java/android/bluetooth/IBluetoothCallback.aidl \
core/java/android/bluetooth/IBluetoothHeadset.aidl \
+ core/java/android/bluetooth/IBluetoothHid.aidl \
core/java/android/bluetooth/IBluetoothPbap.aidl \
core/java/android/content/IContentService.aidl \
core/java/android/content/IIntentReceiver.aidl \
diff --git a/api/current.xml b/api/current.xml
index 9d259f3..c3cec44 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -29016,6 +29016,50 @@
visibility="public"
>
</field>
+<field name="PERIPHERAL_COMBO_KEYBORD_POINTING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1472"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PERIPHERAL_KEYBORD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1344"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PERIPHERAL_POINTING_DEVICE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1408"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="PERIPHERAL_UNCATEGORIZED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1280"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="PHONE_CELLULAR"
type="int"
transient="false"
@@ -59431,7 +59475,7 @@
<method name="drawText"
return="void"
abstract="false"
- native="true"
+ native="false"
synchronized="false"
static="false"
final="false"
@@ -71548,6 +71592,19 @@
visibility="public"
>
</method>
+<method name="open"
+ return="android.hardware.Camera"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cameraNode" type="java.lang.String">
+</parameter>
+</method>
<method name="reconnect"
return="void"
abstract="false"
@@ -71908,6 +71965,28 @@
visibility="public"
>
</method>
+<method name="getAutoExposure"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getBrightness"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getColorEffect"
return="java.lang.String"
abstract="false"
@@ -71919,6 +71998,61 @@
visibility="public"
>
</method>
+<method name="getContrast"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDefaultBrightness"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDefaultContrast"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDefaultSaturation"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getDefaultSharpness"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getExposureCompensation"
return="int"
abstract="false"
@@ -71985,6 +72119,17 @@
visibility="public"
>
</method>
+<method name="getISOValue"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getInt"
return="int"
abstract="false"
@@ -72031,6 +72176,39 @@
visibility="public"
>
</method>
+<method name="getLensShade"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMaxBrightness"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMaxContrast"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getMaxExposureCompensation"
return="int"
abstract="false"
@@ -72042,6 +72220,28 @@
visibility="public"
>
</method>
+<method name="getMaxSaturation"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getMaxSharpness"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getMaxZoom"
return="int"
abstract="false"
@@ -72119,6 +72319,17 @@
visibility="public"
>
</method>
+<method name="getSaturation"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getSceneMode"
return="java.lang.String"
abstract="false"
@@ -72130,6 +72341,17 @@
visibility="public"
>
</method>
+<method name="getSharpness"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getSupportedAntibanding"
return="java.util.List&lt;java.lang.String&gt;"
abstract="false"
@@ -72141,6 +72363,17 @@
visibility="public"
>
</method>
+<method name="getSupportedAutoexposure"
+ return="java.util.List&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getSupportedColorEffects"
return="java.util.List&lt;java.lang.String&gt;"
abstract="false"
@@ -72174,6 +72407,17 @@
visibility="public"
>
</method>
+<method name="getSupportedIsoValues"
+ return="java.util.List&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getSupportedJpegThumbnailSizes"
return="java.util.List&lt;android.hardware.Camera.Size&gt;"
abstract="false"
@@ -72185,6 +72429,17 @@
visibility="public"
>
</method>
+<method name="getSupportedLensShadeModes"
+ return="java.util.List&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getSupportedPictureFormats"
return="java.util.List&lt;java.lang.Integer&gt;"
abstract="false"
@@ -72306,6 +72561,17 @@
visibility="public"
>
</method>
+<method name="isSmartContrastEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="isSmoothZoomSupported"
return="boolean"
abstract="false"
@@ -72395,6 +72661,32 @@
<parameter name="antibanding" type="java.lang.String">
</parameter>
</method>
+<method name="setAutoExposure"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="value" type="java.lang.String">
+</parameter>
+</method>
+<method name="setBrightness"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="brightness" type="float">
+</parameter>
+</method>
<method name="setColorEffect"
return="void"
abstract="false"
@@ -72408,6 +72700,32 @@
<parameter name="value" type="java.lang.String">
</parameter>
</method>
+<method name="setContrast"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="contrast" type="float">
+</parameter>
+</method>
+<method name="setExifDateTime"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dateTime" type="java.lang.String">
+</parameter>
+</method>
<method name="setExposureCompensation"
return="void"
abstract="false"
@@ -72460,6 +72778,19 @@
<parameter name="altitude" type="double">
</parameter>
</method>
+<method name="setGpsAltitudeRef"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="altRef" type="double">
+</parameter>
+</method>
<method name="setGpsLatitude"
return="void"
abstract="false"
@@ -72473,6 +72804,19 @@
<parameter name="latitude" type="double">
</parameter>
</method>
+<method name="setGpsLatitudeRef"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="latRef" type="java.lang.String">
+</parameter>
+</method>
<method name="setGpsLongitude"
return="void"
abstract="false"
@@ -72486,6 +72830,19 @@
<parameter name="longitude" type="double">
</parameter>
</method>
+<method name="setGpsLongitudeRef"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lonRef" type="java.lang.String">
+</parameter>
+</method>
<method name="setGpsProcessingMethod"
return="void"
abstract="false"
@@ -72499,6 +72856,19 @@
<parameter name="processing_method" type="java.lang.String">
</parameter>
</method>
+<method name="setGpsStatus"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="status" type="double">
+</parameter>
+</method>
<method name="setGpsTimestamp"
return="void"
abstract="false"
@@ -72512,6 +72882,19 @@
<parameter name="timestamp" type="long">
</parameter>
</method>
+<method name="setISOValue"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="iso" type="java.lang.String">
+</parameter>
+</method>
<method name="setJpegQuality"
return="void"
abstract="false"
@@ -72553,6 +72936,19 @@
<parameter name="height" type="int">
</parameter>
</method>
+<method name="setLensShade"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="lensshade" type="java.lang.String">
+</parameter>
+</method>
<method name="setPictureFormat"
return="void"
abstract="false"
@@ -72635,6 +73031,19 @@
<parameter name="rotation" type="int">
</parameter>
</method>
+<method name="setSaturation"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="saturation" type="float">
+</parameter>
+</method>
<method name="setSceneMode"
return="void"
abstract="false"
@@ -72648,6 +73057,32 @@
<parameter name="value" type="java.lang.String">
</parameter>
</method>
+<method name="setSharpness"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sharpness" type="float">
+</parameter>
+</method>
+<method name="setSmartContrastEnabled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
<method name="setWhiteBalance"
return="void"
abstract="false"
@@ -72731,6 +73166,39 @@
visibility="public"
>
</field>
+<field name="AUTO_EXPOSURE_CENTER_WEIGHTED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;meter-center&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AUTO_EXPOSURE_FRAME_AVG"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;meter-average&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="AUTO_EXPOSURE_SPOT_METERING"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;meter-spot&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="EFFECT_AQUA"
type="java.lang.String"
transient="false"
@@ -72940,6 +73408,116 @@
visibility="public"
>
</field>
+<field name="FOCUS_MODE_NORMAL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;normal&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ISO_100"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;100&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ISO_1250"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;1250&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ISO_200"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;200&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ISO_400"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;400&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ISO_800"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;800&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ISO_AUTO"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;auto&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ISO_HJR"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;deblur&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LENSSHADE_DISABLE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;disable&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="LENSSHADE_ENABLE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;enable&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="SCENE_MODE_ACTION"
type="java.lang.String"
transient="false"
@@ -73311,6 +73889,80 @@
>
</field>
</class>
+<class name="CameraSwitch"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="CameraSwitch"
+ type="android.hardware.CameraSwitch"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="hasCameraSwitch"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="openCamera"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="cameraNode" type="java.lang.String">
+</parameter>
+</method>
+<method name="openMainCamera"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="SWITCH_CAMERA_MAIN"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;main&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SWITCH_CAMERA_SECONDARY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;secondary&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
<class name="GeomagneticField"
extends="java.lang.Object"
abstract="false"
@@ -82539,6 +83191,17 @@
<parameter name="quality" type="int">
</parameter>
</method>
+<field name="QUALITY_FRONT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="QUALITY_HIGH"
type="int"
transient="false"
@@ -82745,6 +83408,226 @@
>
</field>
</class>
+<class name="EncoderCapabilities"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getAudioEncoders"
+ return="java.util.List&lt;android.media.EncoderCapabilities.AudioEncoderCap&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getOutputFileFormats"
+ return="int[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getVideoEncoders"
+ return="java.util.List&lt;android.media.EncoderCapabilities.VideoEncoderCap&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="EncoderCapabilities.AudioEncoderCap"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="mCodec"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mMaxBitRate"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mMaxChannels"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mMaxSampleRate"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mMinBitRate"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mMinChannels"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mMinSampleRate"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="EncoderCapabilities.VideoEncoderCap"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="mCodec"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mMaxBitRate"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mMaxFrameHeight"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mMaxFrameRate"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mMaxFrameWidth"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mMinBitRate"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mMinFrameHeight"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mMinFrameRate"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mMinFrameWidth"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
<class name="ExifInterface"
extends="java.lang.Object"
abstract="false"
@@ -84825,6 +85708,17 @@
deprecated="not deprecated"
visibility="public"
>
+<field name="AAC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="AMR_NB"
type="int"
transient="false"
@@ -214021,7 +214915,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="arg0" type="T">
+<parameter name="t" type="T">
</parameter>
</method>
</interface>
diff --git a/awt/com/android/internal/awt/AndroidGraphics2D.java b/awt/com/android/internal/awt/AndroidGraphics2D.java
index 9a8ae02..b9cd091 100644
--- a/awt/com/android/internal/awt/AndroidGraphics2D.java
+++ b/awt/com/android/internal/awt/AndroidGraphics2D.java
@@ -406,7 +406,7 @@ public class AndroidGraphics2D extends Graphics2D {
mP.setStrokeWidth(0);
mC.drawText(str.toCharArray(), 0, str.toCharArray().length, x, y,
- mP);
+ mP,false);
mP.setStyle(tmp);
}
@@ -1276,7 +1276,7 @@ public class AndroidGraphics2D extends Graphics2D {
@Override
public void drawChars(char[] data, int offset, int length, int x, int y) {
- mC.drawText(data, offset, length, x, y, mP);
+ mC.drawText(data, offset, length, x, y, mP,false);
}
@Override
diff --git a/camera/libcameraservice/Android.mk b/camera/libcameraservice/Android.mk
index df5c166..4430541 100644
--- a/camera/libcameraservice/Android.mk
+++ b/camera/libcameraservice/Android.mk
@@ -48,9 +48,13 @@ LOCAL_SHARED_LIBRARIES:= \
libutils \
libbinder \
libcutils \
- libmedia \
- libcamera_client \
- libsurfaceflinger_client
+ libmedia
+
+ifneq ($(BOARD_USES_ECLAIR_LIBCAMERA),true)
+ LOCAL_SHARED_LIBRARIES += \
+ libsurfaceflinger_client \
+ libcamera_client
+endif
LOCAL_MODULE:= libcameraservice
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 118249e..0ac089f 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -67,6 +67,16 @@ extern "C" {
static int debug_frame_cnt;
#endif
+struct camera_size_type {
+ int width;
+ int height;
+};
+
+static const camera_size_type preview_sizes[] = {
+ { 1280, 720 }, // 720P
+ { 768, 432 },
+};
+
static int getCallingPid() {
return IPCThreadState::self()->getCallingPid();
}
@@ -555,6 +565,13 @@ status_t CameraService::Client::setOverlay()
CameraParameters params(mHardware->getParameters());
params.getPreviewSize(&w, &h);
+ //for 720p recording , preview can be 800X448
+ if(w == preview_sizes[0].width && h==preview_sizes[0].height){
+ LOGD("Changing overlay dimensions to 768X432 for 720p recording.");
+ w = preview_sizes[1].width;
+ h = preview_sizes[1].height;
+ }
+
if ( w != mOverlayW || h != mOverlayH )
{
// Force the destruction of any previous overlay
@@ -606,6 +623,13 @@ status_t CameraService::Client::registerPreviewBuffers()
CameraParameters params(mHardware->getParameters());
params.getPreviewSize(&w, &h);
+ //for 720p recording , preview can be 800X448
+ if(w == preview_sizes[0].width && h== preview_sizes[0].height){
+ LOGD("registerpreviewbufs :changing dimensions to 768X432 for 720p recording.");
+ w = preview_sizes[1].width;
+ h = preview_sizes[1].height;
+ }
+
// don't use a hardcoded format here
ISurface::BufferHeap buffers(w, h, w, h,
HAL_PIXEL_FORMAT_YCrCb_420_SP,
@@ -886,32 +910,39 @@ status_t CameraService::Client::takePicture()
// snapshot taken
void CameraService::Client::handleShutter(
- image_rect_type *size // The width and height of yuv picture for
+ image_rect_type *size, // The width and height of yuv picture for
// registerBuffer. If this is NULL, use the picture
// size from parameters.
+ bool playShutterSoundOnly
)
{
// Play shutter sound.
- if (mMediaPlayerClick.get() != NULL) {
- // do not play shutter sound if stream volume is 0
- // (typically because ringer mode is silent).
- int index;
- AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index);
- if (index != 0) {
- mMediaPlayerClick->seekTo(0);
- mMediaPlayerClick->start();
+
+ if(playShutterSoundOnly) {
+
+ if (mMediaPlayerClick.get() != NULL) {
+ // do not play shutter sound if stream volume is 0
+ // (typically because ringer mode is silent).
+ int index;
+ AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index);
+ if (index != 0) {
+ mMediaPlayerClick->seekTo(0);
+ mMediaPlayerClick->start();
+ }
+ }
+ sp<ICameraClient> c = mCameraClient;
+ if (c != NULL) {
+ c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
}
+ return ;
}
+
// Screen goes black after the buffer is unregistered.
if (mSurface != 0 && !mUseOverlay) {
mSurface->unregisterBuffers();
}
- sp<ICameraClient> c = mCameraClient;
- if (c != NULL) {
- c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
- }
mHardware->disableMsgType(CAMERA_MSG_SHUTTER);
// It takes some time before yuvPicture callback to be called.
@@ -928,6 +959,7 @@ void CameraService::Client::handleShutter(
h &= ~1;
LOGV("Snapshot image width=%d, height=%d", w, h);
}
+
// FIXME: don't use hardcoded format constants here
ISurface::BufferHeap buffers(w, h, w, h,
HAL_PIXEL_FORMAT_YCrCb_420_SP, mOrientation, 0,
@@ -1085,7 +1117,7 @@ void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1, int32_
switch (msgType) {
case CAMERA_MSG_SHUTTER:
// ext1 is the dimension of the yuv picture.
- client->handleShutter((image_rect_type *)ext1);
+ client->handleShutter((image_rect_type *)ext1, (bool)ext2);
break;
default:
sp<ICameraClient> c = client->mCameraClient;
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index 75e96c6..f04f39c 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -144,7 +144,7 @@ private:
static sp<Client> getClientFromCookie(void* user);
void handlePreviewData(const sp<IMemory>&);
- void handleShutter(image_rect_type *image);
+ void handleShutter(image_rect_type *image, bool playShutterSoundOnly);
void handlePostview(const sp<IMemory>&);
void handleRawPicture(const sp<IMemory>&);
void handleCompressedPicture(const sp<IMemory>&);
diff --git a/camera/tests/CameraServiceTest/Android.mk b/camera/tests/CameraServiceTest/Android.mk
index 9bb190a..5bacb30 100644
--- a/camera/tests/CameraServiceTest/Android.mk
+++ b/camera/tests/CameraServiceTest/Android.mk
@@ -6,7 +6,7 @@ LOCAL_SRC_FILES:= CameraServiceTest.cpp
LOCAL_MODULE:= CameraServiceTest
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := eng tests
LOCAL_C_INCLUDES += \
frameworks/base/libs
@@ -17,8 +17,12 @@ LOCAL_SHARED_LIBRARIES += \
libbinder \
libcutils \
libutils \
- libui \
- libcamera_client \
- libsurfaceflinger_client
+ libui
+
+ifneq ($(BOARD_USES_ECLAIR_LIBCAMERA),true)
+ LOCAL_SHARED_LIBRARIES += \
+ libcamera_client \
+ libsurfaceflinger_client
+endif
include $(BUILD_EXECUTABLE)
diff --git a/cmds/am/am b/cmds/am/am
index c823634..bc40e47 100755
--- a/cmds/am/am
+++ b/cmds/am/am
@@ -1,3 +1,4 @@
+#!/system/bin/sh
# Script to start "am" on the device, which has a very rudimentary
# shell.
#
diff --git a/cmds/bmgr/bmgr b/cmds/bmgr/bmgr
index 6b4bbe2..60b5833 100755
--- a/cmds/bmgr/bmgr
+++ b/cmds/bmgr/bmgr
@@ -1,3 +1,4 @@
+#!/system/bin/sh
# Script to start "bmgr" on the device, which has a very rudimentary
# shell.
#
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index 2b89759..2876362 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -21,8 +21,12 @@ LOCAL_SHARED_LIBRARIES := \
libui \
libskia \
libEGL \
- libGLESv1_CM \
- libsurfaceflinger_client
+ libGLESv1_CM
+
+ifneq ($(BOARD_USES_ECLAIR_LIBCAMERA),true)
+ LOCAL_SHARED_LIBRARIES += \
+ libsurfaceflinger_client
+endif
LOCAL_C_INCLUDES := \
$(call include-path-for, corecg graphics)
diff --git a/cmds/ime/ime b/cmds/ime/ime
index 96c56d3..1a1fdd9 100755
--- a/cmds/ime/ime
+++ b/cmds/ime/ime
@@ -1,3 +1,4 @@
+#!/system/bin/sh
# Script to start "pm" on the device, which has a very rudimentary
# shell.
#
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 41f070c..8d571dc 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -405,6 +405,7 @@ int create_cache_path(char path[PKG_PATH_MAX], const char *src)
char *tmp;
int srclen;
int dstlen;
+ char dexopt_data_only[PROPERTY_VALUE_MAX];
srclen = strlen(src);
@@ -417,7 +418,15 @@ int create_cache_path(char path[PKG_PATH_MAX], const char *src)
return -1;
}
- dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) +
+ const char *cache_path = DALVIK_CACHE_PREFIX;
+ if (!strncmp(src, "/system", 7)) {
+ property_get("dalvik.vm.dexopt-data-only", dexopt_data_only, "");
+ if (strcmp(dexopt_data_only, "1") != 0) {
+ cache_path = DALVIK_SYSTEM_CACHE_PREFIX;
+ }
+ }
+
+ dstlen = srclen + strlen(cache_path) +
strlen(DALVIK_CACHE_POSTFIX) + 1;
if (dstlen > PKG_PATH_MAX) {
@@ -425,11 +434,11 @@ int create_cache_path(char path[PKG_PATH_MAX], const char *src)
}
sprintf(path,"%s%s%s",
- DALVIK_CACHE_PREFIX,
+ cache_path,
src + 1, /* skip the leading / */
DALVIK_CACHE_POSTFIX);
- for(tmp = path + strlen(DALVIK_CACHE_PREFIX); *tmp; tmp++) {
+ for(tmp = path + strlen(cache_path); *tmp; tmp++) {
if (*tmp == '/') {
*tmp = '@';
}
@@ -454,6 +463,77 @@ static void run_dexopt(int zip_fd, int odex_fd, const char* input_file_name,
LOGE("execl(%s) failed: %s\n", DEX_OPT_BIN, strerror(errno));
}
+static void run_check_zipalign(const char* input_file)
+{
+ static const char* ZIPALIGN_BIN = "/system/bin/zipalign";
+ execl(ZIPALIGN_BIN, ZIPALIGN_BIN, "-c", "4", input_file, (char*) NULL);
+}
+
+static void run_zipalign(const char* input_file, const char* output_file)
+{
+ static const char* ZIPALIGN_BIN = "/system/bin/zipalign";
+ execl(ZIPALIGN_BIN, ZIPALIGN_BIN, "4", input_file, output_file, (char*) NULL);
+ LOGE("execl(%s) failed: %s\n", ZIPALIGN_BIN, strerror(errno));
+}
+
+static int wait_check_zipalign(pid_t pid, const char* apk_path)
+{
+ int status;
+ pid_t got_pid;
+
+ while (1) {
+ got_pid = waitpid(pid, &status, 0);
+ if (got_pid == -1 && errno == EINTR) {
+ printf("waitpid interrupted, retrying\n");
+ } else {
+ break;
+ }
+ }
+
+ if (got_pid != pid) {
+ return 1;
+ }
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+ LOGD("CheckZipAlign: --- END '%s' (not needed) ---\n", apk_path);
+ return 0;
+ } else {
+ LOGW("CheckZipAlign: --- END '%s' (needed) ---\n", apk_path);
+ return status;
+ }
+}
+
+static int wait_zipalign(pid_t pid, const char* apk_path)
+{
+ int status;
+ pid_t got_pid;
+
+ /*
+ * Wait for the zipalign process to finish.
+ */
+ while (1) {
+ got_pid = waitpid(pid, &status, 0);
+ if (got_pid == -1 && errno == EINTR) {
+ printf("waitpid interrupted, retrying\n");
+ } else {
+ break;
+ }
+ }
+ if (got_pid != pid) {
+ LOGW("waitpid failed: wanted %d, got %d: %s\n",
+ (int) pid, (int) got_pid, strerror(errno));
+ return 1;
+ }
+
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+ LOGD("ZipAlign: --- END '%s' (success) ---\n", apk_path);
+ return 0;
+ } else {
+ LOGW("ZipAlign: --- END '%s' --- status=0x%04x, process failed\n",
+ apk_path, status);
+ return status; /* always nonzero */
+ }
+}
+
static int wait_dexopt(pid_t pid, const char* apk_path)
{
int status;
@@ -486,6 +566,72 @@ static int wait_dexopt(pid_t pid, const char* apk_path)
}
}
+int zipalign(const char *apk_path, uid_t uid, int is_public)
+{
+ char za_path[PKG_PATH_MAX];
+ struct utimbuf ut;
+ struct stat za_stat, apk_stat;
+ int res;
+
+ pid_t pid;
+ pid = fork();
+ if (pid == 0) {
+ run_check_zipalign(apk_path);
+ exit(67);
+ } else {
+ res = wait_check_zipalign(pid, apk_path);
+ if (res == 0) {
+ goto notneeded;
+ }
+ }
+
+ memset(&apk_stat, 0, sizeof(apk_stat));
+ stat(apk_path, &apk_stat);
+
+ strcpy(za_path, apk_path);
+ strcat(za_path, ".tmp");
+ LOGD("ZipAlign: --- BEGIN '%s' ---\n", apk_path);
+
+ pid = fork();
+ if (pid == 0) {
+ run_zipalign(apk_path, za_path);
+ exit(67);
+ } else {
+ res = wait_zipalign(pid, za_path);
+ if (res != 0) {
+ LOGE("zipalign failed on '%s' res = %d\n", za_path, res);
+ goto fail;
+ }
+ }
+
+ if (chown(za_path, apk_stat.st_uid, apk_stat.st_gid) < 0) {
+ LOGE("zipalign cannot chown '%s'", apk_path);
+ goto fail;
+ }
+ if (chmod(za_path, S_IRUSR|S_IWUSR|S_IRGRP |
+ (is_public ? S_IROTH : 0)) < 0) {
+ LOGE("zipalign cannot chmod '%s'\n", apk_path);
+ goto fail;
+ }
+
+ ut.actime = apk_stat.st_atime;
+ ut.modtime = apk_stat.st_mtime;
+ utime(za_path, &ut);
+
+ unlink(apk_path);
+ rename(za_path, apk_path);
+
+ return 0;
+
+notneeded:
+ return 0;
+
+fail:
+ unlink(za_path);
+ return -1;
+
+}
+
int dexopt(const char *apk_path, uid_t uid, int is_public)
{
struct utimbuf ut;
@@ -501,6 +647,10 @@ int dexopt(const char *apk_path, uid_t uid, int is_public)
if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
return -1;
}
+
+ if (strncmp(apk_path, "/system", 7) != 0) {
+ zipalign(apk_path, uid, is_public);
+ }
/* platform-specific flags affecting optimization and verification */
property_get("dalvik.vm.dexopt-flags", dexopt_flags, "");
diff --git a/cmds/installd/installd.h b/cmds/installd/installd.h
index cfcdb98..fc63b9f 100644
--- a/cmds/installd/installd.h
+++ b/cmds/installd/installd.h
@@ -64,6 +64,7 @@
#define SDCARD_DIR_PREFIX getenv("ASEC_MOUNTPOINT")
#define DALVIK_CACHE_PREFIX "/data/dalvik-cache/"
+#define DALVIK_SYSTEM_CACHE_PREFIX "/cache/dalvik-cache/"
#define DALVIK_CACHE_POSTFIX "/classes.dex"
#define UPDATE_COMMANDS_DIR_PREFIX "/system/etc/updatecmds/"
diff --git a/cmds/pm/pm b/cmds/pm/pm
index 8183838..53f85b2 100755
--- a/cmds/pm/pm
+++ b/cmds/pm/pm
@@ -1,3 +1,4 @@
+#!/system/bin/sh
# Script to start "pm" on the device, which has a very rudimentary
# shell.
#
diff --git a/cmds/zipalign/Android.mk b/cmds/zipalign/Android.mk
new file mode 100644
index 0000000..3451b94
--- /dev/null
+++ b/cmds/zipalign/Android.mk
@@ -0,0 +1,25 @@
+#
+# Copyright 2008 The Android Open Source Project
+#
+# Zip alignment tool
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ ../../../../build/tools/zipalign/ZipFile.cpp \
+ ../../../../build/tools/zipalign/ZipEntry.cpp \
+ ../../../../build/tools/zipalign/ZipAlign.cpp
+
+LOCAL_C_INCLUDES := external/zlib build/tools/zipalign
+
+LOCAL_SHARED_LIBRARIES := \
+ libz \
+ libutils \
+ libcutils
+
+LOCAL_MODULE := zipalign
+
+include $(BUILD_EXECUTABLE)
+
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index f0cef98..ec39ac7 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -174,7 +174,7 @@ public class ApplicationErrorReport implements Parcelable {
/**
* Return activity in receiverPackage that handles ACTION_APP_ERROR.
*
- * @param pm PackageManager isntance
+ * @param pm PackageManager instance
* @param errorPackage package which caused the error
* @param receiverPackage candidate package to receive the error
* @return activity component within receiverPackage which handles
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index f471f57..0f9d314 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1690,8 +1690,9 @@ class ContextImpl extends Context {
if (resolveInfo == null) {
return null;
}
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.setClassName(packageName, resolveInfo.activityInfo.name);
+ Intent intent = new Intent(intentToResolve);
+ intent.setClassName(resolveInfo.activityInfo.applicationInfo.packageName,
+ resolveInfo.activityInfo.name);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
return intent;
}
diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java
index c7fea9e..fc50ad0 100644
--- a/core/java/android/bluetooth/BluetoothClass.java
+++ b/core/java/android/bluetooth/BluetoothClass.java
@@ -201,6 +201,12 @@ public final class BluetoothClass implements Parcelable {
//public static final int AUDIO_VIDEO_RESERVED = 0x0444;
public static final int AUDIO_VIDEO_VIDEO_GAMING_TOY = 0x0448;
+ // Devices in the PERIPHERAL major class
+ public static final int PERIPHERAL_UNCATEGORIZED = 0x0500;
+ public static final int PERIPHERAL_KEYBORD = 0x0540;
+ public static final int PERIPHERAL_POINTING_DEVICE = 0x0580;
+ public static final int PERIPHERAL_COMBO_KEYBORD_POINTING = 0x05C0;
+
// Devices in the WEARABLE major class
public static final int WEARABLE_UNCATEGORIZED = 0x0700;
public static final int WEARABLE_WRIST_WATCH = 0x0704;
@@ -259,6 +265,8 @@ public final class BluetoothClass implements Parcelable {
public static final int PROFILE_A2DP = 1;
/** @hide */
public static final int PROFILE_OPP = 2;
+ /** @hide */
+ public static final int PROFILE_HID = 3;
/**
* Check class bits for possible bluetooth profile support.
diff --git a/core/java/android/bluetooth/BluetoothHid.java b/core/java/android/bluetooth/BluetoothHid.java
new file mode 100644
index 0000000..45347d3
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothHid.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2009 ISB Corporation
+ * Copyright (C) 2010 0xlab
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.server.BluetoothHidService;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.ServiceManager;
+import android.os.RemoteException;
+import android.os.IBinder;
+import android.util.Log;
+
+import java.util.List;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+import java.util.HashSet;
+/**
+ * Public API for controlling the Bluetooth HID Profile Service.
+ *
+ * BluetoothHid is a proxy object for controlling the Bluetooth HID
+ * Service via IPC.
+ *
+ *
+ * Currently the BluetoothHid service runs in the system server and this
+ * proxy object will be immediately bound to the service on construction.
+ * However this may change in future releases, and error codes such as
+ * BluetoothError.ERROR_IPC_NOT_READY will be returned from this API when the
+ * proxy object is not yet attached.
+ *
+ * Currently this class provides methods to connect to HID devices.
+ *
+ * @hide
+ */
+public class BluetoothHid {
+ private static final String TAG = "BluetoothHid";
+ private static final boolean DBG = false;
+
+ /** int extra for DEVICE_STATE_CHANGED_ACTION */
+ public static final String HID_DEVICE_STATE =
+ "android.bluetooth.hid.intent.HID_DEVICE_STATE";
+ /** int extra for DEVICE_STATE_CHANGED_ACTION */
+ public static final String HID_DEVICE_PREVIOUS_STATE =
+ "android.bluetooth.hid.intent.HID_DEVICE_PREVIOUS_STATE";
+
+ /** Indicates the state of an HID device has changed.
+ * This intent will always contain HID_DEVICE_STATE, and
+ * BluetoothIntent.ADDRESS extras.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String HID_DEVICE_STATE_CHANGED_ACTION =
+ "android.bluetooth.hid.intent.action.HID_DEVICE_STATE_CHANGED";
+
+ public static final int STATE_DISCONNECTED = 0;
+ public static final int STATE_CONNECTING = 1;
+ public static final int STATE_CONNECTED = 2;
+ public static final int STATE_DISCONNECTING = 3;
+
+ /** Default priority for hid devices that we try to auto-connect
+ * and allow incoming connections */
+ public static final int PRIORITY_AUTO_CONNECT = 1000;
+ /** Default priority for hid devices that should allow incoming
+ * connections */
+ public static final int PRIORITY_ON = 100;
+ /** Default priority for hid devices that should not allow incoming
+ * connections */
+ public static final int PRIORITY_OFF = 0;
+ /** Default priority when not set or when the device is unpaired */
+ public static final int PRIORITY_UNDEFINED = -1;
+
+ private final IBluetoothHid mService;
+ private final Context mContext;
+
+
+ /**
+ * Create a BluetoothHid proxy object.
+ */
+ public BluetoothHid(Context c) {
+ mContext = c;
+
+ IBinder b = ServiceManager.getService(BluetoothHidService.BLUETOOTH_HID_SERVICE);
+ if (b != null) {
+ mService = IBluetoothHid.Stub.asInterface(b);
+ } else {
+ Log.w(TAG, "Bluetooth HID service not available!");
+ // Instead of throwing an exception which prevents people from going
+ // into Wireless settings in the emulator. Let it crash later when it is actually used.
+ mService = null;
+ }
+ }
+
+
+ /** Initiate a connection to an HID device.
+ * Listen for HID_DEVICE_STATE_CHANGED_ACTION to find out when the
+ * connection is completed.
+ * @param address Remote BT address.
+ * @return Result code, negative indicates an immediate error.
+ * @hide
+ */
+ public boolean connectHidDevice(BluetoothDevice device) {
+ if (DBG) log("connectHidDevice(" + device + ")");
+ try {
+ return mService.connectHidDevice(device);
+ } catch (RemoteException e) {
+ Log.w(TAG, "", e);
+ return false;
+ }
+ }
+
+ /** Initiate disconnect from an HID device.
+ * Listen for HID_DEVICE_STATE_CHANGED_ACTION to find out when
+ * disconnect is completed.
+ * @param address Remote BT address.
+ * @return Result code, negative indicates an immediate error.
+ * @hide
+ */
+ public boolean disconnectHidDevice(BluetoothDevice device) {
+ try {
+ return mService.disconnectHidDevice(device);
+ } catch (RemoteException e) {
+ Log.w(TAG, "", e);
+ return false;
+ }
+ }
+
+ /** Check if a specified HID device is connected.
+ * @param address Remote BT address.
+ * @return True if connected (or playing), false otherwise and on error.
+ * @hide
+ */
+ public boolean isHidDeviceConnected(BluetoothDevice device) {
+ int state = getHidDeviceState(device);
+ return state == STATE_CONNECTED;
+ }
+
+ /** Check if any HID device is connected.
+ * @return a unmodifiable set of connected HID devices, or null on error.
+ * @hide
+ */
+ public Set<BluetoothDevice> getConnectedSinks() {
+ if (DBG) log("getConnectedSinks()");
+ try {
+ return Collections.unmodifiableSet(
+ new HashSet<BluetoothDevice>(Arrays.asList(mService.getConnectedSinks())));
+ } catch (RemoteException e) {
+ Log.w(TAG, "", e);
+ return null;
+ }
+ }
+
+ /** Check if any HID device is in Non Disconnected state
+ * i.e connected, connecting, disconnecting.
+ * @return a unmodifiable set of connected HID devices, or null on error.
+ * @hide
+ */
+ public Set<BluetoothDevice> getNonDisconnectedSinks() {
+ if (DBG) log("getNonDisconnectedSinks()");
+ try {
+ return Collections.unmodifiableSet(
+ new HashSet<BluetoothDevice>(Arrays.asList(mService.getNonDisconnectedSinks())));
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ return null;
+ }
+ }
+
+ /** Get the state of an HID device
+ * @param address Remote BT address.
+ * @return State code, or negative on error
+ * @hide
+ */
+ public int getHidDeviceState(BluetoothDevice device) {
+ if (DBG) log("getHidDeviceState(" + device + ")");
+ try {
+ return mService.getHidDeviceState(device);
+ } catch (RemoteException e) {
+ Log.w(TAG, "", e);
+ return BluetoothHid.STATE_DISCONNECTED;
+ }
+ }
+
+
+ /**
+ * Set priority of HID device.
+ * Priority is a non-negative integer. By default paired devices will have
+ * a priority of PRIORITY_AUTO, and unpaired device PRIORITY_NONE (0).
+ * Sinks with priority greater than zero will accept incoming connections
+ * (if no sink is currently connected).
+ * Priority for unpaired sink must be PRIORITY_NONE.
+ * @param device Paired sink
+ * @param priority Integer priority, for example PRIORITY_AUTO or
+ * PRIORITY_NONE
+ * @return true if priority is set, false on error
+ */
+ public boolean setHidDevicePriority(BluetoothDevice device, int priority) {
+ if (DBG) log("setHidDevicePriority(" + device + ", " + priority + ")");
+ try {
+ return mService.setHidDevicePriority(device, priority);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ return false;
+ }
+ }
+
+ /**
+ * Get priority of HID device.
+ * @param device Sink
+ * @return non-negative priority, or negative error code on error.
+ */
+ public int getHidDevicePriority(BluetoothDevice device) {
+ if (DBG) log("getHidDevicePriority(" + device + ")");
+ try {
+ return mService.getHidDevicePriority(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ return PRIORITY_OFF;
+ }
+ }
+
+ /** Helper for converting a state to a string.
+ * For debug use only - strings are not internationalized.
+ * @hide
+ */
+ public static String stateToString(int state) {
+ switch (state) {
+ case STATE_DISCONNECTED:
+ return "disconnected";
+ case STATE_CONNECTING:
+ return "connecting";
+ case STATE_CONNECTED:
+ return "connected";
+ case STATE_DISCONNECTING:
+ return "disconnecting";
+ default:
+ return "<unknown state " + state + ">";
+ }
+ }
+
+
+ /**
+ * Check class bits for possible HID device support.
+ * This is a simple heuristic that tries to guess if a device with the
+ * given class bits might be a HID device. It is not accurate for all
+ * devices. It tries to err on the side of false positives.
+ * @return True if this device might be a HID device
+ */
+ public static boolean doesClassMatch(BluetoothClass btClass) {
+ switch (btClass.getDeviceClass()) {
+ case BluetoothClass.Device.PERIPHERAL_KEYBORD:
+ case BluetoothClass.Device.PERIPHERAL_POINTING_DEVICE:
+ case BluetoothClass.Device.PERIPHERAL_COMBO_KEYBORD_POINTING:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ private static void log(String msg) {
+ Log.d(TAG, msg);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index 4164a3d..f5f0ba6 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -49,10 +49,12 @@ public final class BluetoothUuid {
ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB");
public static final ParcelUuid ObexObjectPush =
ParcelUuid.fromString("00001105-0000-1000-8000-00805f9b34fb");
+ public static final ParcelUuid HID =
+ ParcelUuid.fromString("00001124-0000-1000-8000-00805f9b34fb");
public static final ParcelUuid[] RESERVED_UUIDS = {
AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget,
- ObexObjectPush};
+ ObexObjectPush,HID};
public static boolean isAudioSource(ParcelUuid uuid) {
return uuid.equals(AudioSource);
@@ -82,6 +84,10 @@ public final class BluetoothUuid {
return uuid.equals(AvrcpTarget);
}
+ public static boolean isHid(ParcelUuid uuid) {
+ return uuid.equals(HID);
+ }
+
/**
* Returns true if ParcelUuid is present in uuidArray
*
diff --git a/core/java/android/bluetooth/IBluetoothHid.aidl b/core/java/android/bluetooth/IBluetoothHid.aidl
new file mode 100644
index 0000000..5941083
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothHid.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2009 ISB Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+import android.bluetooth.BluetoothDevice;
+/**
+ * System private API for Bluetooth HID service
+ *
+ * {@hide}
+ */
+interface IBluetoothHid {
+ boolean connectHidDevice(in BluetoothDevice device);
+ boolean disconnectHidDevice(in BluetoothDevice device);
+ BluetoothDevice[] getConnectedSinks(); // change to Set<> once AIDL supports
+ BluetoothDevice[] getNonDisconnectedSinks(); // change to Set<> once AIDL supports
+ int getHidDeviceState(in BluetoothDevice device);
+ boolean setHidDevicePriority(in BluetoothDevice device, int priority);
+ int getHidDevicePriority(in BluetoothDevice device);
+}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 0608cc0..44e589d 100644..100755
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -25,6 +25,7 @@ import org.xmlpull.v1.XmlPullParserException;
import android.graphics.Movie;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable.ConstantState;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemProperties;
@@ -41,6 +42,8 @@ import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.Locale;
+import android.graphics.PorterDuff.Mode;
+
/**
* Class for accessing an application's resources. This sits on top of the
* asset manager of the application (accessible through getAssets()) and
@@ -66,6 +69,8 @@ public class Resources {
= new LongSparseArray<Drawable.ConstantState>();
private static final SparseArray<ColorStateList> mPreloadedColorStateLists
= new SparseArray<ColorStateList>();
+ private static final LongSparseArray<Drawable.ConstantState> sPreloadedColorDrawables
+ = new LongSparseArray<Drawable.ConstantState>();
private static boolean mPreloaded;
/*package*/ final TypedValue mTmpValue = new TypedValue();
@@ -75,6 +80,8 @@ public class Resources {
= new LongSparseArray<WeakReference<Drawable.ConstantState> >();
private final SparseArray<WeakReference<ColorStateList> > mColorStateListCache
= new SparseArray<WeakReference<ColorStateList> >();
+ private final LongSparseArray<WeakReference<Drawable.ConstantState> > mColorDrawableCache
+ = new LongSparseArray<WeakReference<Drawable.ConstantState> >();
private boolean mPreloading;
/*package*/ TypedArray mCachedStyledAttributes = null;
@@ -582,6 +589,41 @@ public class Resources {
}
}
+
+ /**
+ * Return a drawable object associated with a particular resource ID.
+ * Various types of objects will be returned depending on the underlying
+ * resource -- for example, a solid color, PNG image, scalable image, etc.
+ * The Drawable API hides these implementation details.
+ *
+ * mtwebster:
+ * This version also applies a Porter Duff color mask onto the object before
+ * returning the object. Put in Resources to give reusability, I plan on
+ * applying this to other parts of the gui
+ *
+ * @param id The desired resource identifier, as generated by the aapt
+ * tool. This integer encodes the package, type, and resource
+ * entry. The value 0 is an invalid identifier.
+ *
+ * @param mask The color mask to use (alpha-r-g-b)
+ *
+ * @param masktype The Porter Duff filter mode
+ *
+ * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
+ *
+ * @return Drawable An object that can be used to draw this resource.
+ * @hide
+ */
+ public Drawable getDrawable(int id, int mask, Mode maskType) throws NotFoundException {
+ synchronized (mTmpValue) {
+ TypedValue value = mTmpValue;
+ getValue(id, value, true);
+ Drawable tmpDrawable = loadDrawable(value, id);
+ tmpDrawable.setColorFilter(mask, maskType);
+ return tmpDrawable;
+ }
+ }
+
/**
* Return a movie object associated with the particular resource ID.
* @param id The desired resource identifier, as generated by the aapt
@@ -1299,37 +1341,13 @@ public class Resources {
(int)(mMetrics.density*160), mConfiguration.keyboard,
keyboardHidden, mConfiguration.navigation, width, height,
mConfiguration.screenLayout, mConfiguration.uiMode, sSdkVersion);
- int N = mDrawableCache.size();
- if (DEBUG_CONFIG) {
- Log.d(TAG, "Cleaning up drawables config changes: 0x"
- + Integer.toHexString(configChanges));
- }
- for (int i=0; i<N; i++) {
- WeakReference<Drawable.ConstantState> ref = mDrawableCache.valueAt(i);
- if (ref != null) {
- Drawable.ConstantState cs = ref.get();
- if (cs != null) {
- if (Configuration.needNewResources(
- configChanges, cs.getChangingConfigurations())) {
- if (DEBUG_CONFIG) {
- Log.d(TAG, "FLUSHING #0x"
- + Long.toHexString(mDrawableCache.keyAt(i))
- + " / " + cs + " with changes: 0x"
- + Integer.toHexString(cs.getChangingConfigurations()));
- }
- mDrawableCache.setValueAt(i, null);
- } else if (DEBUG_CONFIG) {
- Log.d(TAG, "(Keeping #0x"
- + Long.toHexString(mDrawableCache.keyAt(i))
- + " / " + cs + " with changes: 0x"
- + Integer.toHexString(cs.getChangingConfigurations())
- + ")");
- }
- }
- }
- }
- mDrawableCache.clear();
+
+ clearDrawableCache(mDrawableCache, configChanges);
+ clearDrawableCache(mColorDrawableCache, configChanges);
+
mColorStateListCache.clear();
+
+
flushLayoutCache();
}
synchronized (mSync) {
@@ -1339,6 +1357,41 @@ public class Resources {
}
}
+ private void clearDrawableCache(
+ LongSparseArray<WeakReference<ConstantState>> cache,
+ int configChanges) {
+ int N = cache.size();
+ if (DEBUG_CONFIG) {
+ Log.d(TAG, "Cleaning up drawables config changes: 0x"
+ + Integer.toHexString(configChanges));
+ }
+ for (int i=0; i<N; i++) {
+ WeakReference<Drawable.ConstantState> ref = cache.valueAt(i);
+ if (ref != null) {
+ Drawable.ConstantState cs = ref.get();
+ if (cs != null) {
+ if (Configuration.needNewResources(
+ configChanges, cs.getChangingConfigurations())) {
+ if (DEBUG_CONFIG) {
+ Log.d(TAG, "FLUSHING #0x"
+ + Long.toHexString(mDrawableCache.keyAt(i))
+ + " / " + cs + " with changes: 0x"
+ + Integer.toHexString(cs.getChangingConfigurations()));
+ }
+ cache.setValueAt(i, null);
+ } else if (DEBUG_CONFIG) {
+ Log.d(TAG, "(Keeping #0x"
+ + Long.toHexString(cache.keyAt(i))
+ + " / " + cs + " with changes: 0x"
+ + Integer.toHexString(cs.getChangingConfigurations())
+ + ")");
+ }
+ }
+ }
+ }
+ cache.clear();
+ }
+
/**
* Update the system resources configuration if they have previously
* been initialized.
@@ -1661,13 +1714,18 @@ public class Resources {
}
final long key = (((long) value.assetCookie) << 32) | value.data;
- Drawable dr = getCachedDrawable(key);
+ boolean isColorDrawable = false;
+ if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
+ value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
+ isColorDrawable = true;
+ }
+ Drawable dr = getCachedDrawable(isColorDrawable ? mColorDrawableCache : mDrawableCache, key);
if (dr != null) {
return dr;
}
- Drawable.ConstantState cs = sPreloadedDrawables.get(key);
+ Drawable.ConstantState cs = isColorDrawable ? sPreloadedColorDrawables.get(key) : sPreloadedDrawables.get(key);
if (cs != null) {
dr = cs.newDrawable(this);
} else {
@@ -1726,13 +1784,21 @@ public class Resources {
cs = dr.getConstantState();
if (cs != null) {
if (mPreloading) {
- sPreloadedDrawables.put(key, cs);
+ if (isColorDrawable) {
+ sPreloadedColorDrawables.put(key, cs);
+ } else {
+ sPreloadedDrawables.put(key, cs);
+ }
} else {
synchronized (mTmpValue) {
//Log.i(TAG, "Saving cached drawable @ #" +
// Integer.toHexString(key.intValue())
// + " in " + this + ": " + cs);
- mDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));
+ if (isColorDrawable) {
+ mColorDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));
+ } else {
+ mDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));
+ }
}
}
}
@@ -1741,9 +1807,11 @@ public class Resources {
return dr;
}
- private Drawable getCachedDrawable(long key) {
+ private Drawable getCachedDrawable(
+ LongSparseArray<WeakReference<ConstantState>> drawableCache,
+ long key) {
synchronized (mTmpValue) {
- WeakReference<Drawable.ConstantState> wr = mDrawableCache.get(key);
+ WeakReference<Drawable.ConstantState> wr = drawableCache.get(key);
if (wr != null) { // we have the key
Drawable.ConstantState entry = wr.get();
if (entry != null) {
@@ -1753,7 +1821,7 @@ public class Resources {
return entry.newDrawable(this);
}
else { // our entry has been purged
- mDrawableCache.delete(key);
+ drawableCache.delete(key);
}
}
}
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 59c386d..ddc4276 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -162,9 +162,18 @@ public class Camera {
* example, if the camera is in use by another process).
*/
public static Camera open() {
+ CameraSwitch.openMainCamera();
return new Camera();
}
+ /**
+ * Returns a new Camera object for the given cameraNode
+ */
+ public static Camera open(String cameraNode) {
+ CameraSwitch.openCamera(cameraNode);
+ return new Camera();
+ }
+
Camera() {
mShutterCallback = null;
mRawImageCallback = null;
@@ -804,7 +813,11 @@ public class Camera {
* @see #getParameters()
*/
public void setParameters(Parameters params) {
- native_setParameters(params.flatten());
+ try {
+ native_setParameters(params.flatten());
+ } catch (RuntimeException ex) {
+ Log.e(TAG, "Failed to set all parameters");
+ }
}
/**
@@ -893,7 +906,12 @@ public class Camera {
private static final String KEY_GPS_LATITUDE = "gps-latitude";
private static final String KEY_GPS_LONGITUDE = "gps-longitude";
private static final String KEY_GPS_ALTITUDE = "gps-altitude";
+ private static final String KEY_GPS_LATITUDE_REF = "gps-latitude-ref";
+ private static final String KEY_GPS_LONGITUDE_REF = "gps-longitude-ref";
+ private static final String KEY_GPS_ALTITUDE_REF = "gps-altitude-ref";
+ private static final String KEY_GPS_STATUS = "gps-status";
private static final String KEY_GPS_TIMESTAMP = "gps-timestamp";
+ private static final String KEY_EXIF_DATETIME = "exif-datetime";
private static final String KEY_GPS_PROCESSING_METHOD = "gps-processing-method";
private static final String KEY_WHITE_BALANCE = "whitebalance";
private static final String KEY_EFFECT = "effect";
@@ -901,6 +919,8 @@ public class Camera {
private static final String KEY_SCENE_MODE = "scene-mode";
private static final String KEY_FLASH_MODE = "flash-mode";
private static final String KEY_FOCUS_MODE = "focus-mode";
+ private static final String KEY_ISO_MODE = "iso";
+ private static final String KEY_LENSSHADE = "lensshade";
private static final String KEY_FOCAL_LENGTH = "focal-length";
private static final String KEY_HORIZONTAL_VIEW_ANGLE = "horizontal-view-angle";
private static final String KEY_VERTICAL_VIEW_ANGLE = "vertical-view-angle";
@@ -908,11 +928,26 @@ public class Camera {
private static final String KEY_MAX_EXPOSURE_COMPENSATION = "max-exposure-compensation";
private static final String KEY_MIN_EXPOSURE_COMPENSATION = "min-exposure-compensation";
private static final String KEY_EXPOSURE_COMPENSATION_STEP = "exposure-compensation-step";
+ private static final String KEY_AUTO_EXPOSURE = "meter-mode";
private static final String KEY_ZOOM = "zoom";
private static final String KEY_MAX_ZOOM = "max-zoom";
private static final String KEY_ZOOM_RATIOS = "zoom-ratios";
private static final String KEY_ZOOM_SUPPORTED = "zoom-supported";
private static final String KEY_SMOOTH_ZOOM_SUPPORTED = "smooth-zoom-supported";
+ private static final String KEY_SHARPNESS = "sharpness";
+ private static final String KEY_MAX_SHARPNESS = "sharpness-max";
+ private static final String KEY_DEFAULT_SHARPNESS = "sharpness-def";
+ private static final String KEY_CONTRAST = "contrast";
+ private static final String KEY_MAX_CONTRAST = "contrast-max";
+ private static final String KEY_DEFAULT_CONTRAST = "contrast-def";
+ private static final String KEY_SATURATION = "saturation";
+ private static final String KEY_MAX_SATURATION = "saturation-max";
+ private static final String KEY_DEFAULT_SATURATION = "saturation-def";
+ private static final String KEY_BRIGHTNESS = "brightness";
+ private static final String KEY_MAX_BRIGHTNESS = "brightness-max";
+ private static final String KEY_DEFAULT_BRIGHTNESS = "brightness-def";
+ private static final String KEY_SMART_CONTRAST = "smart-contrast";
+
// Parameter key suffix for supported values.
private static final String SUPPORTED_VALUES_SUFFIX = "-values";
@@ -939,12 +974,34 @@ public class Camera {
public static final String EFFECT_BLACKBOARD = "blackboard";
public static final String EFFECT_AQUA = "aqua";
+ // Values for auto exposure settings.
+ public static final String AUTO_EXPOSURE_FRAME_AVG = "meter-average";
+ public static final String AUTO_EXPOSURE_CENTER_WEIGHTED = "meter-center";
+ public static final String AUTO_EXPOSURE_SPOT_METERING = "meter-spot";
+
// Values for antibanding settings.
public static final String ANTIBANDING_AUTO = "auto";
public static final String ANTIBANDING_50HZ = "50hz";
public static final String ANTIBANDING_60HZ = "60hz";
public static final String ANTIBANDING_OFF = "off";
+ //Values for ISO settings
+
+ public static final String ISO_AUTO = "auto";
+ public static final String ISO_HJR = "deblur";
+ public static final String ISO_100 = "100";
+ public static final String ISO_200 = "200";
+ public static final String ISO_400 = "400";
+ public static final String ISO_800 = "800";
+ public static final String ISO_1250 = "1250";
+
+ //Values for Lens Shading
+
+ public static final String LENSSHADE_ENABLE = "enable";
+ public static final String LENSSHADE_DISABLE= "disable";
+
+
+
// Values for flash mode settings.
/**
* Flash will not be fired.
@@ -1008,6 +1065,7 @@ public class Camera {
* {@link #autoFocus(AutoFocusCallback)} in this mode.
*/
public static final String FOCUS_MODE_INFINITY = "infinity";
+ public static final String FOCUS_MODE_NORMAL = "normal";
public static final String FOCUS_MODE_MACRO = "macro";
/**
@@ -1145,7 +1203,8 @@ public class Camera {
* @return the int value of the parameter
*/
public int getInt(String key) {
- return Integer.parseInt(mMap.get(key));
+ String value = mMap.get(key);
+ return value == null ? 0 : Integer.parseInt(value);
}
/**
@@ -1330,6 +1389,9 @@ public class Camera {
*/
public List<Integer> getSupportedPreviewFormats() {
String str = get(KEY_PREVIEW_FORMAT + SUPPORTED_VALUES_SUFFIX);
+ if (str == null) {
+ str = get(KEY_PREVIEW_FORMAT);
+ }
ArrayList<Integer> formats = new ArrayList<Integer>();
for (String s : split(str)) {
int f = pixelFormatForCameraFormat(s);
@@ -1482,6 +1544,15 @@ public class Camera {
}
/**
+ * Sets GPS latitude reference coordinate. This will be stored in JPEG EXIF
+ * header.
+ * @param latitude GPS latitude reference coordinate.
+ */
+ public void setGpsLatitudeRef(String latRef) {
+ set(KEY_GPS_LATITUDE_REF, latRef);
+ }
+
+ /**
* Sets GPS latitude coordinate. This will be stored in JPEG EXIF
* header.
*
@@ -1492,6 +1563,15 @@ public class Camera {
}
/**
+ * Sets GPS longitude reference coordinate. This will be stored in JPEG EXIF
+ * header.
+ * @param latitude GPS longitude reference coordinate.
+ */
+ public void setGpsLongitudeRef(String lonRef) {
+ set(KEY_GPS_LONGITUDE_REF, lonRef);
+ }
+
+ /**
* Sets GPS longitude coordinate. This will be stored in JPEG EXIF
* header.
*
@@ -1502,6 +1582,14 @@ public class Camera {
}
/**
+ * Sets GPS altitude reference. This will be stored in JPEG EXIF header.
+ * @param altitude reference GPS altitude in meters.
+ */
+ public void setGpsAltitudeRef(double altRef) {
+ set(KEY_GPS_ALTITUDE_REF, Double.toString(altRef));
+ }
+
+ /**
* Sets GPS altitude. This will be stored in JPEG EXIF header.
*
* @param altitude GPS altitude in meters.
@@ -1528,6 +1616,27 @@ public class Camera {
*/
public void setGpsProcessingMethod(String processing_method) {
set(KEY_GPS_PROCESSING_METHOD, processing_method);
+
+ }
+
+ /**
+ * Sets system timestamp. This will be stored in JPEG EXIF header.
+ *
+ * @param timestamp current timestamp (UTC in seconds since January 1,
+ * 1970).
+ */
+ public void setExifDateTime(String dateTime) {
+ set(KEY_EXIF_DATETIME, dateTime);
+ }
+
+ /**
+ * Sets GPS Status. This will be stored in JPEG EXIF header.
+ *
+ * @param status GPS status (UTC in seconds since January 1,
+ * 1970).
+ */
+ public void setGpsStatus(double status) {
+ set(KEY_GPS_STATUS, Double.toString(status));
}
/**
@@ -1535,8 +1644,11 @@ public class Camera {
* parameters.
*/
public void removeGpsData() {
+ remove(KEY_GPS_LATITUDE_REF);
remove(KEY_GPS_LATITUDE);
+ remove(KEY_GPS_LONGITUDE_REF);
remove(KEY_GPS_LONGITUDE);
+ remove(KEY_GPS_ALTITUDE_REF);
remove(KEY_GPS_ALTITUDE);
remove(KEY_GPS_TIMESTAMP);
remove(KEY_GPS_PROCESSING_METHOD);
@@ -1626,6 +1738,166 @@ public class Camera {
/**
+ * Get Sharpness level
+ *
+ * @return sharpness level
+ */
+ public float getSharpness(){
+ return getFloat(KEY_SHARPNESS, 0.0f);
+ }
+
+ /**
+ * Set Sharpness Level
+ *
+ * @param sharpness level
+ */
+ public void setSharpness(float sharpness){
+ if((sharpness < 0) || (sharpness > getMaxSharpness()) )
+ throw new IllegalArgumentException(
+ "Invalid Sharpness " + sharpness);
+
+ set(KEY_SHARPNESS, String.valueOf(sharpness));
+ }
+
+ /**
+ * Get Max Sharpness Level
+ *
+ * @return max sharpness level
+ */
+ public float getMaxSharpness(){
+ return getFloat(KEY_MAX_SHARPNESS, 0.0f);
+ }
+
+ /**
+ * Get default sharpness level
+ *
+ * @return default sharpness level
+ */
+ public float getDefaultSharpness() {
+ return getFloat(KEY_DEFAULT_SHARPNESS, 0.0f);
+ }
+
+ /**
+ * Get Contrast level
+ *
+ * @return contrast level
+ */
+ public float getContrast(){
+ return getFloat(KEY_CONTRAST, 0.0f);
+ }
+
+ /**
+ * Set Contrast Level
+ *
+ * @param contrast level
+ */
+ public void setContrast(float contrast){
+ if((contrast < 0 ) || (contrast > getMaxContrast()))
+ throw new IllegalArgumentException(
+ "Invalid Contrast " + contrast);
+
+ set(KEY_CONTRAST, String.valueOf(contrast));
+ }
+
+ /**
+ * Get Max Contrast Level
+ *
+ * @return max contrast level
+ */
+ public float getMaxContrast(){
+ return getFloat(KEY_MAX_CONTRAST, 0.0f);
+ }
+
+ /**
+ * Get default contrast level
+ *
+ * @return default contrast level
+ */
+ public float getDefaultContrast() {
+ return getFloat(KEY_DEFAULT_CONTRAST, 0.0f);
+ }
+
+ /**
+ * Get Saturation level
+ *
+ * @return saturation level
+ */
+ public float getSaturation(){
+ return getFloat(KEY_SATURATION, 0.0f);
+ }
+
+ /**
+ * Set Saturation Level
+ *
+ * @param saturation level
+ */
+ public void setSaturation(float saturation){
+ if((saturation < 0 ) || (saturation > getMaxSaturation()))
+ throw new IllegalArgumentException(
+ "Invalid Saturation " + saturation);
+
+ set(KEY_SATURATION, String.valueOf(saturation));
+ }
+
+ /**
+ * Get Max Saturation Level
+ *
+ * @return max contrast level
+ */
+ public float getMaxSaturation(){
+ return getFloat(KEY_MAX_SATURATION, 0.0f);
+ }
+
+ /**
+ * Get default saturation level
+ *
+ * @return default saturation level
+ */
+ public float getDefaultSaturation() {
+ return getFloat(KEY_DEFAULT_SATURATION, 0.0f);
+ }
+
+ /**
+ * Get brightness level
+ *
+ * @return brightness level
+ */
+ public float getBrightness(){
+ return getFloat(KEY_BRIGHTNESS, 0.0f);
+ }
+
+ /**
+ * Set brightness level
+ *
+ * @param brightness level
+ */
+ public void setBrightness(float brightness){
+ if((brightness < 0 ) || (brightness > getMaxBrightness()))
+ throw new IllegalArgumentException(
+ "Invalid Brightness " + brightness);
+
+ set(KEY_BRIGHTNESS, String.valueOf(brightness));
+ }
+
+ /**
+ * Get Max Brightness Level
+ *
+ * @return max brightness level
+ */
+ public float getMaxBrightness(){
+ return getFloat(KEY_MAX_BRIGHTNESS, 0.0f);
+ }
+
+ /**
+ * Get default brightness level
+ *
+ * @return default brightness level
+ */
+ public float getDefaultBrightness() {
+ return getFloat(KEY_DEFAULT_BRIGHTNESS, 0.0f);
+ }
+
+ /**
* Gets the current antibanding setting.
*
* @return current antibanding. null if antibanding setting is not
@@ -1903,7 +2175,11 @@ public class Camera {
* @param value zoom value. The valid range is 0 to {@link #getMaxZoom}.
*/
public void setZoom(int value) {
- set(KEY_ZOOM, value);
+ if (mMap.containsKey("taking-picture-zoom")) {
+ set("taking-picture-zoom", value);
+ } else {
+ set(KEY_ZOOM, value);
+ }
}
/**
@@ -1914,7 +2190,7 @@ public class Camera {
*/
public boolean isZoomSupported() {
String str = get(KEY_ZOOM_SUPPORTED);
- return TRUE.equals(str);
+ return TRUE.equals(str) && getMaxZoom() > 0;
}
/**
@@ -1927,7 +2203,11 @@ public class Camera {
* @return the maximum zoom value supported by the camera.
*/
public int getMaxZoom() {
- return getInt(KEY_MAX_ZOOM, 0);
+ if (mMap.containsKey("taking-picture-zoom-max")) {
+ return getInt("taking-picture-zoom-max", 0);
+ } else {
+ return getInt(KEY_MAX_ZOOM, 0);
+ }
}
/**
@@ -1955,6 +2235,112 @@ public class Camera {
return TRUE.equals(str);
}
+ /**
+ * Gets the current ISO setting.
+ *
+ * @return one of ISO_XXX string constant. null if ISO
+ * setting is not supported.
+ */
+ public String getISOValue() {
+ return get(KEY_ISO_MODE);
+ }
+
+ /**
+ * Sets the ISO.
+ *
+ * @param iso ISO_XXX string constant.
+ */
+ public void setISOValue(String iso) {
+ set(KEY_ISO_MODE, iso);
+ }
+
+ /**
+ * Gets the supported ISO values.
+ *
+ * @return a List of FLASH_MODE_XXX string constants. null if flash mode
+ * setting is not supported.
+ */
+ public List<String> getSupportedIsoValues() {
+ String str = get(KEY_ISO_MODE + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /**
+ * Gets the current LensShade Mode.
+ *
+ * @return LensShade Mode
+ */
+ public String getLensShade() {
+ return get(KEY_LENSSHADE);
+ }
+
+ /**
+ * Sets the current LensShade Mode.
+ *
+ * @return LensShade Mode
+ */
+ public void setLensShade(String lensshade) {
+ set(KEY_LENSSHADE, lensshade);
+ }
+
+ /**
+ * Gets the supported Lensshade modes.
+ *
+ * @return a List of LENS_MODE_XXX string constants. null if lens mode
+ * setting is not supported.
+ */
+ public List<String> getSupportedLensShadeModes() {
+ String str = get(KEY_LENSSHADE + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /**
+ * Gets the current auto exposure setting.
+ *
+ * @return one of AUTO_EXPOSURE_XXX string constant. null if auto exposure
+ * setting is not supported.
+ */
+ public String getAutoExposure() {
+ return get(KEY_AUTO_EXPOSURE);
+ }
+
+ /**
+ * Sets the current auto exposure setting.
+ *
+ * @param value AUTO_EXPOSURE_XXX string constants.
+ */
+ public void setAutoExposure(String value) {
+ set(KEY_AUTO_EXPOSURE, value);
+ }
+
+ /**
+ * Gets the supported auto exposure setting.
+ *
+ * @return a List of AUTO_EXPOSURE_XXX string constants. null if auto exposure
+ * setting is not supported.
+ */
+ public List<String> getSupportedAutoexposure() {
+ String str = get(KEY_AUTO_EXPOSURE + SUPPORTED_VALUES_SUFFIX);
+ return split(str);
+ }
+
+ /**
+ * Sets the smart-contrast feature
+ * @param boolean
+ */
+ public void setSmartContrastEnabled(boolean enabled) {
+ set(KEY_SMART_CONTRAST, enabled ? "on" : "off");
+ }
+
+ /**
+ * Gets the value of smart-contrast
+ *
+ * @return if smart-contrast is enabled
+ */
+ public boolean isSmartContrastEnabled() {
+ return "on".equals(get(KEY_SMART_CONTRAST));
+ }
+
// Splits a comma delimited string to an ArrayList of String.
// Return null if the passing string is null or the size is 0.
private ArrayList<String> split(String str) {
@@ -1986,6 +2372,9 @@ public class Camera {
// Returns the value of a float parameter.
private float getFloat(String key, float defaultValue) {
+ if (!mMap.containsKey(key)) {
+ return defaultValue;
+ }
try {
return Float.parseFloat(mMap.get(key));
} catch (NumberFormatException ex) {
@@ -1995,6 +2384,9 @@ public class Camera {
// Returns the value of a integer parameter.
private int getInt(String key, int defaultValue) {
+ if (!mMap.containsKey(key)) {
+ return defaultValue;
+ }
try {
return Integer.parseInt(mMap.get(key));
} catch (NumberFormatException ex) {
diff --git a/core/java/android/hardware/CameraSwitch.java b/core/java/android/hardware/CameraSwitch.java
new file mode 100644
index 0000000..2475630
--- /dev/null
+++ b/core/java/android/hardware/CameraSwitch.java
@@ -0,0 +1,80 @@
+package android.hardware;
+
+import android.util.Log;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+/**
+ * Handle switching for HTC devices with dual cameras.
+ */
+public class CameraSwitch {
+
+ public static final String SWITCH_CAMERA_MAIN = "main";
+
+ public static final String SWITCH_CAMERA_SECONDARY = "secondary";
+
+ private static final String SWITCH_CAMERA_FILE_PATH = "/sys/android_camera2/htcwc";
+
+ private static final String LOG_TAG = "CameraSwitch";
+
+ private static final boolean HAS_CAMERA_SWITCH;
+
+ static {
+ final File file = new File(SWITCH_CAMERA_FILE_PATH);
+ HAS_CAMERA_SWITCH = file.exists();
+ }
+
+ private static boolean setHTCCameraSwitch(String cameraSwitch) {
+ if (!HAS_CAMERA_SWITCH) {
+ return false;
+ }
+
+ final String node;
+ if (SWITCH_CAMERA_MAIN.equals(cameraSwitch)) {
+ node = "0";
+ Log.d(LOG_TAG, "Open main camera");
+ } else if (SWITCH_CAMERA_SECONDARY.equals(cameraSwitch)) {
+ node = "1";
+ Log.d(LOG_TAG, "Open secondary camera");
+ } else {
+ Log.e(LOG_TAG, "Unknown camera node: " + cameraSwitch + ", using main");
+ node = "0";
+ }
+
+ final File file = new File(SWITCH_CAMERA_FILE_PATH);
+ BufferedWriter writer = null;
+ try {
+ writer = new BufferedWriter(new FileWriter(file));
+ writer.write(node);
+ writer.flush();
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "Can't open " + SWITCH_CAMERA_FILE_PATH, e);
+ return false;
+ } finally {
+ try {
+ if (writer != null) {
+ writer.close();
+ }
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "Error closing " + SWITCH_CAMERA_FILE_PATH, e);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static void openCamera(String cameraNode) {
+ setHTCCameraSwitch(cameraNode);
+ }
+
+ public static void openMainCamera() {
+ setHTCCameraSwitch(SWITCH_CAMERA_MAIN);
+ }
+
+ public static boolean hasCameraSwitch() {
+ return HAS_CAMERA_SWITCH;
+ }
+}
diff --git a/core/java/android/hardware/HtcFrontFacingCamera.java b/core/java/android/hardware/HtcFrontFacingCamera.java
new file mode 100644
index 0000000..5846579
--- /dev/null
+++ b/core/java/android/hardware/HtcFrontFacingCamera.java
@@ -0,0 +1,14 @@
+package android.hardware;
+
+/**
+ * For compatibility with apps written for the EVO 4G.
+ *
+ * @hide
+ */
+public class HtcFrontFacingCamera extends Camera {
+
+ public static Camera getCamera() {
+ return open(CameraSwitch.SWITCH_CAMERA_SECONDARY);
+ }
+
+}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 280ded6..daf86c8 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -200,7 +200,8 @@ public class ConnectivityManager
private IConnectivityManager mService;
static public boolean isNetworkTypeValid(int networkType) {
- return networkType >= 0 && networkType <= MAX_NETWORK_TYPE;
+ // HACK! Accept TYPE_WIMAX even though we don't support it yet
+ return TYPE_WIMAX == networkType || (networkType >= 0 && networkType <= MAX_NETWORK_TYPE);
}
public void setNetworkPreference(int preference) {
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 649cb8c..cfb4b30 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -373,4 +373,13 @@ public class NetworkInfo implements Parcelable {
return new NetworkInfo[size];
}
};
+
+ /**
+ * HACK! Get an empty NetworkInfo object for WIMAX stub
+ * @hide
+ */
+ public static final NetworkInfo getEmptyWimaxNetworkInfo() {
+ return new NetworkInfo(ConnectivityManager.TYPE_WIMAX, 0, "", "");
+ }
+
}
diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java
index 66eefb2..39d4ac1 100644
--- a/core/java/android/net/Proxy.java
+++ b/core/java/android/net/Proxy.java
@@ -16,12 +16,20 @@
package android.net;
+import org.apache.harmony.luni.platform.INetworkSystem;
+import org.apache.harmony.luni.platform.Platform;
+import org.apache.http.HttpHost;
+
import android.content.ContentResolver;
import android.content.Context;
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.Log;
+import java.net.InetAddress;
+import java.net.URI;
+import java.net.UnknownHostException;
+
import junit.framework.Assert;
/**
@@ -36,6 +44,8 @@ final public class Proxy {
static final public String PROXY_CHANGE_ACTION =
"android.intent.action.PROXY_CHANGE";
+ static final private INetworkSystem NETIMPL = Platform.getNetworkSystem();
+
/**
* Return the proxy host set by the user.
* @param ctx A Context used to get the settings for the proxy host.
@@ -120,4 +130,74 @@ final public class Proxy {
}
}
+ /**
+ * Returns the preferred proxy to be used by clients. This is a wrapper
+ * around {@link android.net.Proxy#getHost()}. Currently no proxy will
+ * be returned for localhost or if the active network is Wi-Fi.
+ *
+ * @param context the context which will be passed to
+ * {@link android.net.Proxy#getHost()}
+ * @param url the target URL for the request
+ * @note Calling this method requires permission
+ * android.permission.ACCESS_NETWORK_STATE
+ * @return The preferred proxy to be used by clients, or null if there
+ * is no proxy.
+ *
+ * {@hide}
+ */
+ static final public HttpHost getPreferredHttpHost(Context context,
+ String url) {
+ if (!isLocalHost(url) && !isNetworkWifi(context)) {
+ final String proxyHost = Proxy.getHost(context);
+ if (proxyHost != null) {
+ return new HttpHost(proxyHost, Proxy.getPort(context), "http");
+ }
+ }
+
+ return null;
+ }
+
+ static final private boolean isLocalHost(String url) {
+ if (url == null) {
+ return false;
+ }
+
+ try {
+ final URI uri = URI.create(url);
+ final String host = uri.getHost();
+ if (host != null) {
+ if (host.equalsIgnoreCase("localhost")) {
+ return true;
+ }
+ if (InetAddress.getByAddress(NETIMPL.ipStringToByteArray(host))
+ .isLoopbackAddress()) {
+ return true;
+ }
+ }
+ } catch (UnknownHostException uex) {
+ // Ignore (INetworkSystem.ipStringToByteArray)
+ } catch (IllegalArgumentException iex) {
+ // Ignore (URI.create)
+ }
+
+ return false;
+ }
+
+ static final private boolean isNetworkWifi(Context context) {
+ if (context == null) {
+ return false;
+ }
+
+ final ConnectivityManager connectivity = (ConnectivityManager)
+ context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (connectivity != null) {
+ final NetworkInfo info = connectivity.getActiveNetworkInfo();
+ if (info != null &&
+ info.getType() == ConnectivityManager.TYPE_WIFI) {
+ return true;
+ }
+ }
+
+ return false;
+ }
};
diff --git a/core/java/android/net/http/Headers.java b/core/java/android/net/http/Headers.java
index 09f6f4f..74c0de8 100644
--- a/core/java/android/net/http/Headers.java
+++ b/core/java/android/net/http/Headers.java
@@ -262,7 +262,14 @@ public final class Headers {
break;
case HASH_CACHE_CONTROL:
if (name.equals(CACHE_CONTROL)) {
- mHeaders[IDX_CACHE_CONTROL] = val;
+ // In case where we receive more than one header, create a ',' separated list.
+ // This should be ok, according to RFC 2616 chapter 4.2
+ if (mHeaders[IDX_CACHE_CONTROL] != null &&
+ mHeaders[IDX_CACHE_CONTROL].length() > 0) {
+ mHeaders[IDX_CACHE_CONTROL] += (',' + val);
+ } else {
+ mHeaders[IDX_CACHE_CONTROL] = val;
+ }
}
break;
case HASH_LAST_MODIFIED:
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 2e14667..86f9a6b 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -94,7 +94,8 @@ public final class Debug
/**
* Default trace file path and file
*/
- private static final String DEFAULT_TRACE_PATH_PREFIX = "/sdcard/";
+ private static final String DEFAULT_TRACE_PATH_PREFIX =
+ Environment.getExternalStorageDirectory().getPath() + "/";
private static final String DEFAULT_TRACE_BODY = "dmtrace";
private static final String DEFAULT_TRACE_EXTENSION = ".trace";
private static final String DEFAULT_TRACE_FILE_PATH =
@@ -127,7 +128,7 @@ public final class Debug
public int otherPrivateDirty;
/** The shared dirty pages used by everything else. */
public int otherSharedDirty;
-
+
public MemoryInfo() {
}
@@ -137,21 +138,21 @@ public final class Debug
public int getTotalPss() {
return dalvikPss + nativePss + otherPss;
}
-
+
/**
* Return total private dirty memory usage in kB.
*/
public int getTotalPrivateDirty() {
return dalvikPrivateDirty + nativePrivateDirty + otherPrivateDirty;
}
-
+
/**
* Return total shared dirty memory usage in kB.
*/
public int getTotalSharedDirty() {
return dalvikSharedDirty + nativeSharedDirty + otherSharedDirty;
}
-
+
public int describeContents() {
return 0;
}
@@ -179,7 +180,7 @@ public final class Debug
otherPrivateDirty = source.readInt();
otherSharedDirty = source.readInt();
}
-
+
public static final Creator<MemoryInfo> CREATOR = new Creator<MemoryInfo>() {
public MemoryInfo createFromParcel(Parcel source) {
return new MemoryInfo(source);
@@ -460,7 +461,7 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo
* Like startMethodTracing(String, int, int), but taking an already-opened
* FileDescriptor in which the trace is written. The file name is also
* supplied simply for logging. Makes a dup of the file descriptor.
- *
+ *
* Not exposed in the SDK unless we are really comfortable with supporting
* this and find it would be useful.
* @hide
@@ -1070,7 +1071,7 @@ href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Lo
* static {
* // Sets all the fields
* Debug.setFieldsOn(MyDebugVars.class);
- *
+ *
* // Sets only the fields annotated with @Debug.DebugProperty
* // Debug.setFieldsOn(MyDebugVars.class, true);
* }
diff --git a/core/java/android/preference/ListPreference.java b/core/java/android/preference/ListPreference.java
index f842d75..f44cbe4 100644
--- a/core/java/android/preference/ListPreference.java
+++ b/core/java/android/preference/ListPreference.java
@@ -39,6 +39,7 @@ public class ListPreference extends DialogPreference {
private CharSequence[] mEntries;
private CharSequence[] mEntryValues;
private String mValue;
+ private String mSummary;
private int mClickedDialogEntryIndex;
public ListPreference(Context context, AttributeSet attrs) {
@@ -49,8 +50,16 @@ public class ListPreference extends DialogPreference {
mEntries = a.getTextArray(com.android.internal.R.styleable.ListPreference_entries);
mEntryValues = a.getTextArray(com.android.internal.R.styleable.ListPreference_entryValues);
a.recycle();
+
+ /* Retrieve the Preference summary attribute since it's private
+ * in the Preference class.
+ */
+ a = context.obtainStyledAttributes(attrs,
+ com.android.internal.R.styleable.Preference, 0, 0);
+ mSummary = a.getString(com.android.internal.R.styleable.Preference_summary);
+ a.recycle();
}
-
+
public ListPreference(Context context) {
this(context, null);
}
@@ -127,6 +136,43 @@ public class ListPreference extends DialogPreference {
}
/**
+ * Returns the summary of this ListPreference. If the summary
+ * has a {@linkplain java.lang.String#format String formatting}
+ * marker in it (i.e. "%s" or "%1$s"), then the current entry
+ * value will be substituted in its place.
+ *
+ * @return the summary with appropriate string substitution
+ */
+ @Override
+ public CharSequence getSummary() {
+ final CharSequence entry = getEntry();
+ if (mSummary == null || entry == null) {
+ return super.getSummary();
+ } else {
+ return String.format(mSummary, entry);
+ }
+ }
+
+ /**
+ * Sets the summary for this Preference with a CharSequence.
+ * If the summary has a
+ * {@linkplain java.lang.String#format String formatting}
+ * marker in it (i.e. "%s" or "%1$s"), then the current entry
+ * value will be substituted in its place when it's retrieved.
+ *
+ * @param summary The summary for the preference.
+ */
+ @Override
+ public void setSummary(CharSequence summary) {
+ super.setSummary(summary);
+ if (summary == null && mSummary != null) {
+ mSummary = null;
+ } else if (summary != null && !summary.equals(mSummary)) {
+ mSummary = summary.toString();
+ }
+ }
+
+ /**
* Sets the value to the given index from the entry values.
*
* @param index The index of the value to set.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e12dfb0..9109bd6 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1526,14 +1526,202 @@ public final class Settings {
public static final String FANCY_IME_ANIMATIONS = "fancy_ime_animations";
/**
+ * Whether WebViews reflow content when zooming in by pinching. The value is
+ * boolean (1 or 0).
+ * @hide
+ */
+ public static final String WEB_VIEW_PINCH_REFLOW = "web_view_pinch_reflow";
+
+ /**
* Control whether the accelerometer will be used to change screen
* orientation. If 0, it will not be used unless explicitly requested
* by the application; if 1, it will be used by default unless explicitly
* disabled by the application.
*/
public static final String ACCELEROMETER_ROTATION = "accelerometer_rotation";
+
+ /**
+ * Control the type of rotation which can be performed using the accelerometer
+ * if ACCELEROMETER_ROTATION is enabled.
+ * Value is a bitwise combination of
+ * 1 = 90 degrees (left)
+ * 2 = 180 degrees (inverted)
+ * 4 = 270 degrees (right)
+ * Normal portrait (0 degrees) is always enabled
+ * Default is 5 (90 & 270 degrees) like stock Froyo
+ * @hide
+ */
+ public static final String ACCELEROMETER_ROTATION_MODE = "accelerometer_rotation_mode";
+
+ /**
+ * Specifies the number of recent apps to show (8, 12, 16)
+ * @hide
+ */
+ public static final String RECENT_APPS_NUMBER = "recent_apps_number";
+
+ /**
+ * Specifies the number of recent apps to show (8, 12, 16)
+ * @hide
+ */
+ public static final String RECENT_APPS_SHOW_TITLE = "recent_apps_show_title";
+
+ /**
+ * Specifies whether or not to use a custom app instead of the recent applications dialog
+ * @hide
+ */
+ public static final String USE_CUSTOM_APP = "use_custom_app";
+
+ /**
+ * Stores the uri of the custom application to use
+ * @hide
+ */
+ public static final String SELECTED_CUSTOM_APP = "selected_custom_app";
+
+ /**
+ * Toggles whether to display the PLMN field on the Lockscreen
+ * @hide
+ */
+ public static final String SHOW_PLMN_LS = "show_plmn_ls";
+
+ /**
+ * Toggles whether to display the SPN field on the Lockscreen
+ * @hide
+ */
+ public static final String SHOW_SPN_LS = "show_spn_ls";
+
+ /**
+ * Toggles whether to display the PLMN field on the Notification bar
+ * @hide
+ */
+ public static final String SHOW_PLMN_SB = "show_plmn_sb";
+
+ /**
+ * Toggles whether to display the SPN field on the Notification bar
+ * @hide
+ */
+ public static final String SHOW_SPN_SB = "show_spn_sb";
+
+ /**
+ * Specifies whether to show or hide clock
+ * @hide
+ */
+ public static final String SHOW_STATUS_CLOCK = "show_status_clock";
+
+ /**
+ * Specifies the clock color
+ * @hide
+ */
+ public static final String CLOCK_COLOR = "clock_color";
+
+ /**
+ * Specifies whether to show or hide the dbm signal level
+ * @hide
+ */
+ public static final String SHOW_STATUS_DBM = "show_status_dbm";
+
+ /**
+ * Specifies the dbm signal level color
+ * @hide
+ */
+ public static final String DBM_COLOR = "dbm_color";
+
+ /**
+ * Specifies whether to prompt on the power dialog
+ * @hide
+ */
+ public static final String POWER_DIALOG_PROMPT = "power_dialog_prompt";
+
+ /**
+ * Specifies notification count color
+ * @hide
+ */
+ public static final String NOTIF_COUNT_COLOR = "notifications_count_color";
+
+ /**
+ * Specifies the date color
+ * @hide
+ */
+ public static final String DATE_COLOR = "date_color";
+
+ /**
+ * Specifies new notification ticker color
+ * @hide
+ */
+ public static final String NEW_NOTIF_TICKER_COLOR = "new_notifications_ticker_color";
+
+ /**
+ * Specifies no notifications color
+ * @hide
+ */
+ public static final String NO_NOTIF_COLOR = "no_notifications_color";
+
+ /**
+ * Specifies latest nofitication color
+ * @hide
+ */
+ public static final String LATEST_NOTIF_COLOR = "latest_notifications_color";
+
+ /**
+ * Specifies ongoing notification color
+ * @hide
+ */
+ public static final String ONGOING_NOTIF_COLOR = "ongoing_notifications_color";
+
+ /**
+ * Specifies spn label color
+ * @hide
+ */
+ public static final String SPN_LABEL_COLOR = "spn_label_color";
+
+ /**
+ * Specifies plmn color
+ * @hide
+ */
+ public static final String PLMN_LABEL_COLOR = "plmn_label_color";
+
+ /**
+ * Specifies clear button color
+ * @hide
+ */
+ public static final String CLEAR_BUTTON_LABEL_COLOR = "clear_button_label_color";
+
+ /**
+ * Specifies notification item title color.
+ * @hide
+ */
+ public static final String NOTIF_ITEM_TITLE_COLOR = "notifications_title_color";
+
+ /**
+ * Specifies notification item text color.
+ * @hide
+ */
+ public static final String NOTIF_ITEM_TEXT_COLOR = "notifications_text_color";
+
+ /**
+ * Specifies notification item time color.
+ * @hide
+ */
+ public static final String NOTIF_ITEM_TIME_COLOR = "notifications_time_color";
/**
+ * Whether to show the battery level percentage overlayed on the icon.
+ * @hide
+ */
+ public static final String BATTERY_PERCENTAGE_STATUS_ICON = "battery_percentage_status_icon";
+
+ /**
+ * Specifies battery percentage status color
+ * @hide
+ */
+ public static final String BATTERY_PERCENTAGE_STATUS_COLOR = "battery_status_color_title";
+
+ /**
+ * Specifies whether to show AM/PM indicators for 12-hour clock
+ * @hide
+ */
+ public static final String SHOW_TWELVE_HOUR_CLOCK_PERIOD = "show_clock_period";
+
+ /**
* Whether the audible DTMF tones are played by the dialer when dialing. The value is
* boolean (1 or 0).
*/
@@ -1596,6 +1784,72 @@ public final class Settings {
public static final String HAPTIC_FEEDBACK_ENABLED = "haptic_feedback_enabled";
/**
+ * Whether haptic feedback is enabled on virtual key release (as opposed to pressed)
+ * boolean (1 or 0).
+ * @hide
+ */
+ public static final String HAPTIC_FEEDBACK_UP_ENABLED = "haptic_feedback_up_enabled";
+
+ /**
+ * Whether haptic is also activated for all screen interaction (follows Sound Effects Enabled behaviour)
+ * boolean (1 or 0).
+ * @hide
+ */
+ public static final String HAPTIC_FEEDBACK_ALL_ENABLED = "haptic_feedback_all_enabled";
+
+ /**
+ * Value for haptic down (string will be converted to array -
+ * format is ***"delay in msec before turning on"_"delay in msec before turning off__**repeat**)
+ * @hide
+ */
+ public static final String HAPTIC_DOWN_ARRAY = "haptic_down_array";
+
+ /**
+ * Value for haptic up - same format as _DOWN_ARRAY
+ * @hide
+ */
+ public static final String HAPTIC_UP_ARRAY = "haptic_up_array";
+
+ /**
+ * Value for long presses - same format as _DOWN_ARRAY
+ * @hide
+ */
+ public static final String HAPTIC_LONG_ARRAY = "haptic_long_array";
+
+ /**
+ * these store the ORIGINAL default haptic values from config.xml
+ * this is so HapticAdjust can easily pull them when resetting defaults
+ * these are created and acted on in PhoneWindowManager
+ * @hide
+ */
+ public static final String HAPTIC_DOWN_ARRAY_DEFAULT = "haptic_down_array_default";
+
+ /**
+ * Same as HAPTIC_DOWN_ARRAY_DEFAULT but for key releases
+ * @hide
+ */
+ public static final String HAPTIC_UP_ARRAY_DEFAULT = "haptic_up_array_default";
+
+ /**
+ * Same as HAPTIC_DOWN_ARRAY_DEFAULT but for key releases
+ * @hide
+ */
+ public static final String HAPTIC_LONG_ARRAY_DEFAULT = "haptic_long_array_default";
+
+ /**
+ * Set values for haptic feedback from typing on keypad (new for Froyo)
+ * @hide
+ */
+ public static final String HAPTIC_TAP_ARRAY = "haptic_tap_array";
+
+ /**
+ * Default values for haptic feedback from typing on keypad (new for Froyo) - pulled
+ * from config.xml
+ * @hide
+ */
+ public static final String HAPTIC_TAP_ARRAY_DEFAULT = "haptic_tap_array_default";
+
+ /**
* Whether live web suggestions while the user types into search dialogs are
* enabled. Browsers and other search UIs should respect this, as it allows
* a user to avoid sending partial queries to a search engine, if it poses
@@ -1679,6 +1933,66 @@ public final class Settings {
public static final String UNLOCK_SOUND = "unlock_sound";
/**
+ * Whether to wake the screen with the trackball. The value is boolean (1 or 0).
+ * @hide
+ */
+ public static final String TRACKBALL_WAKE_SCREEN = "trackball_wake_screen";
+
+ /**
+ * Whether to unlock the screen with the trackball. The value is boolean (1 or 0).
+ * @hide
+ */
+ public static final String TRACKBALL_UNLOCK_SCREEN = "trackball_unlock_screen";
+
+ /**
+ * Pulse the Trackball with Screen On. The value is boolean (1 or 0).
+ * @hide
+ */
+ public static final String TRACKBALL_SCREEN_ON = "trackball_screen_on";
+
+ /**
+ * Whether to unlock the menu key. The value is boolean (1 or 0).
+ * @hide
+ */
+ public static final String MENU_UNLOCK_SCREEN = "menu_unlock_screen";
+
+ /**
+ * Color mask tp apply to notification bar when custom is set
+ * @hide
+ */
+ public static final String NOTIF_BAR_COLOR = "notif_bar_color";
+
+ /**
+ * Whether to use custom notification bar
+ * @hide
+ */
+ public static final String NOTIF_BAR_CUSTOM = "notif_bar_custom";
+
+ /**
+ * Whether to use custom notification bar
+ * @hide
+ */
+ public static final String LOCKSCREEN_MUSIC_CONTROLS = "lockscreen_music_controls";
+
+ /**
+ * Whether to use custom notification bar
+ * @hide
+ */
+ public static final String LOCKSCREEN_ALWAYS_MUSIC_CONTROLS = "lockscreen_always_music_controls";
+
+ /**
+ * Whether to use a custom pull-down notification screen
+ * @hide
+ */
+ public static final String NOTIF_EXPANDED_BAR_COLOR = "notif_expanded_bar_color";
+
+ /**
+ * Color mask to apply to pull-down notification screen
+ * @hide
+ */
+ public static final String NOTIF_EXPANDED_BAR_CUSTOM = "notif_expanded_bar_custom";
+
+ /**
* Settings to backup. This is here so that it's in the same place as the settings
* keys and easy to update.
* @hide
@@ -1738,7 +2052,22 @@ public final class Settings {
DOCK_SOUNDS_ENABLED,
LOCKSCREEN_SOUNDS_ENABLED,
SHOW_WEB_SUGGESTIONS,
- NOTIFICATION_LIGHT_PULSE
+ NOTIFICATION_LIGHT_PULSE,
+ HAPTIC_FEEDBACK_UP_ENABLED,
+ HAPTIC_FEEDBACK_ALL_ENABLED,
+ HAPTIC_DOWN_ARRAY,
+ HAPTIC_UP_ARRAY,
+ HAPTIC_LONG_ARRAY,
+ HAPTIC_DOWN_ARRAY_DEFAULT,
+ HAPTIC_UP_ARRAY_DEFAULT,
+ HAPTIC_LONG_ARRAY_DEFAULT,
+ HAPTIC_TAP_ARRAY,
+ HAPTIC_TAP_ARRAY_DEFAULT,
+ NOTIF_BAR_COLOR,
+ NOTIF_BAR_CUSTOM,
+ NOTIF_EXPANDED_BAR_COLOR,
+ NOTIF_EXPANDED_BAR_CUSTOM
+
};
// Settings moved to Settings.Secure
@@ -2237,6 +2566,12 @@ public final class Settings {
public static final String ADB_ENABLED = "adb_enabled";
/**
+ * Whether to show ADB notifications.
+ * @hide
+ */
+ public static final String ADB_NOTIFY = "adb_notify";
+
+ /**
* Setting to allow mock locations and location provider status to be injected into the
* LocationManager service for testing purposes during application development. These
* locations and status values override actual location and status information generated
@@ -2275,6 +2610,14 @@ public final class Settings {
}
/**
+ * Get the key that retrieves a bluetooth hid device's priority.
+ * @hide
+ */
+ public static final String getBluetoothHidDevicePriorityKey(String address) {
+ return ("bluetooth_hid_device_priority_" + address.toUpperCase());
+ }
+
+ /**
* Whether or not data roaming is enabled. (0 = false, 1 = true)
*/
public static final String DATA_ROAMING = "data_roaming";
@@ -2341,6 +2684,48 @@ public final class Settings {
"lock_pattern_tactile_feedback_enabled";
/**
+ * LOCK_DOTS_VISIBLE
+ * @hide
+ */
+ public static final String LOCK_DOTS_VISIBLE = "lock_pattern_dotsvisible";
+
+ /**
+ * LOCK_SHOW_ERROR_PATH
+ * @hide
+ */
+ public static final String LOCK_SHOW_ERROR_PATH = "lock_pattern_show_error_path";
+
+ /**
+ * LOCK_INCORRECT_DELAY
+ * @hide
+ */
+ public static final String LOCK_INCORRECT_DELAY = "lock_pattern_incorrect_delay";
+
+ /**
+ * SHOW_UNLOCK_TEXT
+ * @hide
+ */
+ public static final String SHOW_UNLOCK_TEXT = "lock_pattern_show_unlock_text";
+
+ /**
+ * SHOW_UNLOCK_ERR_TEXT
+ * @hide
+ */
+ public static final String SHOW_UNLOCK_ERR_TEXT = "lock_pattern_show_unlock_err_text";
+
+ /**
+ * LOCK_SHOW_CUSTOM_MSG
+ * @hide
+ */
+ public static final String LOCK_SHOW_CUSTOM_MSG = "lock_screen_show_custom_msg";
+
+ /**
+ * LOCK_CUSTOM_MSG
+ * @hide
+ */
+ public static final String LOCK_CUSTOM_MSG = "lock_screen_custom_msg";
+
+ /**
* Whether assisted GPS should be enabled or not.
* @hide
*/
@@ -3360,6 +3745,13 @@ public final class Settings {
/**
+ * Whether to allow move of any app to external storage
+ * @hide
+ */
+ public static final String ALLOW_MOVE_ALL_APPS_EXTERNAL =
+ "allow_move_all_apps_external";
+
+ /**
* @hide
*/
public static final String[] SETTINGS_TO_BACKUP = {
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index bf9e854..d271e93 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -25,6 +25,7 @@ import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SqliteWrapper;
import android.net.Uri;
+import android.os.Environment;
import android.telephony.SmsMessage;
import android.text.TextUtils;
import android.util.Config;
@@ -1526,7 +1527,8 @@ public final class Telephony {
* which streams the captured image to the uri. Internally we write the media content
* to this file. It's named '.temp.jpg' so Gallery won't pick it up.
*/
- public static final String SCRAP_FILE_PATH = "/sdcard/mms/scrapSpace/.temp.jpg";
+ public static final String SCRAP_FILE_PATH =
+ Environment.getExternalStorageDirectory().getPath() + "/mms/scrapSpace/.temp.jpg";
}
public static final class Intents {
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index 893db2e..1cac1cd 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -22,6 +22,8 @@
package android.server;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -35,6 +37,7 @@ import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Handler;
import android.os.Message;
+import android.os.SystemClock;
import android.provider.Settings;
import android.util.Log;
@@ -55,7 +58,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
private static final String BLUETOOTH_ENABLED = "bluetooth_enabled";
- private static final int MESSAGE_CONNECT_TO = 1;
+ private static final String ACTION_CONNECT_TO = "android.bluetooth_a2dp.action.CONNECT_TO";
private static final String PROPERTY_STATE = "State";
@@ -111,8 +114,24 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
// after a delay. We delay to avoid connection collisions,
// and to give other profiles such as HFP a chance to
// connect first.
- Message msg = Message.obtain(mHandler, MESSAGE_CONNECT_TO, device);
- mHandler.sendMessageDelayed(msg, 6000);
+ AlarmManager mgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+ Intent i = new Intent(ACTION_CONNECT_TO);
+ i.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
+ PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
+ mgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 6000, pi);
+ }
+ } else if (action.equals(ACTION_CONNECT_TO)) {
+ // check bluetooth is still on, device is still preferred, and
+ // nothing is currently connected
+ if (mBluetoothService.isEnabled() &&
+ getSinkPriority(device) == BluetoothA2dp.PRIORITY_AUTO_CONNECT &&
+ lookupSinksMatchingStates(new int[] {
+ BluetoothA2dp.STATE_CONNECTING,
+ BluetoothA2dp.STATE_CONNECTED,
+ BluetoothA2dp.STATE_PLAYING,
+ BluetoothA2dp.STATE_DISCONNECTING}).size() == 0) {
+ log("Auto-connecting A2DP to sink " + device);
+ connectSink(device);
}
} else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
synchronized (this) {
@@ -180,6 +199,7 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
mIntentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
mIntentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
mIntentFilter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
+ mIntentFilter.addAction(ACTION_CONNECT_TO);
mContext.registerReceiver(mReceiver, mIntentFilter);
mAudioDevices = new HashMap<BluetoothDevice, Integer>();
@@ -201,23 +221,6 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
- switch (msg.what) {
- case MESSAGE_CONNECT_TO:
- BluetoothDevice device = (BluetoothDevice) msg.obj;
- // check bluetooth is still on, device is still preferred, and
- // nothing is currently connected
- if (mBluetoothService.isEnabled() &&
- getSinkPriority(device) == BluetoothA2dp.PRIORITY_AUTO_CONNECT &&
- lookupSinksMatchingStates(new int[] {
- BluetoothA2dp.STATE_CONNECTING,
- BluetoothA2dp.STATE_CONNECTED,
- BluetoothA2dp.STATE_PLAYING,
- BluetoothA2dp.STATE_DISCONNECTING}).size() == 0) {
- log("Auto-connecting A2DP to sink " + device);
- connectSink(device);
- }
- break;
- }
}
};
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index c0e4600..b53779b 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +21,7 @@ import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHid;
import android.bluetooth.BluetoothUuid;
import android.content.Context;
import android.content.Intent;
@@ -380,6 +382,13 @@ class BluetoothEventLoop {
mBluetoothService.setLinkTimeout(address, 8000);
}
} else {
+ // Check and clean-up if bonding is in progress
+ if (mBluetoothService.getBondState().getBondState(address) ==
+ BluetoothDevice.BOND_BONDING) {
+ mBluetoothService.getBondState().setBondState(address,
+ BluetoothDevice.BOND_NONE);
+ }
+
intent = new Intent(BluetoothDevice.ACTION_ACL_DISCONNECTED);
}
intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
@@ -555,6 +564,7 @@ class BluetoothEventLoop {
boolean authorized = false;
ParcelUuid uuid = ParcelUuid.fromString(deviceUuid);
BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
+ BluetoothHid hid = new BluetoothHid(mContext);
// Bluez sends the UUID of the local service being accessed, _not_ the
// remote service
@@ -569,6 +579,15 @@ class BluetoothEventLoop {
} else {
Log.i(TAG, "Rejecting incoming A2DP / AVRCP connection from " + address);
}
+ } else if( mBluetoothService.isEnabled() && BluetoothUuid.isHid(uuid)) {
+ Log.i(TAG, "Allowing incoming HID connection from " + address);
+ BluetoothDevice device = mAdapter.getRemoteDevice(address);
+ authorized = hid.getHidDevicePriority(device) > BluetoothHid.PRIORITY_OFF;
+ if (authorized) {
+ Log.i(TAG, "Allowing incoming HID connection from " + address);
+ } else {
+ Log.i(TAG, "Rejecting incoming HID connection from " + address);
+ }
} else {
Log.i(TAG, "Rejecting incoming " + deviceUuid + " connection from " + address);
}
diff --git a/core/java/android/server/BluetoothHidService.java b/core/java/android/server/BluetoothHidService.java
new file mode 100644
index 0000000..1fd2e04
--- /dev/null
+++ b/core/java/android/server/BluetoothHidService.java
@@ -0,0 +1,462 @@
+/*
+ * Copyright (C) 2009 ISB Corporation
+ * Copyright (C) 2010 0xlab
+ *
+ * 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.
+ */
+
+/**
+ * TODO: Move this to services.jar
+ * and make the contructor package private again.
+ * @hide
+ */
+
+package android.server;
+
+import android.bluetooth.BluetoothHid;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothUuid;
+import android.bluetooth.IBluetoothHid;
+import android.os.ParcelUuid;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.Message;
+import android.provider.Settings;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+public class BluetoothHidService extends IBluetoothHid.Stub {
+ private static final String TAG = "BluetoothHidService";
+ private static final boolean DBG = false;
+
+ public static final String BLUETOOTH_HID_SERVICE = "bluetooth_hid";
+
+ private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
+ private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
+ private static final String BLUETOOTH_ENABLED = "bluetooth_enabled";
+
+ private final Context mContext;
+ private final IntentFilter mIntentFilter;
+ private HashMap<BluetoothDevice, Integer> mHidDevices;
+ private final BluetoothService mBluetoothService;
+ private final BluetoothAdapter mAdapter;
+
+
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ BluetoothDevice device =
+ intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
+ int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
+ BluetoothAdapter.ERROR);
+ switch (state) {
+ case BluetoothAdapter.STATE_ON:
+ onBluetoothEnable();
+ break;
+ case BluetoothAdapter.STATE_TURNING_OFF:
+ onBluetoothDisable();
+ break;
+ }
+ } else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
+ int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
+ BluetoothDevice.ERROR);
+ switch(bondState) {
+ case BluetoothDevice.BOND_BONDED:
+ setHidDevicePriority(device, BluetoothHid.PRIORITY_ON);
+ break;
+ case BluetoothDevice.BOND_BONDING:
+ case BluetoothDevice.BOND_NONE:
+ setHidDevicePriority(device, BluetoothHid.PRIORITY_OFF);
+ break;
+ }
+ } else if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {
+ synchronized (this) {
+ if (mHidDevices.containsKey(device)) {
+ int state = mHidDevices.get(device);
+ handleHIDStateChange(device, state, BluetoothHid.STATE_CONNECTED);
+ }
+ }
+ } else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
+ synchronized (this) {
+ if (mHidDevices.containsKey(device)) {
+ int state = mHidDevices.get(device);
+ handleHIDStateChange(device, state, BluetoothHid.STATE_DISCONNECTED);
+ }
+ }
+ }
+ }
+ };
+
+
+ public BluetoothHidService(Context context, BluetoothService bluetoothService) {
+ mContext = context;
+
+ mBluetoothService = bluetoothService;
+ if (mBluetoothService == null) {
+ throw new RuntimeException("Platform does not support Bluetooth");
+ }
+
+ if (!initNative()) {
+ throw new RuntimeException("Could not init BluetoothHidService");
+ }
+
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
+ mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
+ mIntentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
+ mIntentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
+ mIntentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
+ mContext.registerReceiver(mReceiver, mIntentFilter);
+
+ mHidDevices = new HashMap<BluetoothDevice, Integer>();
+
+ if (mBluetoothService.isEnabled())
+ onBluetoothEnable();
+ }
+
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ cleanupNative();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ private boolean isHidDevice(BluetoothDevice device) {
+ ParcelUuid[] uuids = mBluetoothService.getRemoteUuids(device.getAddress());
+ if (uuids != null && BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.HID)) {
+ return true;
+ }
+ return false;
+ }
+
+ private synchronized boolean addHidDevice (BluetoothDevice device) {
+ String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
+ String propValues[] = (String []) getHidPropertiesNative(path);
+ if (DBG) log("addHidDevice device = " + device);
+
+ if (propValues == null) {
+ Log.e(TAG, "Error while getting HID properties for device: " + device);
+ return false;
+ }
+ Integer state = null;
+ String name = propValues[0];
+ if (name.equals("Connected")) {
+ state = BluetoothHid.STATE_DISCONNECTED;
+ if (propValues[1].equals("true"))
+ state = BluetoothHid.STATE_CONNECTED;
+ }
+ mHidDevices.put(device, state);
+ handleHIDStateChange(device, BluetoothHid.STATE_DISCONNECTED, state);
+ return true;
+ }
+
+
+ private synchronized void onBluetoothEnable() {
+ String devices = mBluetoothService.getProperty("Devices");
+
+ if (devices != null) {
+ String [] paths = devices.split(",");
+ for (String path: paths) {
+ String address = mBluetoothService.getAddressFromObjectPath(path);
+ BluetoothDevice device = mAdapter.getRemoteDevice(address);
+ ParcelUuid[] remoteUuids = mBluetoothService.getRemoteUuids(address);
+ if (remoteUuids != null)
+ if (BluetoothUuid.containsAnyUuid(remoteUuids,
+ new ParcelUuid[] {BluetoothUuid.HID})) {
+ addHidDevice(device);
+ }
+ }
+ }
+ }
+
+ private synchronized void onBluetoothDisable() {
+ if (!mHidDevices.isEmpty()) {
+ BluetoothDevice[] devices = new BluetoothDevice[mHidDevices.size()];
+ devices = mHidDevices.keySet().toArray(devices);
+
+ for (BluetoothDevice device : devices) {
+ int state = mHidDevices.get(device);
+ switch (state) {
+ case BluetoothHid.STATE_CONNECTING:
+ case BluetoothHid.STATE_CONNECTED:
+ disconnectHidDeviceNative(mBluetoothService.getObjectPathFromAddress(
+ device.getAddress()));
+ handleHIDStateChange(device, state, BluetoothHid.STATE_DISCONNECTED);
+ break;
+ case BluetoothHid.STATE_DISCONNECTING:
+ handleHIDStateChange(device, BluetoothHid.STATE_DISCONNECTING,
+ BluetoothHid.STATE_DISCONNECTED);
+ break;
+ }
+ }
+ mHidDevices.clear();
+ }
+
+ }
+
+ public synchronized boolean connectHidDevice(BluetoothDevice device) {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH_ADMIN permission");
+ if (DBG) log("connectHidDevice(" + device + ")");
+
+ // ignore if there are any active sinks
+ if (lookupSinksMatchingStates(new int[] {
+ BluetoothHid.STATE_CONNECTING,
+ BluetoothHid.STATE_CONNECTED,
+ BluetoothHid.STATE_DISCONNECTING}).size() != 0) {
+ return false;
+ }
+ if (mHidDevices.get(device) == null && !addHidDevice(device))
+ return false;
+
+ int state = mHidDevices.get(device);
+
+ switch (state) {
+ case BluetoothHid.STATE_CONNECTED:
+ case BluetoothHid.STATE_DISCONNECTING:
+ return false;
+ case BluetoothHid.STATE_CONNECTING:
+ return true;
+ }
+
+ String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
+ if (path == null)
+ return false;
+
+ // State is DISCONNECTED
+ if (!connectHidDeviceNative(path)) {
+ return false;
+ }
+ return true;
+ }
+
+ public synchronized boolean disconnectHidDevice(BluetoothDevice device) {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH_ADMIN permission");
+ if (DBG) log("disconnectHidDevice(" + device + ")");
+
+ if (mHidDevices.get(device) == null)
+ return false;
+
+ int state = mHidDevices.get(device);
+ switch (state) {
+ case BluetoothHid.STATE_DISCONNECTED:
+ return false;
+ case BluetoothHid.STATE_DISCONNECTING:
+ return true;
+ }
+
+ String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
+ if (path == null) {
+ return false;
+ }
+
+ if (!disconnectHidDeviceNative(path)) {
+ return false;
+ }
+ return true;
+ }
+
+ public synchronized BluetoothDevice[] getConnectedSinks() {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ Set<BluetoothDevice> sinks = lookupSinksMatchingStates(
+ new int[] {BluetoothHid.STATE_CONNECTED});
+ return sinks.toArray(new BluetoothDevice[sinks.size()]);
+ }
+
+ public synchronized BluetoothDevice[] getNonDisconnectedSinks() {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ Set<BluetoothDevice> sinks = lookupSinksMatchingStates(
+ new int[] {BluetoothHid.STATE_CONNECTED,
+ BluetoothHid.STATE_CONNECTING,
+ BluetoothHid.STATE_DISCONNECTING});
+ return sinks.toArray(new BluetoothDevice[sinks.size()]);
+ }
+
+ public synchronized int getHidDeviceState(BluetoothDevice device) {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ Integer state = mHidDevices.get(device);
+ if (state == null){
+ return BluetoothHid.STATE_DISCONNECTED;
+ }
+ return state;
+ }
+
+ public synchronized int getHidDevicePriority(BluetoothDevice device) {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.getBluetoothHidDevicePriorityKey(device.getAddress()),
+ BluetoothHid.PRIORITY_UNDEFINED);
+ }
+
+
+ public synchronized boolean setHidDevicePriority(BluetoothDevice device, int priority) {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH_ADMIN permission");
+ if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
+ return false;
+ }
+ return Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.getBluetoothHidDevicePriorityKey(device.getAddress()), priority);
+
+ }
+
+
+ public synchronized void onPropertyChanged(String path, String []propValues) {
+ if (!mBluetoothService.isEnabled()) {
+ return;
+ }
+
+ String name = propValues[0];
+ String address = mBluetoothService.getAddressFromObjectPath(path);
+
+ if (address == null) {
+ Log.e(TAG, "onPropertyChanged: Address of the remote device in null");
+ return;
+ }
+
+ BluetoothDevice device = mAdapter.getRemoteDevice(address);
+ if (DBG) log("HID Device property changed: " + address + " property: " + name);
+
+ if (name.equals("Connected")) {
+ int state = BluetoothHid.STATE_DISCONNECTED;
+ if (propValues[1].equals("true")) {
+ state = BluetoothHid.STATE_CONNECTED;
+ }
+ if (mHidDevices.get(device) == null) {
+ // This is for an incoming connection for a device not known to us.
+ // We have authorized it and bluez state has changed.
+ addHidDevice(device);
+ } else {
+ int prevState = mHidDevices.get(device);
+ handleHIDStateChange(device, prevState, state);
+ }
+ }
+
+ }
+
+ private void handleHIDStateChange(BluetoothDevice device, int prevState, int state) {
+
+ if(DBG) log("HID device: " + device + " State:" + prevState + "->" + state);
+
+ if (state != prevState) {
+ mHidDevices.put(device, state);
+
+ if (getHidDevicePriority(device) > BluetoothHid.PRIORITY_OFF &&
+ state == BluetoothHid.STATE_CONNECTING ||
+ state == BluetoothHid.STATE_CONNECTED) {
+ setHidDevicePriority(device, BluetoothHid.PRIORITY_AUTO_CONNECT);
+ }
+ Intent intent = new Intent(BluetoothHid.HID_DEVICE_STATE_CHANGED_ACTION);
+ intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
+ intent.putExtra(BluetoothHid.HID_DEVICE_PREVIOUS_STATE, prevState);
+ intent.putExtra(BluetoothHid.HID_DEVICE_STATE, state);
+ mContext.sendBroadcast(intent, BLUETOOTH_PERM);
+ }
+ }
+
+ private synchronized Set<BluetoothDevice> lookupSinksMatchingStates(int[] states) {
+ Set<BluetoothDevice> sinks = new HashSet<BluetoothDevice>();
+ if (mHidDevices.isEmpty()) {
+ return sinks;
+ }
+ for (BluetoothDevice device: mHidDevices.keySet()) {
+ int sinkState = getHidDeviceState(device);
+ for (int state : states) {
+ if (state == sinkState) {
+ sinks.add(device);
+ break;
+ }
+ }
+ }
+ return sinks;
+ }
+
+ public synchronized void onHidDeviceConnected(String path) {
+ if (mHidDevices == null) return;
+
+ if (!mBluetoothService.isEnabled()) {
+ return;
+ }
+
+ String address = mBluetoothService.getAddressFromObjectPath(path);
+ if (address == null) {
+ Log.e(TAG, "onHidDeviceConnected: Address of the remote device in null");
+ return;
+ }
+
+ BluetoothDevice device = mAdapter.getRemoteDevice(address);
+ if(DBG) log(" onHidDeviceConnected device = " + device);
+ if (mHidDevices.containsKey(device)) {
+ int prevState = mHidDevices.get(device);
+ handleHIDStateChange(device, prevState, BluetoothHid.STATE_CONNECTED);
+ }
+
+ }
+
+ public synchronized void onHidDeviceDisconnected(String path) {
+ if (mHidDevices == null) return;
+
+ if (!mBluetoothService.isEnabled()) {
+ return;
+ }
+
+ String address = mBluetoothService.getAddressFromObjectPath(path);
+ if (address == null) {
+ Log.e(TAG, "onHidDeviceDisconnected: Address of the remote device in null");
+ return;
+ }
+
+ BluetoothDevice device = mAdapter.getRemoteDevice(address);
+ if(DBG) log(" onHidDeviceDisconnected device = " + device);
+ if (mHidDevices.containsKey(device)) {
+ int prevState = mHidDevices.get(device);
+ handleHIDStateChange(device, prevState, BluetoothHid.STATE_DISCONNECTED);
+ }
+ }
+
+ @Override
+ protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mHidDevices.isEmpty()) return;
+ pw.println("Cached hid devices:");
+ for (BluetoothDevice device : mHidDevices.keySet()) {
+ int state = mHidDevices.get(device);
+ pw.println(device + " " + BluetoothHid.stateToString(state));
+ }
+ }
+
+ private static void log(String msg) {
+ Log.d(TAG, msg);
+ }
+
+ private native boolean initNative();
+ private native void cleanupNative();
+
+ private synchronized native boolean connectHidDeviceNative(String path);
+ private synchronized native boolean disconnectHidDeviceNative(String path);
+ private synchronized native Object []getHidPropertiesNative(String path);
+
+}
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index c0affd3..7095dbe 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -1167,7 +1168,13 @@ public class BluetoothService extends IBluetooth.Stub {
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
return false;
}
- return removeDeviceNative(getObjectPathFromAddress(address));
+
+ if (removeDeviceNative(getObjectPathFromAddress(address))) {
+ removeRemoteDeviceProperties(address);
+ return true;
+ }
+
+ return false;
}
public synchronized String[] listBonds() {
@@ -1275,6 +1282,7 @@ public class BluetoothService extends IBluetooth.Stub {
if (propVal != null) {
propVal.put(name, value);
mDeviceProperties.put(address, propVal);
+ Log.d(TAG, "setRemoteDeviceProperty addr = " + address + " name = " + name + " value = " + value);
} else {
Log.e(TAG, "setRemoteDeviceProperty for a device not in cache:" + address);
}
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 38ac9b7..4063aef 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -305,13 +305,13 @@ public abstract class Layout {
if (spans[n] instanceof LeadingMarginSpan) {
LeadingMarginSpan margin = (LeadingMarginSpan) spans[n];
- if (dir == DIR_RIGHT_TO_LEFT) {
- margin.drawLeadingMargin(c, paint, right, dir, ltop,
- lbaseline, lbottom, buf,
- start, end, isFirstParaLine, this);
-
- right -= margin.getLeadingMargin(isFirstParaLine);
- } else {
+ // if (dir == DIR_RIGHT_TO_LEFT) {
+ // margin.drawLeadingMargin(c, paint, right, dir, ltop,
+ // lbaseline, lbottom, buf,
+ // start, end, isFirstParaLine, this);
+ //
+ // right -= margin.getLeadingMargin(isFirstParaLine);
+ //} else {
margin.drawLeadingMargin(c, paint, left, dir, ltop,
lbaseline, lbottom, buf,
start, end, isFirstParaLine, this);
@@ -320,7 +320,7 @@ public abstract class Layout {
if (margin instanceof LeadingMarginSpan.LeadingMarginSpan2) {
int count = ((LeadingMarginSpan.LeadingMarginSpan2)margin).getLeadingMarginLineCount();
useMargin = count > i;
- }
+ // }
left += margin.getLeadingMargin(useMargin);
}
}
@@ -364,8 +364,7 @@ public abstract class Layout {
Assert.assertTrue(dir == DIR_LEFT_TO_RIGHT);
Assert.assertNotNull(c);
}
- // XXX: assumes there's nothing additional to be done
- c.drawText(buf, start, end, x, lbaseline, paint);
+ c.drawText(buf, start, end, x, lbaseline, paint,false);
} else {
drawText(c, buf, start, end, dir, directions,
x, ltop, lbaseline, lbottom, paint, mWorkPaint,
@@ -1810,7 +1809,7 @@ public abstract class Layout {
public static class Directions {
private short[] mDirections;
- // The values in mDirections are the offsets from the first character
+ // The values in mDirections are the offsets from the last flip in direction
// in the line to the next flip in direction. Runs at even indices
// are left-to-right, the others are right-to-left. So, for example,
// a line that starts with a right-to-left run has 0 at mDirections[0],
@@ -1823,6 +1822,36 @@ public abstract class Layout {
/* package */ Directions(short[] dirs) {
mDirections = dirs;
}
+
+ static int baseDirection(Directions dir,int length) {
+ if (dir == DIRS_ALL_LEFT_TO_RIGHT) {
+ return DIR_LEFT_TO_RIGHT;
+ } else if (dir == DIRS_ALL_RIGHT_TO_LEFT) {
+ return DIR_RIGHT_TO_LEFT;
+ }
+
+ int sum=0;
+ int lastSwitch=0;
+ int i=0;
+ while ((i+1) < dir.mDirections.length) {
+ sum+=dir.mDirections[i];//-lastSwitch;
+ sum-=dir.mDirections[i+1];//-dir.mDirections[i];
+ lastSwitch=dir.mDirections[i+1];
+ i+=2;
+ }
+
+ if ((i+1)==dir.mDirections.length) {
+ sum+=dir.mDirections[i];//-lastSwitch);
+ } else if (i==dir.mDirections.length) {
+ sum-=length-lastSwitch;
+ }
+
+ if (sum>=0) {
+ return DIR_LEFT_TO_RIGHT;
+ } else {
+ return DIR_RIGHT_TO_LEFT;
+ }
+ }
}
/**
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index caaafa1..b6a9b17 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -1042,14 +1042,14 @@ implements CharSequence, GetChars, Spannable, Editable, Appendable,
checkRange("drawText", start, end);
if (end <= mGapStart) {
- c.drawText(mText, start, end - start, x, y, p);
+ c.drawText(mText, start, end - start, x, y, p,true);
} else if (start >= mGapStart) {
- c.drawText(mText, start + mGapLength, end - start, x, y, p);
+ c.drawText(mText, start + mGapLength, end - start, x, y, p,true);
} else {
char[] buf = TextUtils.obtain(end - start);
getChars(start, end, buf, 0);
- c.drawText(buf, 0, end - start, x, y, p);
+ c.drawText(buf, 0, end - start, x, y, p,true);
TextUtils.recycle(buf);
}
}
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index f02ad2a..047e6156 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -689,6 +689,7 @@ extends Layout
if (cur ==
Character.DIRECTIONALITY_RIGHT_TO_LEFT_ARABIC)
chInfo[j] = Character.DIRECTIONALITY_ARABIC_NUMBER;
+ else chInfo[j] = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
}
}
@@ -777,7 +778,7 @@ extends Layout
cur = d;
if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER)
- chInfo[j] = cur;
+ chInfo[j] = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
}
// dump(chdirs, n, "W7");
@@ -790,9 +791,10 @@ extends Layout
if (d == Character.DIRECTIONALITY_LEFT_TO_RIGHT ||
d == Character.DIRECTIONALITY_RIGHT_TO_LEFT) {
cur = d;
- } else if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER ||
- d == Character.DIRECTIONALITY_ARABIC_NUMBER) {
+ } else if (d == Character.DIRECTIONALITY_EUROPEAN_NUMBER) {
cur = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
+ } else if (d == Character.DIRECTIONALITY_ARABIC_NUMBER) {
+ cur = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
} else {
byte dd = SOR;
int k;
@@ -804,8 +806,10 @@ extends Layout
dd == Character.DIRECTIONALITY_RIGHT_TO_LEFT) {
break;
}
- if (dd == Character.DIRECTIONALITY_EUROPEAN_NUMBER ||
- dd == Character.DIRECTIONALITY_ARABIC_NUMBER) {
+ if (dd == Character.DIRECTIONALITY_EUROPEAN_NUMBER) {
+ dd = Character.DIRECTIONALITY_LEFT_TO_RIGHT;
+ break;
+ } else if (dd == Character.DIRECTIONALITY_ARABIC_NUMBER) {
dd = Character.DIRECTIONALITY_RIGHT_TO_LEFT;
break;
}
@@ -1244,7 +1248,7 @@ extends Layout
}
public int getParagraphDirection(int line) {
- return mLines[mColumns * line + DIR] >> DIR_SHIFT;
+ return Directions.baseDirection(mLineDirections[line],getLineEnd(line)-getLineStart(line));
}
public boolean getLineContainsTab(int line) {
diff --git a/core/java/android/text/Styled.java b/core/java/android/text/Styled.java
index 513b2cd..d2be383 100644
--- a/core/java/android/text/Styled.java
+++ b/core/java/android/text/Styled.java
@@ -129,7 +129,7 @@ public class Styled
}
canvas.drawText(tmp, tmpstart, tmpend,
- x - ret, y + workPaint.baselineShift, workPaint);
+ x - ret, y + workPaint.baselineShift, workPaint,false);
} else {
if (needWidth) {
if (!haveWidth) {
@@ -139,7 +139,7 @@ public class Styled
}
canvas.drawText(tmp, tmpstart, tmpend,
- x, y + workPaint.baselineShift, workPaint);
+ x, y + workPaint.baselineShift, workPaint,false);
}
} else {
if (needWidth && !haveWidth) {
@@ -261,13 +261,13 @@ public class Styled
if (canvas != null)
canvas.drawText(tmp, 0, tmpend,
- x - ret, y, paint);
+ x - ret, y, paint,false);
} else {
if (needWidth)
ret = paint.measureText(text, start, end);
if (canvas != null)
- canvas.drawText(text, start, end, x, y, paint);
+ canvas.drawText(text, start, end, x, y, paint,false);
}
if (fmi != null) {
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index 8eae111..c05a8fe 100644
--- a/core/java/android/text/format/Time.java
+++ b/core/java/android/text/format/Time.java
@@ -32,7 +32,7 @@ public class Time {
private static final String Y_M_D_T_H_M_S_000 = "%Y-%m-%dT%H:%M:%S.000";
private static final String Y_M_D_T_H_M_S_000_Z = "%Y-%m-%dT%H:%M:%S.000Z";
private static final String Y_M_D = "%Y-%m-%d";
-
+
public static final String TIMEZONE_UTC = "UTC";
/**
@@ -170,11 +170,11 @@ public class Time {
public Time() {
this(TimeZone.getDefault().getID());
}
-
+
/**
* A copy constructor. Construct a Time object by copying the given
* Time object. No normalization occurs.
- *
+ *
* @param other
*/
public Time(Time other) {
@@ -185,17 +185,17 @@ public class Time {
* Ensures the values in each field are in range. For example if the
* current value of this calendar is March 32, normalize() will convert it
* to April 1. It also fills in weekDay, yearDay, isDst and gmtoff.
- *
+ *
* <p>
* If "ignoreDst" is true, then this method sets the "isDst" field to -1
* (the "unknown" value) before normalizing. It then computes the
* correct value for "isDst".
- *
+ *
* <p>
* See {@link #toMillis(boolean)} for more information about when to
* use <tt>true</tt> or <tt>false</tt> for "ignoreDst".
- *
- * @return the UTC milliseconds since the epoch
+ *
+ * @return the UTC milliseconds since the epoch
*/
native public long normalize(boolean ignoreDst);
@@ -379,13 +379,13 @@ public class Time {
* Parses a date-time string in either the RFC 2445 format or an abbreviated
* format that does not include the "time" field. For example, all of the
* following strings are valid:
- *
+ *
* <ul>
* <li>"20081013T160000Z"</li>
* <li>"20081013T160000"</li>
* <li>"20081013"</li>
* </ul>
- *
+ *
* Returns whether or not the time is in UTC (ends with Z). If the string
* ends with "Z" then the timezone is set to UTC. If the date-time string
* included only a date and no time field, then the <code>allDay</code>
@@ -396,10 +396,10 @@ public class Time {
* <code>yearDay</code>, and <code>gmtoff</code> are always set to zero,
* and the field <code>isDst</code> is set to -1 (unknown). To set those
* fields, call {@link #normalize(boolean)} after parsing.
- *
+ *
* To parse a date-time string and convert it to UTC milliseconds, do
* something like this:
- *
+ *
* <pre>
* Time time = new Time();
* String date = "20081013T160000Z";
@@ -428,25 +428,25 @@ public class Time {
* Parse a time in RFC 3339 format. This method also parses simple dates
* (that is, strings that contain no time or time offset). For example,
* all of the following strings are valid:
- *
+ *
* <ul>
* <li>"2008-10-13T16:00:00.000Z"</li>
* <li>"2008-10-13T16:00:00.000+07:00"</li>
* <li>"2008-10-13T16:00:00.000-07:00"</li>
* <li>"2008-10-13"</li>
* </ul>
- *
+ *
* <p>
* If the string contains a time and time offset, then the time offset will
* be used to convert the time value to UTC.
* </p>
- *
+ *
* <p>
* If the given string contains just a date (with no time field), then
* the {@link #allDay} field is set to true and the {@link #hour},
* {@link #minute}, and {@link #second} fields are set to zero.
* </p>
- *
+ *
* <p>
* Returns true if the resulting time value is in UTC time.
* </p>
@@ -462,7 +462,7 @@ public class Time {
}
return false;
}
-
+
native private boolean nativeParse3339(String s);
/**
@@ -484,13 +484,13 @@ public class Time {
* <em>not</em> change any of the fields in this Time object. If you want
* to normalize the fields in this Time object and also get the milliseconds
* then use {@link #normalize(boolean)}.
- *
+ *
* <p>
* If "ignoreDst" is false, then this method uses the current setting of the
* "isDst" field and will adjust the returned time if the "isDst" field is
* wrong for the given time. See the sample code below for an example of
* this.
- *
+ *
* <p>
* If "ignoreDst" is true, then this method ignores the current setting of
* the "isDst" field in this Time object and will instead figure out the
@@ -499,27 +499,27 @@ public class Time {
* correct value of the "isDst" field is when the time is inherently
* ambiguous because it falls in the hour that is repeated when switching
* from Daylight-Saving Time to Standard Time.
- *
+ *
* <p>
* Here is an example where <tt>toMillis(true)</tt> adjusts the time,
* assuming that DST changes at 2am on Sunday, Nov 4, 2007.
- *
+ *
* <pre>
* Time time = new Time();
- * time.set(2007, 10, 4); // set the date to Nov 4, 2007, 12am
+ * time.set(4, 10, 2007); // set the date to Nov 4, 2007, 12am
* time.normalize(); // this sets isDst = 1
* time.monthDay += 1; // changes the date to Nov 5, 2007, 12am
* millis = time.toMillis(false); // millis is Nov 4, 2007, 11pm
* millis = time.toMillis(true); // millis is Nov 5, 2007, 12am
* </pre>
- *
+ *
* <p>
* To avoid this problem, use <tt>toMillis(true)</tt>
* after adding or subtracting days or explicitly setting the "monthDay"
* field. On the other hand, if you are adding
* or subtracting hours or minutes, then you should use
* <tt>toMillis(false)</tt>.
- *
+ *
* <p>
* You should also use <tt>toMillis(false)</tt> if you want
* to read back the same milliseconds that you set with {@link #set(long)}
@@ -531,14 +531,14 @@ public class Time {
* Sets the fields in this Time object given the UTC milliseconds. After
* this method returns, all the fields are normalized.
* This also sets the "isDst" field to the correct value.
- *
+ *
* @param millis the time in UTC milliseconds since the epoch.
*/
native public void set(long millis);
/**
* Format according to RFC 2445 DATETIME type.
- *
+ *
* <p>
* The same as format("%Y%m%dT%H%M%S").
*/
@@ -584,7 +584,7 @@ public class Time {
* Sets the date from the given fields. Also sets allDay to true.
* Sets weekDay, yearDay and gmtoff to 0, and isDst to -1.
* Call {@link #normalize(boolean)} if you need those.
- *
+ *
* @param monthDay the day of the month (in the range [1,31])
* @param month the zero-based month number (in the range [0,11])
* @param year the year
@@ -606,7 +606,7 @@ public class Time {
/**
* Returns true if the time represented by this Time object occurs before
* the given time.
- *
+ *
* @param that a given Time object to compare against
* @return true if this time is less than the given time
*/
@@ -618,7 +618,7 @@ public class Time {
/**
* Returns true if the time represented by this Time object occurs after
* the given time.
- *
+ *
* @param that a given Time object to compare against
* @return true if this time is greater than the given time
*/
@@ -632,12 +632,12 @@ public class Time {
* closest Thursday yearDay.
*/
private static final int[] sThursdayOffset = { -3, 3, 2, 1, 0, -1, -2 };
-
+
/**
* Computes the week number according to ISO 8601. The current Time
* object must already be normalized because this method uses the
* yearDay and weekDay fields.
- *
+ *
* <p>
* In IS0 8601, weeks start on Monday.
* The first week of the year (week 1) is defined by ISO 8601 as the
@@ -645,12 +645,12 @@ public class Time {
* Or equivalently, the week containing January 4. Or equivalently,
* the week with the year's first Thursday in it.
* </p>
- *
+ *
* <p>
* The week number can be calculated by counting Thursdays. Week N
* contains the Nth Thursday of the year.
* </p>
- *
+ *
* @return the ISO week number.
*/
public int getWeekNumber() {
@@ -661,7 +661,7 @@ public class Time {
if (closestThursday >= 0 && closestThursday <= 364) {
return closestThursday / 7 + 1;
}
-
+
// The week crosses a year boundary.
Time temp = new Time(this);
temp.monthDay += sThursdayOffset[weekDay];
@@ -670,7 +670,7 @@ public class Time {
}
/**
- * Return a string in the RFC 3339 format.
+ * Return a string in the RFC 3339 format.
* <p>
* If allDay is true, expresses the time as Y-M-D</p>
* <p>
@@ -691,13 +691,13 @@ public class Time {
int offset = (int)Math.abs(gmtoff);
int minutes = (offset % 3600) / 60;
int hours = offset / 3600;
-
+
return String.format("%s%s%02d:%02d", base, sign, hours, minutes);
}
}
-
+
/**
- * Returns true if the day of the given time is the epoch on the Julian Calendar
+ * Returns true if the day of the given time is the epoch on the Julian Calendar
* (January 1, 1970 on the Gregorian calendar).
*
* @param time the time to test
@@ -707,7 +707,7 @@ public class Time {
long millis = time.toMillis(true);
return getJulianDay(millis, 0) == EPOCH_JULIAN_DAY;
}
-
+
/**
* Computes the Julian day number, given the UTC milliseconds
* and the offset (in seconds) from UTC. The Julian day for a given
@@ -716,10 +716,10 @@ public class Time {
* what timezone is being used. The Julian day is useful for testing
* if two events occur on the same day and for determining the relative
* time of an event from the present ("yesterday", "3 days ago", etc.).
- *
+ *
* <p>
* Use {@link #toMillis(boolean)} to get the milliseconds.
- *
+ *
* @param millis the time in UTC milliseconds
* @param gmtoff the offset from UTC in seconds
* @return the Julian day
@@ -729,7 +729,7 @@ public class Time {
long julianDay = (millis + offsetMillis) / DateUtils.DAY_IN_MILLIS;
return (int) julianDay + EPOCH_JULIAN_DAY;
}
-
+
/**
* <p>Sets the time from the given Julian day number, which must be based on
* the same timezone that is set in this Time object. The "gmtoff" field
@@ -738,7 +738,7 @@ public class Time {
* After this method returns all the fields will be normalized and the time
* will be set to 12am at the beginning of the given Julian day.
* </p>
- *
+ *
* <p>
* The only exception to this is if 12am does not exist for that day because
* of daylight saving time. For example, Cairo, Eqypt moves time ahead one
@@ -746,7 +746,7 @@ public class Time {
* also change daylight saving time at 12am. In those cases, the time
* will be set to 1am.
* </p>
- *
+ *
* @param julianDay the Julian day in the timezone for this Time object
* @return the UTC milliseconds for the beginning of the Julian day
*/
@@ -756,13 +756,13 @@ public class Time {
// the day.
long millis = (julianDay - EPOCH_JULIAN_DAY) * DateUtils.DAY_IN_MILLIS;
set(millis);
-
+
// Figure out how close we are to the requested Julian day.
// We can't be off by more than a day.
int approximateDay = getJulianDay(millis, gmtoff);
int diff = julianDay - approximateDay;
monthDay += diff;
-
+
// Set the time to 12am and re-normalize.
hour = 0;
minute = 0;
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index 8f40260..e21689d 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -36,6 +36,12 @@ public class HapticFeedbackConstants {
public static final int VIRTUAL_KEY = 1;
/**
+ * User has released a virtual on-screen key.
+ * @hide
+ */
+ public static final int VIRTUAL_RELEASED = 2;
+
+ /**
* The user has pressed a soft keyboard key.
*/
public static final int KEYBOARD_TAP = 3;
diff --git a/core/java/android/view/RawInputEvent.java b/core/java/android/view/RawInputEvent.java
index 3bbfea8..a4475a1 100644
--- a/core/java/android/view/RawInputEvent.java
+++ b/core/java/android/view/RawInputEvent.java
@@ -28,6 +28,7 @@ public class RawInputEvent {
public static final int CLASS_TRACKBALL = 0x00000008;
public static final int CLASS_TOUCHSCREEN_MT = 0x00000010;
public static final int CLASS_DPAD = 0x00000020;
+ public static final int CLASS_MOUSE= 0x00000040;
// More special classes for QueuedEvent below.
public static final int CLASS_CONFIGURATION_CHANGED = 0x10000000;
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 03efea9..2591a04 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -2586,6 +2586,9 @@ public final class ViewRoot extends Handler implements ViewParent,
switch (effectId) {
case SoundEffectConstants.CLICK:
audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK);
+ if (audioManager.queryHapticsAllEnabled()){
+ performHapticFeedback(HapticFeedbackConstants.VIRTUAL_RELEASED, false);
+ };
return;
case SoundEffectConstants.NAVIGATION_DOWN:
audioManager.playSoundEffect(AudioManager.FX_FOCUS_NAVIGATION_DOWN);
diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java
index 25df1f4..0d6f973 100755
--- a/core/java/android/view/WindowOrientationListener.java
+++ b/core/java/android/view/WindowOrientationListener.java
@@ -16,11 +16,15 @@
package android.view;
+import android.content.ContentResolver;
import android.content.Context;
+import android.database.ContentObserver;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
+import android.os.Handler;
+import android.provider.Settings;
import android.util.Config;
import android.util.Log;
@@ -39,6 +43,10 @@ public abstract class WindowOrientationListener {
private int mRate;
private Sensor mSensor;
private SensorEventListenerImpl mSensorEventListener;
+ private Context mContext;
+ private Handler mHandler;
+ private SettingsObserver mSettingsObserver;
+ private int mAccelerometerMode;
/**
* Creates a new WindowOrientationListener.
@@ -70,6 +78,8 @@ public abstract class WindowOrientationListener {
// Create listener only if sensors do exist
mSensorEventListener = new SensorEventListenerImpl();
}
+ mContext = context;
+ mHandler = new Handler();
}
/**
@@ -85,6 +95,10 @@ public abstract class WindowOrientationListener {
if (localLOGV) Log.d(TAG, "WindowOrientationListener enabled");
mSensorManager.registerListener(mSensorEventListener, mSensor, mRate);
mEnabled = true;
+ if (mSettingsObserver == null) {
+ mSettingsObserver = new SettingsObserver(mHandler);
+ }
+ mSettingsObserver.observe();
}
}
@@ -100,6 +114,10 @@ public abstract class WindowOrientationListener {
if (localLOGV) Log.d(TAG, "WindowOrientationListener disabled");
mSensorManager.unregisterListener(mSensorEventListener);
mEnabled = false;
+ if (mSettingsObserver != null) {
+ mSettingsObserver.stop();
+ mSettingsObserver = null;
+ }
}
}
@@ -110,6 +128,38 @@ public abstract class WindowOrientationListener {
return -1;
}
+ class SettingsObserver extends ContentObserver {
+ SettingsObserver(Handler handler) {
+ super(handler);
+ }
+
+ void observe() {
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ Settings.System.ACCELEROMETER_ROTATION_MODE), false, this);
+ if (localLOGV) Log.i(TAG, "SettingsObserver enabled");
+ update();
+ }
+
+ public void stop() {
+ ContentResolver resolver = mContext.getContentResolver();
+ resolver.unregisterContentObserver(this);
+ if (localLOGV) Log.i(TAG, "SettingsObserver disabled");
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ update();
+ }
+
+ public void update() {
+ ContentResolver resolver = mContext.getContentResolver();
+ mAccelerometerMode = Settings.System.getInt(resolver,
+ Settings.System.ACCELEROMETER_ROTATION_MODE, 5);
+ if (localLOGV) Log.i(TAG, "mAccelerometerMode=" + mAccelerometerMode);
+ }
+ }
+
class SensorEventListenerImpl implements SensorEventListener {
// We work with all angles in degrees in this class.
private static final float RADIANS_TO_DEGREES = (float) (180 / Math.PI);
@@ -123,14 +173,15 @@ public abstract class WindowOrientationListener {
// ROTATION_90 = right side of device facing the sky, etc.
private static final int ROTATION_0 = 0;
private static final int ROTATION_90 = 1;
- private static final int ROTATION_270 = 2;
+ private static final int ROTATION_180 = 2;
+ private static final int ROTATION_270 = 3;
// Current orientation state
private int mRotation = ROTATION_0;
// Mapping our internal aliases into actual Surface rotation values
private final int[] SURFACE_ROTATIONS = new int[] {Surface.ROTATION_0, Surface.ROTATION_90,
- Surface.ROTATION_270};
+ Surface.ROTATION_180, Surface.ROTATION_270};
// Threshold ranges of orientation angle to transition into other orientation states.
// The first list is for transitions from ROTATION_0, the next for ROTATION_90, etc.
@@ -140,16 +191,18 @@ public abstract class WindowOrientationListener {
// between two states with a swing of 30 degrees for hysteresis. For ROTATION_180,
// however, we enforce stricter thresholds, pushing the thresholds 15 degrees closer to 180.
private final int[][][] THRESHOLDS = new int[][][] {
- {{60, 180}, {180, 300}},
- {{0, 45}, {45, 165}, {330, 360}},
- {{0, 30}, {195, 315}, {315, 360}}
+ {{60, 165}, {165, 195}, {195, 300}},
+ {{0, 30}, {150, 210}, {30, 150}, {330, 360}},
+ {{240, 345}, {15, 120}, {0, 15}, {345, 360}},
+ {{0, 30}, {150, 195}, {195, 315}, {315, 360}}
};
// See THRESHOLDS
private final int[][] ROTATE_TO = new int[][] {
- {ROTATION_270, ROTATION_90},
- {ROTATION_0, ROTATION_270, ROTATION_0},
- {ROTATION_0, ROTATION_90, ROTATION_0}
+ {ROTATION_270, ROTATION_180, ROTATION_90},
+ {ROTATION_0, ROTATION_180, ROTATION_270, ROTATION_0},
+ {ROTATION_90, ROTATION_270, ROTATION_0, ROTATION_0},
+ {ROTATION_0, ROTATION_180, ROTATION_90, ROTATION_0}
};
// Maximum absolute tilt angle at which to consider orientation changes. Beyond this (i.e.
@@ -159,7 +212,7 @@ public abstract class WindowOrientationListener {
// Additional limits on tilt angle to transition to each new orientation. We ignore all
// vectors with tilt beyond MAX_TILT, but we can set stricter limits on transition to a
// particular orientation here.
- private final int[] MAX_TRANSITION_TILT = new int[] {MAX_TILT, MAX_TILT, MAX_TILT};
+ private final int[] MAX_TRANSITION_TILT = new int[] {MAX_TILT, MAX_TILT, MAX_TILT, MAX_TILT};
// Between this tilt angle and MAX_TILT, we'll allow orientation changes, but we'll filter
// with a higher time constant, making us less sensitive to change. This primarily helps
@@ -224,6 +277,25 @@ public abstract class WindowOrientationListener {
return;
}
+ boolean allowed = rotation == ROTATION_0;
+ if (!allowed) {
+ switch (rotation) {
+ case ROTATION_90:
+ allowed = (mAccelerometerMode & 1) != 0;
+ break;
+ case ROTATION_180:
+ allowed = (mAccelerometerMode & 2) != 0;
+ break;
+ case ROTATION_270:
+ allowed = (mAccelerometerMode & 4) != 0;
+ break;
+ }
+ }
+ if (!allowed) {
+ if (localLOGV) Log.i(TAG, " not allowed rotation = " + rotation);
+ return;
+ }
+
if (localLOGV) Log.i(TAG, " new rotation = " + rotation);
mRotation = rotation;
onOrientationChanged(SURFACE_ROTATIONS[rotation]);
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index b767f11..cfb6b92 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -424,6 +424,14 @@ public class WebSettings {
public boolean getNavDump() {
return mNavDump;
}
+
+ /**
+ * Whether or not to display zoom controls
+ * @hide
+ */
+ public void showZoomControls(boolean value) {
+ mWebView.showZoomControls(value);
+ }
/**
* Set whether the WebView supports zoom
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 2df250d..766a80c 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -46,6 +46,7 @@ import android.os.Handler;
import android.os.Message;
import android.os.ServiceManager;
import android.os.SystemClock;
+import android.provider.Settings;
import android.text.IClipboard;
import android.text.Selection;
import android.text.Spannable;
@@ -774,6 +775,9 @@ public class WebView extends AbsoluteLayout
public static final String SCHEME_GEO = "geo:0,0?q=";
private int mBackgroundColor = Color.WHITE;
+
+ //Wysie
+ private boolean showZoomControls = true;
// Used to notify listeners of a new picture.
private PictureListener mPictureListener;
@@ -945,6 +949,11 @@ public class WebView extends AbsoluteLayout
updateMultiTouchSupport(context);
}
+
+ //Wysie
+ void showZoomControls(boolean value) {
+ showZoomControls = value;
+ }
void updateMultiTouchSupport(Context context) {
WebSettings settings = getSettings();
@@ -961,17 +970,21 @@ public class WebView extends AbsoluteLayout
private void updateZoomButtonsEnabled() {
if (mZoomButtonsController == null) return;
- boolean canZoomIn = mActualScale < mMaxZoomScale;
- boolean canZoomOut = mActualScale > mMinZoomScale && !mInZoomOverview;
- if (!canZoomIn && !canZoomOut) {
- // Hide the zoom in and out buttons, as well as the fit to page
- // button, if the page cannot zoom
+ if (!showZoomControls) {
mZoomButtonsController.getZoomControls().setVisibility(View.GONE);
} else {
- // Set each one individually, as a page may be able to zoom in
- // or out.
- mZoomButtonsController.setZoomInEnabled(canZoomIn);
- mZoomButtonsController.setZoomOutEnabled(canZoomOut);
+ boolean canZoomIn = mActualScale < mMaxZoomScale;
+ boolean canZoomOut = mActualScale > mMinZoomScale && !mInZoomOverview;
+ if (!canZoomIn && !canZoomOut) {
+ // Hide the zoom in and out buttons, as well as the fit to page
+ // button, if the page cannot zoom
+ mZoomButtonsController.getZoomControls().setVisibility(View.GONE);
+ } else {
+ // Set each one individually, as a page may be able to zoom in
+ // or out.
+ mZoomButtonsController.setZoomInEnabled(canZoomIn);
+ mZoomButtonsController.setZoomOutEnabled(canZoomOut);
+ }
}
}
@@ -4601,6 +4614,10 @@ public class WebView extends AbsoluteLayout
boolean reflowNow = (mActualScale - mMinZoomScale
<= MINIMUM_SCALE_INCREMENT)
|| ((mActualScale <= 0.8 * mTextWrapScale));
+ if(mActualScale > mTextWrapScale) {
+ reflowNow |= Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.WEB_VIEW_PINCH_REFLOW, 0) != 0;
+ }
// force zoom after mPreviewZoomOnly is set to false so that the
// new view size will be passed to the WebKit
setNewZoomScale(mActualScale, reflowNow, true);
diff --git a/core/java/android/widget/TabHost.java b/core/java/android/widget/TabHost.java
index 02cd6a8..e0f1583 100644
--- a/core/java/android/widget/TabHost.java
+++ b/core/java/android/widget/TabHost.java
@@ -51,6 +51,14 @@ public class TabHost extends FrameLayout implements ViewTreeObserver.OnTouchMode
* {@hide}
*/
protected int mCurrentTab = -1;
+ /**
+ * This field when set to true ensures that first tab is not set as the current tab
+ * by preventing the addTab() from calling setCurrentTab() with index set to 0.
+ * To ensure that the operations of an application are not changed, it should be set to
+ * false whenever mCurrenttab is set to -1.
+ * {@hide}
+ */
+ private boolean mAvoidFirstTabLoad = false;
private View mCurrentView = null;
/**
* This field should be made private, so it is hidden from the SDK.
@@ -75,6 +83,7 @@ public class TabHost extends FrameLayout implements ViewTreeObserver.OnTouchMode
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
mCurrentTab = -1;
+ mAvoidFirstTabLoad = false;
mCurrentView = null;
}
@@ -209,7 +218,9 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
mTabWidget.addView(tabIndicator);
mTabSpecs.add(tabSpec);
- if (mCurrentTab == -1) {
+ // The second test is always true except when an application explicitly sets
+ // mAvoidFirstTabLoad to true.
+ if (mCurrentTab == -1 && !mAvoidFirstTabLoad) {
setCurrentTab(0);
}
}
@@ -252,7 +263,18 @@ mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
public View getCurrentView() {
return mCurrentView;
}
-
+ /**
+ * {@hide}
+ */
+ public void setAvoidFirstTabLoad(boolean flag) {
+ mAvoidFirstTabLoad = flag;
+ }
+ /**
+ * {@hide}
+ */
+ public void setCurrentTabToZero() {
+ mCurrentTab = 0;
+ }
public void setCurrentTabByTag(String tag) {
int i;
for (i = 0; i < mTabSpecs.size(); i++) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 64c9c99..2b37887 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -2778,7 +2778,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
public void drawText(Canvas c, int start, int end,
float x, float y, Paint p) {
- c.drawText(mChars, start + mStart, end - start, x, y, p);
+ c.drawText(mChars, start + mStart, end - start, x, y, p,false);
}
public float measureText(int start, int end, Paint p) {
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 107b145..4a0617c 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -435,6 +435,7 @@ public class AlertController {
View titleTemplate = mWindow.findViewById(R.id.title_template);
titleTemplate.setVisibility(View.GONE);
mIconView.setVisibility(View.GONE);
+ topPanel.setVisibility(View.GONE);
hasTitle = false;
}
}
diff --git a/core/java/com/android/internal/app/ShutdownThread.java b/core/java/com/android/internal/app/ShutdownThread.java
index a96253b..310ae99 100644
--- a/core/java/com/android/internal/app/ShutdownThread.java
+++ b/core/java/com/android/internal/app/ShutdownThread.java
@@ -94,17 +94,33 @@ public final class ShutdownThread extends Thread {
Log.d(TAG, "Notifying thread to start radio shutdown");
if (confirm) {
- final AlertDialog dialog = new AlertDialog.Builder(context)
- .setIcon(android.R.drawable.ic_dialog_alert)
- .setTitle(com.android.internal.R.string.power_off)
- .setMessage(com.android.internal.R.string.shutdown_confirm)
- .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- beginShutdownSequence(context);
- }
- })
- .setNegativeButton(com.android.internal.R.string.no, null)
- .create();
+ final AlertDialog dialog;
+ // Set different dialog message based on whether or not we're rebooting
+ if (mReboot) {
+ dialog = new AlertDialog.Builder(context)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setTitle(com.android.internal.R.string.reboot_system)
+ .setMessage(com.android.internal.R.string.reboot_confirm)
+ .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ beginShutdownSequence(context);
+ }
+ })
+ .setNegativeButton(com.android.internal.R.string.no, null)
+ .create();
+ } else {
+ dialog = new AlertDialog.Builder(context)
+ .setIcon(android.R.drawable.ic_dialog_alert)
+ .setTitle(com.android.internal.R.string.power_off)
+ .setMessage(com.android.internal.R.string.shutdown_confirm)
+ .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ beginShutdownSequence(context);
+ }
+ })
+ .setNegativeButton(com.android.internal.R.string.no, null)
+ .create();
+ }
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
if (!context.getResources().getBoolean(
com.android.internal.R.bool.config_sf_slowBlur)) {
@@ -139,8 +155,13 @@ public final class ShutdownThread extends Thread {
// throw up an indeterminate system dialog to indicate radio is
// shutting down.
ProgressDialog pd = new ProgressDialog(context);
- pd.setTitle(context.getText(com.android.internal.R.string.power_off));
- pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
+ if (mReboot) {
+ pd.setTitle(context.getText(com.android.internal.R.string.reboot_system));
+ pd.setMessage(context.getText(com.android.internal.R.string.reboot_progress));
+ } else {
+ pd.setTitle(context.getText(com.android.internal.R.string.power_off));
+ pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
+ }
pd.setIndeterminate(true);
pd.setCancelable(false);
pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index aadb576..55b25f6 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -844,7 +844,7 @@ public final class BatteryStatsImpl extends BatteryStats {
private final Map<String, KernelWakelockStats> readKernelWakelockStats() {
- byte[] buffer = new byte[4096];
+ byte[] buffer = new byte[8192];
int len;
try {
@@ -891,9 +891,11 @@ public final class BatteryStatsImpl extends BatteryStats {
for (endIndex=startIndex;
endIndex < len && wlBuffer[endIndex] != '\n' && wlBuffer[endIndex] != '\0';
endIndex++);
- // Don't go over the end of the buffer
- if (endIndex < len) {
- endIndex++; // endIndex is an exclusive upper bound.
+ endIndex++; // endIndex is an exclusive upper bound.
+ // Don't go over the end of the buffer, Process.parseProcLine might
+ // write to wlBuffer[endIndex]
+ if (endIndex >= (len - 1) ) {
+ return m;
}
String[] nameStringArray = mProcWakelocksName;
@@ -1224,6 +1226,8 @@ public final class BatteryStatsImpl extends BatteryStats {
if (mPhoneSignalStrengthBin != bin) {
if (mPhoneSignalStrengthBin >= 0) {
mPhoneSignalStrengthsTimer[mPhoneSignalStrengthBin].stopRunningLocked(this);
+ } else {
+ mPhoneSignalStrengthsTimer[SIGNAL_STRENGTH_NONE_OR_UNKNOWN].stopRunningLocked(this);
}
mPhoneSignalStrengthBin = bin;
mPhoneSignalStrengthsTimer[bin].startRunningLocked(this);
diff --git a/core/java/com/android/internal/os/SamplingProfilerIntegration.java b/core/java/com/android/internal/os/SamplingProfilerIntegration.java
index 5f5c7a4..127fb23 100644
--- a/core/java/com/android/internal/os/SamplingProfilerIntegration.java
+++ b/core/java/com/android/internal/os/SamplingProfilerIntegration.java
@@ -85,7 +85,8 @@ public class SamplingProfilerIntegration {
pending = true;
snapshotWriter.execute(new Runnable() {
public void run() {
- String dir = "/sdcard/snapshots";
+ String dir =
+ Environment.getExternalStorageDirectory().getPath() + "/snapshots";
if (!dirMade) {
new File(dir).mkdirs();
if (new File(dir).isDirectory()) {
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index dbbd286..b227d67 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -90,7 +90,7 @@ public class LockPatternUtils {
private final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
private final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type";
- private final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt";
+ private final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt";
private final Context mContext;
private final ContentResolver mContentResolver;
@@ -572,6 +572,62 @@ public class LockPatternUtils {
public void setTactileFeedbackEnabled(boolean enabled) {
setBoolean(Settings.Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, enabled);
}
+
+ public void setVisibleDotsEnabled(boolean enabled) {
+ setBoolean(Settings.Secure.LOCK_DOTS_VISIBLE, enabled);
+ }
+
+ public boolean isVisibleDotsEnabled() {
+ return getBoolean(Settings.Secure.LOCK_DOTS_VISIBLE, true);
+ }
+
+ public void setShowErrorPath(boolean enabled) {
+ setBoolean(Settings.Secure.LOCK_SHOW_ERROR_PATH, enabled);
+ }
+
+ public boolean isShowErrorPath() {
+ return getBoolean(Settings.Secure.LOCK_SHOW_ERROR_PATH, true);
+ }
+
+ public void setShowCustomMsg(boolean enabled) {
+ setBoolean(Settings.Secure.LOCK_SHOW_CUSTOM_MSG, enabled);
+ }
+
+ public boolean isShowCustomMsg() {
+ return getBoolean(Settings.Secure.LOCK_SHOW_CUSTOM_MSG, false);
+ }
+
+ public void setCustomMsg(String msg) {
+ setString(Settings.Secure.LOCK_CUSTOM_MSG, msg);
+ }
+
+ public String getCustomMsg() {
+ return getString(Settings.Secure.LOCK_CUSTOM_MSG);
+ }
+
+ public int getIncorrectDelay() {
+ return getInt(Settings.Secure.LOCK_INCORRECT_DELAY, 2000);
+ }
+
+ public void setIncorrectDelay(int delay) {
+ setInt(Settings.Secure.LOCK_INCORRECT_DELAY, delay);
+ }
+
+ public void setShowUnlockMsg(boolean enabled) {
+ setBoolean(Settings.Secure.SHOW_UNLOCK_TEXT, enabled);
+ }
+
+ public boolean isShowUnlockMsg() {
+ return getBoolean(Settings.Secure.SHOW_UNLOCK_TEXT, true);
+ }
+
+ public void setShowUnlockErrMsg(boolean enabled) {
+ setBoolean(Settings.Secure.SHOW_UNLOCK_ERR_TEXT, enabled);
+ }
+
+ public boolean isShowUnlockErrMsg() {
+ return getBoolean(Settings.Secure.SHOW_UNLOCK_ERR_TEXT, true);
+ }
/**
* Set and store the lockout deadline, meaning the user can't attempt his/her unlock
@@ -636,6 +692,13 @@ public class LockPatternUtils {
return 1 ==
android.provider.Settings.Secure.getInt(mContentResolver, secureSettingKey, 0);
}
+
+ private boolean getBoolean(String systemSettingKey, boolean defaultValue) {
+ return 1 ==
+ android.provider.Settings.Secure.getInt(
+ mContentResolver,
+ systemSettingKey, defaultValue ? 1 : 0);
+ }
private void setBoolean(String secureSettingKey, boolean enabled) {
android.provider.Settings.Secure.putInt(mContentResolver, secureSettingKey,
@@ -649,6 +712,27 @@ public class LockPatternUtils {
private void setLong(String secureSettingKey, long value) {
android.provider.Settings.Secure.putLong(mContentResolver, secureSettingKey, value);
}
+
+ private int getInt(String systemSettingKey, int def) {
+ return android.provider.Settings.Secure.getInt(mContentResolver, systemSettingKey, def);
+ }
+
+ private void setInt(String systemSettingKey, int value) {
+ android.provider.Settings.Secure.putInt(mContentResolver, systemSettingKey, value);
+ }
+
+ private String getString(String systemSettingKey) {
+ String s = android.provider.Settings.Secure.getString(mContentResolver, systemSettingKey);
+
+ if (s == null)
+ return "";
+
+ return s;
+ }
+
+ private void setString(String systemSettingKey, String value) {
+ android.provider.Settings.Secure.putString(mContentResolver, systemSettingKey, value);
+ }
public boolean isSecure() {
long mode = getKeyguardStoredPasswordQuality();
diff --git a/core/java/com/android/internal/widget/LockPatternView.java b/core/java/com/android/internal/widget/LockPatternView.java
index 007e7b9..8ae5a2f 100644
--- a/core/java/com/android/internal/widget/LockPatternView.java
+++ b/core/java/com/android/internal/widget/LockPatternView.java
@@ -101,6 +101,10 @@ public class LockPatternView extends View {
private boolean mInStealthMode = false;
private boolean mTactileFeedbackEnabled = true;
private boolean mPatternInProgress = false;
+
+ private boolean mVisibleDots = true;
+ private boolean mShowErrorPath = true;
+ private int mDelay = 2000;
private float mDiameterFactor = 0.5f;
private float mHitFactor = 0.6f;
@@ -332,6 +336,22 @@ public class LockPatternView extends View {
public void setInStealthMode(boolean inStealthMode) {
mInStealthMode = inStealthMode;
}
+
+ public void setVisibleDots(boolean visibleDots) {
+ mVisibleDots = visibleDots;
+ }
+
+ public boolean isVisibleDots() {
+ return mVisibleDots;
+ }
+
+ public void setShowErrorPath(boolean showErrorPath) {
+ mShowErrorPath = showErrorPath;
+ }
+
+ public boolean isShowErrorPath() {
+ return mShowErrorPath;
+ }
/**
* Set whether the view will use tactile feedback. If true, there will be
@@ -433,6 +453,14 @@ public class LockPatternView extends View {
public void enableInput() {
mInputEnabled = true;
}
+
+ public int getIncorrectDelay() {
+ return mDelay;
+ }
+
+ public void setIncorrectDelay(int delay) {
+ mDelay = delay;
+ }
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
@@ -838,7 +866,10 @@ public class LockPatternView extends View {
// only the last segment of the path should be computed here
// draw the path of the pattern (unless the user is in progress, and
// we are in stealth mode)
- final boolean drawPath = (!mInStealthMode || mPatternDisplayMode == DisplayMode.Wrong);
+ final boolean drawPath = ((!mInStealthMode && mPatternDisplayMode != DisplayMode.Wrong)
+ || (mPatternDisplayMode == DisplayMode.Wrong && mShowErrorPath));
+
+ //final boolean drawPath = (!mInStealthMode || mPatternDisplayMode == DisplayMode.Wrong);
if (drawPath) {
boolean anyCircles = false;
for (int i = 0; i < count; i++) {
@@ -872,13 +903,15 @@ public class LockPatternView extends View {
// draw the circles
final int paddingTop = mPaddingTop;
final int paddingLeft = mPaddingLeft;
-
- for (int i = 0; i < 3; i++) {
- float topY = paddingTop + i * squareHeight;
- //float centerY = mPaddingTop + i * mSquareHeight + (mSquareHeight / 2);
- for (int j = 0; j < 3; j++) {
- float leftX = paddingLeft + j * squareWidth;
- drawCircle(canvas, (int) leftX, (int) topY, drawLookup[i][j]);
+
+ if (mVisibleDots) {
+ for (int i = 0; i < 3; i++) {
+ float topY = paddingTop + i * squareHeight;
+ //float centerY = mPaddingTop + i * mSquareHeight + (mSquareHeight / 2);
+ for (int j = 0; j < 3; j++) {
+ float leftX = paddingLeft + j * squareWidth;
+ drawCircle(canvas, (int) leftX, (int) topY, drawLookup[i][j]);
+ }
}
}
@@ -959,8 +992,15 @@ public class LockPatternView extends View {
innerCircle = mBitmapBtnTouched;
} else if (mPatternDisplayMode == DisplayMode.Wrong) {
// the pattern is wrong
- outerCircle = mBitmapCircleRed;
- innerCircle = mBitmapBtnDefault;
+
+ if (mShowErrorPath) {
+ outerCircle = mBitmapCircleRed;
+ innerCircle = mBitmapBtnDefault;
+ }
+ else {
+ outerCircle = mBitmapCircleDefault;
+ innerCircle = mBitmapBtnDefault;
+ }
} else if (mPatternDisplayMode == DisplayMode.Correct ||
mPatternDisplayMode == DisplayMode.Animate) {
// the pattern is correct
@@ -989,7 +1029,7 @@ public class LockPatternView extends View {
return new SavedState(superState,
LockPatternUtils.patternToString(mPattern),
mPatternDisplayMode.ordinal(),
- mInputEnabled, mInStealthMode, mTactileFeedbackEnabled);
+ mInputEnabled, mInStealthMode, mTactileFeedbackEnabled, mVisibleDots, mShowErrorPath);
}
@Override
@@ -1003,6 +1043,8 @@ public class LockPatternView extends View {
mInputEnabled = ss.isInputEnabled();
mInStealthMode = ss.isInStealthMode();
mTactileFeedbackEnabled = ss.isTactileFeedbackEnabled();
+ mVisibleDots = ss.isVisibleDots();
+ mShowErrorPath = ss.isShowErrorPath();
}
/**
@@ -1015,18 +1057,22 @@ public class LockPatternView extends View {
private final boolean mInputEnabled;
private final boolean mInStealthMode;
private final boolean mTactileFeedbackEnabled;
+ private final boolean mVisibleDots;
+ private final boolean mShowErrorPath;
/**
* Constructor called from {@link LockPatternView#onSaveInstanceState()}
*/
private SavedState(Parcelable superState, String serializedPattern, int displayMode,
- boolean inputEnabled, boolean inStealthMode, boolean tactileFeedbackEnabled) {
+ boolean inputEnabled, boolean inStealthMode, boolean tactileFeedbackEnabled, boolean visibleDots, boolean showErrorPath) {
super(superState);
mSerializedPattern = serializedPattern;
mDisplayMode = displayMode;
mInputEnabled = inputEnabled;
mInStealthMode = inStealthMode;
mTactileFeedbackEnabled = tactileFeedbackEnabled;
+ mVisibleDots = visibleDots;
+ mShowErrorPath = showErrorPath;
}
/**
@@ -1039,6 +1085,8 @@ public class LockPatternView extends View {
mInputEnabled = (Boolean) in.readValue(null);
mInStealthMode = (Boolean) in.readValue(null);
mTactileFeedbackEnabled = (Boolean) in.readValue(null);
+ mVisibleDots = (Boolean) in.readValue(null);
+ mShowErrorPath = (Boolean) in.readValue(null);
}
public String getSerializedPattern() {
@@ -1060,6 +1108,14 @@ public class LockPatternView extends View {
public boolean isTactileFeedbackEnabled(){
return mTactileFeedbackEnabled;
}
+
+ public boolean isVisibleDots() {
+ return mVisibleDots;
+ }
+
+ public boolean isShowErrorPath() {
+ return mShowErrorPath;
+ }
@Override
public void writeToParcel(Parcel dest, int flags) {
@@ -1069,6 +1125,8 @@ public class LockPatternView extends View {
dest.writeValue(mInputEnabled);
dest.writeValue(mInStealthMode);
dest.writeValue(mTactileFeedbackEnabled);
+ dest.writeValue(mVisibleDots);
+ dest.writeValue(mShowErrorPath);
}
public static final Parcelable.Creator<SavedState> CREATOR =
diff --git a/core/java/com/google/android/mms/pdu/PduParser.java b/core/java/com/google/android/mms/pdu/PduParser.java
index 131ac51..4ca92e3 100644
--- a/core/java/com/google/android/mms/pdu/PduParser.java
+++ b/core/java/com/google/android/mms/pdu/PduParser.java
@@ -163,6 +163,13 @@ public class PduParser {
// or "application/vnd.wap.multipart.related"
// or "application/vnd.wap.multipart.alternative"
return retrieveConf;
+ } else if (ctTypeStr.equals(ContentType.MULTIPART_ALTERNATIVE)) {
+ // "application/vnd.wap.multipart.alternative"
+ // should take only the first part.
+ PduPart firstPart = mBody.getPart(0);
+ mBody.removeAll();
+ mBody.addPart(0, firstPart);
+ return retrieveConf;
}
return null;
case PduHeaders.MESSAGE_TYPE_DELIVERY_IND:
@@ -202,7 +209,18 @@ public class PduParser {
PduHeaders headers = new PduHeaders();
while (keepParsing && (pduDataStream.available() > 0)) {
+ pduDataStream.mark(1);
int headerField = extractByteValue(pduDataStream);
+ /* parse custom text header */
+ if ((headerField >= TEXT_MIN) && (headerField <= TEXT_MAX)) {
+ pduDataStream.reset();
+ byte [] bVal = parseWapString(pduDataStream, TYPE_TEXT_STRING);
+ if (LOCAL_LOGV) {
+ Log.v(LOG_TAG, "TextHeader: " + new String(bVal));
+ }
+ /* we should ignore it at the moment */
+ continue;
+ }
switch (headerField) {
case PduHeaders.MESSAGE_TYPE:
{
@@ -780,26 +798,34 @@ public class PduParser {
/* get part's data */
if (dataLength > 0) {
byte[] partData = new byte[dataLength];
+ String partContentType = new String(part.getContentType());
pduDataStream.read(partData, 0, dataLength);
- // Check Content-Transfer-Encoding.
- byte[] partDataEncoding = part.getContentTransferEncoding();
- if (null != partDataEncoding) {
- String encoding = new String(partDataEncoding);
- if (encoding.equalsIgnoreCase(PduPart.P_BASE64)) {
- // Decode "base64" into "binary".
- partData = Base64.decodeBase64(partData);
- } else if (encoding.equalsIgnoreCase(PduPart.P_QUOTED_PRINTABLE)) {
- // Decode "quoted-printable" into "binary".
- partData = QuotedPrintable.decodeQuotedPrintable(partData);
- } else {
- // "binary" is the default encoding.
+ if (partContentType.equalsIgnoreCase(ContentType.MULTIPART_ALTERNATIVE)) {
+ // parse "multipart/vnd.wap.multipart.alternative".
+ PduBody childBody = parseParts(new ByteArrayInputStream(partData));
+ // take the first part of children.
+ part = childBody.getPart(0);
+ } else {
+ // Check Content-Transfer-Encoding.
+ byte[] partDataEncoding = part.getContentTransferEncoding();
+ if (null != partDataEncoding) {
+ String encoding = new String(partDataEncoding);
+ if (encoding.equalsIgnoreCase(PduPart.P_BASE64)) {
+ // Decode "base64" into "binary".
+ partData = Base64.decodeBase64(partData);
+ } else if (encoding.equalsIgnoreCase(PduPart.P_QUOTED_PRINTABLE)) {
+ // Decode "quoted-printable" into "binary".
+ partData = QuotedPrintable.decodeQuotedPrintable(partData);
+ } else {
+ // "binary" is the default encoding.
+ }
}
+ if (null == partData) {
+ log("Decode part data error!");
+ return null;
+ }
+ part.setData(partData);
}
- if (null == partData) {
- log("Decode part data error!");
- return null;
- }
- part.setData(partData);
}
/* add this part to body */
@@ -1531,18 +1557,36 @@ public class PduParser {
* Attachment = <Octet 129>
* Inline = <Octet 130>
*/
- int len = parseValueLength(pduDataStream);
+ int len = -1;
+ boolean validDispositionLength = true;
+ pduDataStream.mark(1);
+
+ try {
+ len = parseValueLength(pduDataStream);
+ } catch (RuntimeException e) {
+ // tolerate invalid content-disposition length
+ len = 31;
+ validDispositionLength = false;
+ pduDataStream.reset();
+ }
+
pduDataStream.mark(1);
int thisStartPos = pduDataStream.available();
int thisEndPos = 0;
int value = pduDataStream.read();
-
- if (value == PduPart.P_DISPOSITION_FROM_DATA ) {
- part.setContentDisposition(PduPart.DISPOSITION_FROM_DATA);
- } else if (value == PduPart.P_DISPOSITION_ATTACHMENT) {
- part.setContentDisposition(PduPart.DISPOSITION_ATTACHMENT);
- } else if (value == PduPart.P_DISPOSITION_INLINE) {
- part.setContentDisposition(PduPart.DISPOSITION_INLINE);
+
+ if (validDispositionLength) {
+ if (value == PduPart.P_DISPOSITION_FROM_DATA ) {
+ part.setContentDisposition(PduPart.DISPOSITION_FROM_DATA);
+ } else if (value == PduPart.P_DISPOSITION_ATTACHMENT) {
+ part.setContentDisposition(PduPart.DISPOSITION_ATTACHMENT);
+ } else if (value == PduPart.P_DISPOSITION_INLINE) {
+ part.setContentDisposition(PduPart.DISPOSITION_INLINE);
+ } else {
+ pduDataStream.reset();
+ /* Token-text */
+ part.setContentDisposition(parseWapString(pduDataStream, TYPE_TEXT_STRING));
+ }
} else {
pduDataStream.reset();
/* Token-text */
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index df1ab9e..6edc45f 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -120,6 +120,7 @@ LOCAL_SRC_FILES:= \
android_server_BluetoothService.cpp \
android_server_BluetoothEventLoop.cpp \
android_server_BluetoothA2dpService.cpp \
+ android_server_BluetoothHidService.cpp \
android_server_Watchdog.cpp \
android_message_digest_sha1.cpp \
android_ddm_DdmHandleNativeHeap.cpp \
@@ -162,8 +163,6 @@ LOCAL_SHARED_LIBRARIES := \
libbinder \
libnetutils \
libui \
- libsurfaceflinger_client \
- libcamera_client \
libskiagl \
libskia \
libsqlite \
@@ -184,6 +183,12 @@ LOCAL_SHARED_LIBRARIES := \
libwpa_client \
libjpeg
+ifneq ($(BOARD_USES_ECLAIR_LIBCAMERA),true)
+ LOCAL_SHARED_LIBRARIES += \
+ libsurfaceflinger_client \
+ libcamera_client
+endif
+
ifeq ($(BOARD_HAVE_BLUETOOTH),true)
LOCAL_C_INCLUDES += \
external/dbus \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index d38d748..682f78e 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -153,6 +153,7 @@ extern int register_android_bluetooth_ScoSocket(JNIEnv *env);
extern int register_android_server_BluetoothService(JNIEnv* env);
extern int register_android_server_BluetoothEventLoop(JNIEnv *env);
extern int register_android_server_BluetoothA2dpService(JNIEnv* env);
+extern int register_android_server_BluetoothHidService(JNIEnv* env);
extern int register_android_server_Watchdog(JNIEnv* env);
extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
extern int register_com_android_internal_os_ZygoteInit(JNIEnv* env);
@@ -555,7 +556,10 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
}
}
- property_get("dalvik.vm.execution-mode", propBuf, "");
+ property_get("persist.sys.jit-mode", propBuf, "");
+ if (strcmp(propBuf, "") == 0) {
+ property_get("dalvik.vm.execution-mode", propBuf, "");
+ }
if (strcmp(propBuf, "int:portable") == 0) {
executionMode = kEMIntPortable;
} else if (strcmp(propBuf, "int:fast") == 0) {
@@ -603,8 +607,12 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
//options[curOpt++].optionString = "-verbose:class";
strcpy(heapsizeOptsBuf, "-Xmx");
- property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");
- //LOGI("Heap size: %s", heapsizeOptsBuf);
+ property_get("persist.sys.vm.heapsize", propBuf, "");
+ if (strcmp(propBuf, "") == 0) {
+ property_get("dalvim.vm.heapsize", propBuf, "16m");
+ }
+ strcpy(heapsizeOptsBuf+4, propBuf);
+ LOGI("Heap size: %s", heapsizeOptsBuf);
opt.optionString = heapsizeOptsBuf;
mOptions.add(opt);
@@ -1277,6 +1285,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_server_BluetoothService),
REG_JNI(register_android_server_BluetoothEventLoop),
REG_JNI(register_android_server_BluetoothA2dpService),
+ REG_JNI(register_android_server_BluetoothHidService),
REG_JNI(register_android_server_Watchdog),
REG_JNI(register_android_message_digest_sha1),
REG_JNI(register_android_ddm_DdmHandleNativeHeap),
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index e1e9536..a528006 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -951,7 +951,7 @@ static JNINativeMethod gCanvasMethods[] = {
(void*) SkCanvasGlue::drawText___CIIFFPaint},
{"native_drawText","(ILjava/lang/String;IIFFI)V",
(void*) SkCanvasGlue::drawText__StringIIFFPaint},
- {"drawText","(Ljava/lang/String;FFLandroid/graphics/Paint;)V",
+ {"native_drawText","(Ljava/lang/String;FFLandroid/graphics/Paint;)V",
(void*) SkCanvasGlue::drawString},
{"native_drawPosText","(I[CII[FI)V",
(void*) SkCanvasGlue::drawPosText___CII_FPaint},
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index b85466b..7531dee 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -476,7 +476,8 @@ static void android_hardware_Camera_setParameters(JNIEnv *env, jobject thiz, jst
env->ReleaseStringCritical(params, str);
}
if (camera->setParameters(params8) != NO_ERROR) {
- jniThrowException(env, "java/lang/RuntimeException", "setParameters failed");
+ LOGE("setParameters failed!");
+ //jniThrowException(env, "java/lang/RuntimeException", "setParameters failed");
return;
}
}
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index feb0dad..50df9d3 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -22,29 +22,8 @@
#include <utils/Log.h>
#include <arpa/inet.h>
-extern "C" {
-int ifc_enable(const char *ifname);
-int ifc_disable(const char *ifname);
-int ifc_add_host_route(const char *ifname, uint32_t addr);
-int ifc_remove_host_routes(const char *ifname);
-int ifc_set_default_route(const char *ifname, uint32_t gateway);
-int ifc_get_default_route(const char *ifname);
-int ifc_remove_default_route(const char *ifname);
-int ifc_reset_connections(const char *ifname);
-int ifc_configure(const char *ifname, in_addr_t ipaddr, in_addr_t netmask, in_addr_t gateway, in_addr_t dns1, in_addr_t dns2);
-
-int dhcp_do_request(const char *ifname,
- in_addr_t *ipaddr,
- in_addr_t *gateway,
- in_addr_t *mask,
- in_addr_t *dns1,
- in_addr_t *dns2,
- in_addr_t *server,
- uint32_t *lease);
-int dhcp_stop(const char *ifname);
-int dhcp_release_lease(const char *ifname);
-char *dhcp_get_errmsg();
-}
+#include <netutils/ifc.h>
+#include <netutils/dhcp.h>
#define NETUTILS_PKG_NAME "android/net/NetworkUtils"
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index 46000c9..5903f09 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -30,23 +30,6 @@ namespace android {
static jboolean sScanModeActive = false;
-/*
- * The following remembers the jfieldID's of the fields
- * of the DhcpInfo Java object, so that we don't have
- * to look them up every time.
- */
-static struct fieldIds {
- jclass dhcpInfoClass;
- jmethodID constructorId;
- jfieldID ipaddress;
- jfieldID gateway;
- jfieldID netmask;
- jfieldID dns1;
- jfieldID dns2;
- jfieldID serverAddress;
- jfieldID leaseDuration;
-} dhcpInfoFieldIds;
-
static int doCommand(const char *cmd, char *replybuf, int replybuflen)
{
size_t reply_len = replybuflen - 1;
@@ -479,28 +462,6 @@ static jboolean android_net_wifi_clearBlacklistCommand(JNIEnv* env, jobject claz
return doBooleanCommand("BLACKLIST clear", "OK");
}
-static jboolean android_net_wifi_doDhcpRequest(JNIEnv* env, jobject clazz, jobject info)
-{
- jint ipaddr, gateway, mask, dns1, dns2, server, lease;
- jboolean succeeded = ((jboolean)::do_dhcp_request(&ipaddr, &gateway, &mask,
- &dns1, &dns2, &server, &lease) == 0);
- if (succeeded && dhcpInfoFieldIds.dhcpInfoClass != NULL) {
- env->SetIntField(info, dhcpInfoFieldIds.ipaddress, ipaddr);
- env->SetIntField(info, dhcpInfoFieldIds.gateway, gateway);
- env->SetIntField(info, dhcpInfoFieldIds.netmask, mask);
- env->SetIntField(info, dhcpInfoFieldIds.dns1, dns1);
- env->SetIntField(info, dhcpInfoFieldIds.dns2, dns2);
- env->SetIntField(info, dhcpInfoFieldIds.serverAddress, server);
- env->SetIntField(info, dhcpInfoFieldIds.leaseDuration, lease);
- }
- return succeeded;
-}
-
-static jstring android_net_wifi_getDhcpError(JNIEnv* env, jobject clazz)
-{
- return env->NewStringUTF(::get_dhcp_error_string());
-}
-
// ----------------------------------------------------------------------------
/*
@@ -556,9 +517,6 @@ static JNINativeMethod gWifiMethods[] = {
{ "setScanResultHandlingCommand", "(I)Z", (void*) android_net_wifi_setScanResultHandlingCommand },
{ "addToBlacklistCommand", "(Ljava/lang/String;)Z", (void*) android_net_wifi_addToBlacklistCommand },
{ "clearBlacklistCommand", "()Z", (void*) android_net_wifi_clearBlacklistCommand },
-
- { "doDhcpRequest", "(Landroid/net/DhcpInfo;)Z", (void*) android_net_wifi_doDhcpRequest },
- { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_wifi_getDhcpError },
};
int register_android_net_wifi_WifiManager(JNIEnv* env)
@@ -566,18 +524,6 @@ int register_android_net_wifi_WifiManager(JNIEnv* env)
jclass wifi = env->FindClass(WIFI_PKG_NAME);
LOG_FATAL_IF(wifi == NULL, "Unable to find class " WIFI_PKG_NAME);
- dhcpInfoFieldIds.dhcpInfoClass = env->FindClass("android/net/DhcpInfo");
- if (dhcpInfoFieldIds.dhcpInfoClass != NULL) {
- dhcpInfoFieldIds.constructorId = env->GetMethodID(dhcpInfoFieldIds.dhcpInfoClass, "<init>", "()V");
- dhcpInfoFieldIds.ipaddress = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "ipAddress", "I");
- dhcpInfoFieldIds.gateway = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "gateway", "I");
- dhcpInfoFieldIds.netmask = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "netmask", "I");
- dhcpInfoFieldIds.dns1 = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "dns1", "I");
- dhcpInfoFieldIds.dns2 = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "dns2", "I");
- dhcpInfoFieldIds.serverAddress = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "serverAddress", "I");
- dhcpInfoFieldIds.leaseDuration = env->GetFieldID(dhcpInfoFieldIds.dhcpInfoClass, "leaseDuration", "I");
- }
-
return AndroidRuntime::registerNativeMethods(env,
WIFI_PKG_NAME, gWifiMethods, NELEM(gWifiMethods));
}
diff --git a/core/jni/android_server_BluetoothEventLoop.cpp b/core/jni/android_server_BluetoothEventLoop.cpp
index 259cc01..7c35ff4 100644
--- a/core/jni/android_server_BluetoothEventLoop.cpp
+++ b/core/jni/android_server_BluetoothEventLoop.cpp
@@ -729,6 +729,7 @@ static jboolean isEventLoopRunningNative(JNIEnv *env, jobject object) {
#ifdef HAVE_BLUETOOTH
extern DBusHandlerResult a2dp_event_filter(DBusMessage *msg, JNIEnv *env);
+extern DBusHandlerResult hid_event_filter(DBusMessage *msg, JNIEnv *env);
// Called by dbus during WaitForAndDispatchEventNative()
static DBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg,
@@ -853,9 +854,21 @@ static DBusHandlerResult event_filter(DBusConnection *conn, DBusMessage *msg,
method_onDeviceDisconnectRequested,
env->NewStringUTF(remote_device_path));
goto success;
+ } else if (dbus_message_is_signal(msg,
+ "org.bluez.Input",
+ "PropertyChanged")) {
+ LOGD("Input device receive propertychnaged!!!");
}
+ if (a2dp_event_filter(msg, env) == DBUS_HANDLER_RESULT_HANDLED) {
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ } else if (hid_event_filter(msg, env) == DBUS_HANDLER_RESULT_HANDLED) {
+ ret = DBUS_HANDLER_RESULT_HANDLED;
+ } else {
+ ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
- ret = a2dp_event_filter(msg, env);
+ //ret = a2dp_event_filter(msg, env);
env->PopLocalFrame(NULL);
return ret;
diff --git a/core/jni/android_server_BluetoothHidService.cpp b/core/jni/android_server_BluetoothHidService.cpp
new file mode 100644
index 0000000..1e54a02
--- /dev/null
+++ b/core/jni/android_server_BluetoothHidService.cpp
@@ -0,0 +1,335 @@
+/*
+** Copyright 2009 ISB Corporation
+** Copyright (C) 2010 0xlab
+**
+** 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 "BluetoothHidService.cpp"
+
+#include "android_bluetooth_common.h"
+#include "android_runtime/AndroidRuntime.h"
+#include "JNIHelp.h"
+#include "jni.h"
+#include "utils/Log.h"
+#include "utils/misc.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef HAVE_BLUETOOTH
+#include <dbus/dbus.h>
+#endif
+
+namespace android {
+
+#ifdef HAVE_BLUETOOTH
+static jmethodID method_onPropertyChanged;
+static jmethodID method_onHidDeviceConnected;
+static jmethodID method_onHidDeviceDisconnected;
+
+typedef struct {
+ JavaVM *vm;
+ int envVer;
+ DBusConnection *conn;
+ jobject me; // for callbacks to java
+} native_data_t;
+
+static native_data_t *nat = NULL; // global native data
+static Properties hid_properties[] = {
+ {"Connected", DBUS_TYPE_BOOLEAN},
+ };
+static void onConnectHidDeviceResult(DBusMessage *msg, void *user, void *nat);
+static void onDisconnectHidDeviceResult(DBusMessage *msg, void *user, void *nat);
+#endif
+
+
+/* Returns true on success (even if adapter is present but disabled).
+ * Return false if dbus is down, or another serious error (out of memory)
+*/
+static bool initNative(JNIEnv* env, jobject object) {
+ LOGD(__FUNCTION__);
+#ifdef HAVE_BLUETOOTH
+ nat = (native_data_t *)calloc(1, sizeof(native_data_t));
+ if (NULL == nat) {
+ LOGE("%s: out of memory!", __FUNCTION__);
+ return false;
+ }
+ env->GetJavaVM( &(nat->vm) );
+ nat->envVer = env->GetVersion();
+ nat->me = env->NewGlobalRef(object);
+
+ DBusError err;
+ dbus_error_init(&err);
+ dbus_threads_init_default();
+ nat->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
+ if (dbus_error_is_set(&err)) {
+ LOGE("Could not get onto the system bus: %s", err.message);
+ dbus_error_free(&err);
+ return false;
+ }
+#endif /*HAVE_BLUETOOTH*/
+ return true;
+}
+
+static void cleanupNative(JNIEnv* env, jobject object) {
+#ifdef HAVE_BLUETOOTH
+ LOGD(__FUNCTION__);
+ if (nat) {
+ dbus_connection_close(nat->conn);
+ env->DeleteGlobalRef(nat->me);
+ free(nat);
+ nat = NULL;
+ }
+#endif
+}
+
+static jobjectArray getHidPropertiesNative(JNIEnv *env, jobject object,
+ jstring path) {
+#ifdef HAVE_BLUETOOTH
+ LOGD(__FUNCTION__);
+ if (nat) {
+ DBusMessage *msg, *reply;
+ DBusError err;
+ dbus_error_init(&err);
+
+ const char *c_path = env->GetStringUTFChars(path, NULL);
+ reply = dbus_func_args_timeout(env,
+ nat->conn, -1, c_path,
+ "org.bluez.Input", "GetProperties",
+ DBUS_TYPE_INVALID);
+ env->ReleaseStringUTFChars(path, c_path);
+ if (!reply && dbus_error_is_set(&err)) {
+ LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
+ return NULL;
+ } else if (!reply) {
+ LOGE("DBus reply is NULL in function %s", __FUNCTION__);
+ return NULL;
+ }
+ DBusMessageIter iter;
+ if (dbus_message_iter_init(reply, &iter))
+ return parse_properties(env, &iter, (Properties *)&hid_properties,
+ sizeof(hid_properties) / sizeof(Properties));
+ }
+#endif
+ return NULL;
+}
+
+static jboolean connectHidDeviceNative(JNIEnv *env, jobject object, jstring path) {
+#ifdef HAVE_BLUETOOTH
+ LOGD(__FUNCTION__);
+ if (nat) {
+ const char *c_path = env->GetStringUTFChars(path, NULL);
+ size_t path_sz = env->GetStringUTFLength(path) + 1;
+ char *c_path_copy = (char *)malloc(path_sz); // callback data
+ strncpy(c_path_copy, c_path, path_sz);
+
+ bool ret =
+ dbus_func_args_async(env, nat->conn, -1, onConnectHidDeviceResult,
+ (void *)c_path_copy, nat,
+ c_path, "org.bluez.Input",
+ "Connect", DBUS_TYPE_INVALID);
+
+ env->ReleaseStringUTFChars(path, c_path);
+ if (!ret) {
+ free(c_path_copy);
+ return JNI_FALSE;
+ }
+ return JNI_TRUE;
+ }
+#endif
+ return JNI_FALSE;
+}
+
+static jboolean disconnectHidDeviceNative(JNIEnv *env, jobject object,
+ jstring path) {
+#ifdef HAVE_BLUETOOTH
+ LOGD(__FUNCTION__);
+ if (nat) {
+ const char *c_path = env->GetStringUTFChars(path, NULL);
+
+ bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
+ c_path, "org.bluez.Input", "Disconnect",
+ DBUS_TYPE_INVALID);
+ LOGD("... path = %s", c_path);
+ env->ReleaseStringUTFChars(path, c_path);
+ return ret ? JNI_TRUE : JNI_FALSE;
+ }
+#endif
+ return JNI_FALSE;
+}
+
+
+#ifdef HAVE_BLUETOOTH
+
+static void onConnectHidDeviceResult(DBusMessage *msg, void *user, void *natData) {
+ LOGD(__FUNCTION__);
+
+ char *c_path = (char *)user;
+ DBusError err;
+ JNIEnv *env;
+
+ if (nat->vm->GetEnv((void**)&env, nat->envVer) < 0) {
+ LOGE("%s: error finding Env for our VM\n", __FUNCTION__);
+ return;
+ }
+
+ dbus_error_init(&err);
+
+ LOGD("... path = %s", c_path);
+ if (dbus_set_error_from_message(&err, msg)) {
+ LOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message);
+ dbus_error_free(&err);
+ env->CallVoidMethod(nat->me,
+ method_onHidDeviceDisconnected,
+ env->NewStringUTF(c_path));
+ if (env->ExceptionCheck()) {
+ LOGE("VM Exception occurred in native function %s (%s:%d)",
+ __FUNCTION__, __FILE__, __LINE__);
+ }
+ } else { // else Java callback is triggered by signal in hid_event_filter?
+ env->CallVoidMethod(nat->me,
+ method_onHidDeviceConnected,
+ env->NewStringUTF(c_path));
+ }
+
+ free(c_path);
+}
+
+static void onDisconnectHidDeviceResult(DBusMessage *msg, void *user, void *natData) {
+ LOGD(__FUNCTION__);
+
+ char *c_path = (char *)user;
+ DBusError err;
+ JNIEnv *env;
+
+ if (nat->vm->GetEnv((void**)&env, nat->envVer) < 0) {
+ LOGE("%s: error finding Env for our VM\n", __FUNCTION__);
+ return;
+ }
+
+ dbus_error_init(&err);
+
+ LOGD("... path = %s", c_path);
+ if (dbus_set_error_from_message(&err, msg)) {
+ LOGE("%s: D-Bus error: %s (%s)\n", __FUNCTION__, err.name, err.message);
+ if (strcmp(err.name, "org.bluez.Error.NotConnected") == 0) {
+ // we were already disconnected, so report disconnect
+ env->CallVoidMethod(nat->me,
+ method_onHidDeviceDisconnected,
+ env->NewStringUTF(c_path));
+ } else {
+ // Assume it is still connected
+ env->CallVoidMethod(nat->me,
+ method_onHidDeviceConnected,
+ env->NewStringUTF(c_path));
+ }
+ dbus_error_free(&err);
+ if (env->ExceptionCheck()) {
+ LOGE("VM Exception occurred in native function %s (%s:%d)",
+ __FUNCTION__, __FILE__, __LINE__);
+ }
+ } else { // else Java callback is triggered by signal in hid_event_filter?
+ env->CallVoidMethod(nat->me,
+ method_onHidDeviceDisconnected,
+ env->NewStringUTF(c_path));
+ }
+ free(c_path);
+}
+
+DBusHandlerResult hid_event_filter(DBusMessage *msg, JNIEnv *env) {
+ DBusError err;
+ LOGD("hid_event_filter...");
+ if (!nat) {
+ LOGE("... skipping %s\n", __FUNCTION__);
+ LOGE("... ignored\n");
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ dbus_error_init(&err);
+
+ if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_SIGNAL) {
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ DBusHandlerResult result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if (dbus_message_is_signal(msg, "org.bluez.Input",
+ "PropertyChanged")) {
+ jobjectArray str_array =
+ parse_property_change(env, msg, (Properties *)&hid_properties,
+ sizeof(hid_properties) / sizeof(Properties));
+ const char *c_path = dbus_message_get_path(msg);
+ LOGD("received org.bluez.Input PropertyChanged...");
+ jstring path = env->NewStringUTF(c_path);
+
+ env->CallVoidMethod(nat->me,
+ method_onPropertyChanged,
+ path,
+ str_array);
+
+ env->DeleteLocalRef(path);
+
+ result = DBUS_HANDLER_RESULT_HANDLED;
+ return result;
+ } else {
+ LOGV("... ignored");
+ }
+ if (env->ExceptionCheck()) {
+ LOGE("VM Exception occurred while handling %s.%s (%s) in %s,"
+ " leaving for VM",
+ dbus_message_get_interface(msg), dbus_message_get_member(msg),
+ dbus_message_get_path(msg), __FUNCTION__);
+ }
+
+ return result;
+}
+#endif
+
+
+static JNINativeMethod sMethods[] = {
+ {"initNative", "()Z", (void *)initNative},
+ {"cleanupNative", "()V", (void *)cleanupNative},
+
+
+ {"connectHidDeviceNative", "(Ljava/lang/String;)Z", (void*)connectHidDeviceNative},
+ {"disconnectHidDeviceNative", "(Ljava/lang/String;)Z", (void*)disconnectHidDeviceNative},
+ {"getHidPropertiesNative", "(Ljava/lang/String;)[Ljava/lang/Object;",
+ (void *)getHidPropertiesNative},
+};
+
+
+int register_android_server_BluetoothHidService(JNIEnv *env) {
+ jclass clazz = env->FindClass("android/server/BluetoothHidService");
+ if (clazz == NULL) {
+ LOGE("Can't find android/server/BluetoothHidService");
+ return -1;
+ }
+
+#ifdef HAVE_BLUETOOTH
+ method_onHidDeviceConnected = env->GetMethodID(clazz, "onHidDeviceConnected", "(Ljava/lang/String;)V");
+ method_onHidDeviceDisconnected = env->GetMethodID(clazz, "onHidDeviceDisconnected", "(Ljava/lang/String;)V");
+ method_onPropertyChanged = env->GetMethodID(clazz, "onPropertyChanged",
+ "(Ljava/lang/String;[Ljava/lang/String;)V");
+#endif
+
+ return AndroidRuntime::registerNativeMethods(env,
+ "android/server/BluetoothHidService", sMethods, NELEM(sMethods));
+}
+
+
+} /* namespace android */
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index 200a1b2..70375f9 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -131,12 +131,23 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:drawablePadding="4dip"
/>
+
+ <TextView
+ android:id="@+id/customMsg"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="4.0dip"
+ android:layout_marginLeft="24dip"
+ android:layout_marginRight="24dip"
+ android:layout_below="@id/status2"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ />
<TextView
android:id="@+id/screenLocked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_below="@id/status2"
+ android:layout_below="@id/customMsg"
android:layout_marginLeft="24dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_marginTop="12dip"
@@ -167,5 +178,56 @@
android:visibility="gone"
/>
+ <!-- music control buttons -->
+ <ImageButton
+ android:id="@+id/musicControlPlay"
+ android:src="@drawable/ic_media_play"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerInParent="true"
+ android:layout_alignParentBottom="true"
+ android:layout_marginBottom="20dip"
+ android:padding="10px"
+ android:background="@color/transparent"
+ android:visibility="gone"
+ />
+ <ImageButton
+ android:id="@+id/musicControlPause"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_media_pause"
+ android:layout_centerInParent="true"
+ android:layout_alignParentBottom="true"
+ android:layout_marginBottom="20dip"
+ android:padding="10px"
+ android:background="@color/transparent"
+ android:visibility="gone"
+ />
+ <ImageButton
+ android:id="@+id/musicControlPrevious"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_media_previous"
+ android:layout_alignParentBottom="true"
+ android:layout_marginBottom="20dip"
+ android:padding="10px"
+ android:layout_toLeftOf="@+id/musicControlPause"
+ android:background="@color/transparent"
+ android:visibility="gone"
+ />
+ <ImageButton
+ android:id="@+id/musicControlNext"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_media_next"
+ android:layout_alignParentBottom="true"
+ android:layout_marginBottom="20dip"
+ android:padding="10px"
+ android:layout_toRightOf="@+id/musicControlPause"
+ android:background="@color/transparent"
+ android:visibility="gone"
+ />
+
+
</RelativeLayout>
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index 23505c2..1e5884d 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -130,17 +130,75 @@
android:textAppearance="?android:attr/textAppearanceMedium"
android:drawablePadding="4dip"
/>
+
+ <TextView
+ android:id="@+id/customMsg"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="4.0dip"
+ android:layout_below="@id/status2"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ />
<TextView
android:id="@+id/screenLocked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_below="@id/status2"
+ android:layout_below="@id/customMsg"
android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="center"
android:layout_marginTop="12dip"
android:drawablePadding="4dip"
/>
+ <!-- music control buttons -->
+ <ImageButton
+ android:id="@+id/musicControlPlay"
+ android:src="@drawable/ic_media_play"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerInParent="true"
+ android:layout_alignParentBottom="true"
+ android:layout_marginBottom="20dip"
+ android:padding="10px"
+ android:background="@color/transparent"
+ android:visibility="gone"
+ />
+ <ImageButton
+ android:id="@+id/musicControlPause"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_media_pause"
+ android:layout_centerInParent="true"
+ android:layout_alignParentBottom="true"
+ android:layout_marginBottom="20dip"
+ android:padding="10px"
+ android:background="@color/transparent"
+ android:visibility="gone"
+ />
+ <ImageButton
+ android:id="@+id/musicControlPrevious"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_media_previous"
+ android:layout_alignParentBottom="true"
+ android:layout_marginBottom="20dip"
+ android:padding="10px"
+ android:layout_toLeftOf="@+id/musicControlPause"
+ android:background="@color/transparent"
+ android:visibility="gone"
+ />
+ <ImageButton
+ android:id="@+id/musicControlNext"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_media_next"
+ android:layout_alignParentBottom="true"
+ android:layout_marginBottom="20dip"
+ android:padding="10px"
+ android:layout_toRightOf="@+id/musicControlPause"
+ android:background="@color/transparent"
+ android:visibility="gone"
+ />
</RelativeLayout>
diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
index b5cd442..f512378 100644
--- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
@@ -137,6 +137,13 @@
android:drawablePadding="4dip"
/>
</LinearLayout>
+
+ <TextView
+ android:id="@+id/customMsg"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ />
<!-- fill space between header and button below -->
<View
diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
index 9ac0a47..9f99fec 100644
--- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
@@ -100,6 +100,17 @@
/>
</RelativeLayout>
+
+ <TextView
+ android:id="@+id/customMsg"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="4dip"
+ android:layout_marginLeft="24dip"
+ android:layout_marginRight="24dip"
+ android:layout_below="@id/status2"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ />
<View
android:id="@+id/divider"
diff --git a/core/res/res/layout/recent_apps_dialog.xml b/core/res/res/layout/recent_apps_dialog.xml
index e3492f6..dece5ec 100644
--- a/core/res/res/layout/recent_apps_dialog.xml
+++ b/core/res/res/layout/recent_apps_dialog.xml
@@ -28,6 +28,7 @@
<!-- Title -->
<TextView
+ android:id="@+id/recent_title"
android:layout_width="wrap_content"
android:layout_height="40dip"
android:gravity="center"
diff --git a/core/res/res/layout/recent_apps_dialog_12.xml b/core/res/res/layout/recent_apps_dialog_12.xml
new file mode 100644
index 0000000..66db0b8
--- /dev/null
+++ b/core/res/res/layout/recent_apps_dialog_12.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<com.android.internal.policy.impl.RecentApplicationsBackground
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="@drawable/recent_dialog_background"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:padding="4dip"
+ android:orientation="vertical">
+
+ <!-- Title -->
+ <TextView
+ android:id="@+id/recent_title"
+ android:layout_width="wrap_content"
+ android:layout_height="20dip"
+ android:gravity="center"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="#80FFFFFF"
+ android:textStyle="bold"
+ android:singleLine="true"
+ android:text="@android:string/recent_tasks_title" />
+
+ <!-- This is only intended to be visible when all buttons (below) are invisible -->
+ <TextView
+ android:id="@+id/no_applications_message"
+ android:layout_width="320dip"
+ android:layout_height="80dip"
+ android:gravity="center"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:text="@android:string/no_recent_tasks" />
+
+ <!-- The first row has a fixed-width because the UI spec requires the box
+ to display with full-width no matter how many icons are visible, but to
+ adjust height based on number of rows. -->
+ <!-- TODO Adjust all sizes, padding, etc. to meet pixel-perfect specs -->
+ <LinearLayout
+ android:layout_width="320dip"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ >
+
+ <include
+ layout="@android:layout/recent_apps_icon_12"
+ android:id="@+id/button0" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_12"
+ android:id="@+id/button1" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_12"
+ android:id="@+id/button2" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_12"
+ android:id="@+id/button3" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="320dp"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <include
+ layout="@android:layout/recent_apps_icon_12"
+ android:id="@+id/button4" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_12"
+ android:id="@+id/button5" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_12"
+ android:id="@+id/button6" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_12"
+ android:id="@+id/button7" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="320dp"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <include
+ layout="@android:layout/recent_apps_icon_12"
+ android:id="@+id/button8" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_12"
+ android:id="@+id/button9" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_12"
+ android:id="@+id/button10" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_12"
+ android:id="@+id/button11" />
+
+ </LinearLayout>
+
+ <!-- spacer to balance out the title above -->
+ <FrameLayout
+ android:layout_height="20dip"
+ android:layout_width="match_parent"
+ />
+</com.android.internal.policy.impl.RecentApplicationsBackground>
diff --git a/core/res/res/layout/recent_apps_dialog_15.xml b/core/res/res/layout/recent_apps_dialog_15.xml
new file mode 100644
index 0000000..ee0f33e
--- /dev/null
+++ b/core/res/res/layout/recent_apps_dialog_15.xml
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<com.android.internal.policy.impl.RecentApplicationsBackground
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:background="@drawable/recent_dialog_background"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:padding="4dip"
+ android:orientation="vertical">
+
+ <!-- Title -->
+ <TextView
+ android:id="@+id/recent_title"
+ android:layout_width="wrap_content"
+ android:layout_height="20dip"
+ android:gravity="center"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="#80FFFFFF"
+ android:textStyle="bold"
+ android:singleLine="true"
+ android:text="@android:string/recent_tasks_title" />
+
+ <!-- This is only intended to be visible when all buttons (below) are invisible -->
+ <TextView
+ android:id="@+id/no_applications_message"
+ android:layout_width="320dip"
+ android:layout_height="80dip"
+ android:gravity="center"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:text="@android:string/no_recent_tasks" />
+
+ <!-- The first row has a fixed-width because the UI spec requires the box
+ to display with full-width no matter how many icons are visible, but to
+ adjust height based on number of rows. -->
+ <!-- TODO Adjust all sizes, padding, etc. to meet pixel-perfect specs -->
+ <LinearLayout
+ android:layout_width="320dip"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ >
+
+ <include
+ layout="@android:layout/recent_apps_icon_15"
+ android:id="@+id/button0" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_15"
+ android:id="@+id/button1" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_15"
+ android:id="@+id/button2" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_15"
+ android:id="@+id/button3" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_15"
+ android:id="@+id/button4" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="320dp"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <include
+ layout="@android:layout/recent_apps_icon_15"
+ android:id="@+id/button5" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_15"
+ android:id="@+id/button6" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_15"
+ android:id="@+id/button7" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_15"
+ android:id="@+id/button8" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_15"
+ android:id="@+id/button9" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="320dp"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <include
+ layout="@android:layout/recent_apps_icon_15"
+ android:id="@+id/button10" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_15"
+ android:id="@+id/button11" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_15"
+ android:id="@+id/button12" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_15"
+ android:id="@+id/button13" />
+
+ <include
+ layout="@android:layout/recent_apps_icon_15"
+ android:id="@+id/button14" />
+
+ </LinearLayout>
+
+ <!-- spacer to balance out the title above -->
+ <FrameLayout
+ android:layout_height="20dip"
+ android:layout_width="match_parent"
+ />
+</com.android.internal.policy.impl.RecentApplicationsBackground>
diff --git a/core/res/res/layout/recent_apps_icon_12.xml b/core/res/res/layout/recent_apps_icon_12.xml
new file mode 100644
index 0000000..c9501e1
--- /dev/null
+++ b/core/res/res/layout/recent_apps_icon_12.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is not a standalone element - it is imported into recent_apps_dialog.xml -->
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/label"
+ style="?android:attr/buttonStyle"
+ android:background="#00000000"
+ android:layout_width="80dip"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="3dip"
+ android:layout_marginBottom="3dip"
+ android:textColor="@color/bright_foreground_dark"
+
+ android:paddingTop="0dip"
+ android:paddingBottom="0dip"
+ android:drawablePadding="4dip"
+
+ android:textSize="11dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ android:gravity="top|center_horizontal" />
diff --git a/core/res/res/layout/recent_apps_icon_15.xml b/core/res/res/layout/recent_apps_icon_15.xml
new file mode 100644
index 0000000..8ec38f5
--- /dev/null
+++ b/core/res/res/layout/recent_apps_icon_15.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2008, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This is not a standalone element - it is imported into recent_apps_dialog.xml -->
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/label"
+ style="?android:attr/buttonStyle"
+ android:background="#00000000"
+ android:layout_width="64dip"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="3dip"
+ android:layout_marginBottom="3dip"
+ android:textColor="@color/bright_foreground_dark"
+
+ android:paddingTop="0dip"
+ android:paddingBottom="0dip"
+ android:drawablePadding="4dip"
+
+ android:textSize="11dip"
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal"
+ android:gravity="top|center_horizontal" />
diff --git a/core/res/res/layout/status_bar_expanded.xml b/core/res/res/layout/status_bar_expanded.xml
index 30138a7..b20492a 100644
--- a/core/res/res/layout/status_bar_expanded.xml
+++ b/core/res/res/layout/status_bar_expanded.xml
@@ -24,7 +24,7 @@
android:descendantFocusability="afterDescendants"
>
- <LinearLayout
+ <LinearLayout android:id="@+id/exp_view_lin_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
diff --git a/core/res/res/layout/status_bar_tracking.xml b/core/res/res/layout/status_bar_tracking.xml
index c0a7a97..b15ee39 100644
--- a/core/res/res/layout/status_bar_tracking.xml
+++ b/core/res/res/layout/status_bar_tracking.xml
@@ -36,7 +36,7 @@
android:layout_height="wrap_content"
android:orientation="vertical"
>
- <ImageView
+ <ImageView android:id="@+id/close_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 11095c0..da06ba5 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -134,11 +134,23 @@
<string name="power_off" msgid="4266614107412865048">"Ausschalten"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Wird heruntergefahren..."</string>
<string name="shutdown_confirm" msgid="649792175242821353">"Ihr Telefon wird heruntergefahren."</string>
+
+ <!-- Button to reboot the phone, within the Phone Options dialog -->
+ <string name="reboot_system">Neu starten</string>
+ <!-- Reboot Progress Dialog. This is shown if the user chooses to reboot the phone. -->
+ <string name="reboot_progress">Neu starten...</string>
+ <!-- Reboot Confirmation Dialog. When the user chooses to reboot the phone, there will be a confirmation dialog. This is the message. -->
+ <string name="reboot_confirm">Ihr Telefon wird neu gestartet.</string>
+
<string name="recent_tasks_title" msgid="3691764623638127888">"Zuletzt verwendet"</string>
<string name="no_recent_tasks" msgid="279702952298056674">"Keine zuletzt verwendeten Anwendungen"</string>
<string name="global_actions" msgid="2406416831541615258">"Telefonoptionen"</string>
<string name="global_action_lock" msgid="2844945191792119712">"Display-Sperre"</string>
<string name="global_action_power_off" msgid="4471879440839879722">"Ausschalten"</string>
+
+ <!-- label for item that reboots the phone in phone options dialog -->
+ <string name="global_action_reboot">Neu starten</string>
+
<string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Lautlos"</string>
<string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Ton ist AUS"</string>
<string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Ton ist AN"</string>
@@ -861,4 +873,7 @@
<string name="throttle_warning_notification_message" msgid="2609734763845705708">"Weitere Informationen über die Mobildatennutzung durch Berühren aufrufen"</string>
<string name="throttled_notification_title" msgid="6269541897729781332">"Mobildatenlimit überschritten"</string>
<string name="throttled_notification_message" msgid="4712369856601275146">"Weitere Informationen über die Mobildatennutzung durch Berühren aufrufen"</string>
+
+ <!-- Reboot recommended after applying color changes (CM) -->
+ <string name="toast_reboot_recommend">Achtung: Neustart wird empfohlen nach Beendigung der Anpassungen!</string>
</resources>
diff --git a/core/res/res/values-he-rIL/donottranslate-cldr.xml b/core/res/res/values-he-rIL/donottranslate-cldr.xml
new file mode 100644
index 0000000..89cbf42
--- /dev/null
+++ b/core/res/res/values-he-rIL/donottranslate-cldr.xml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="month_long_standalone_january">ינואר</string>
+ <string name="month_long_standalone_february">פברואר</string>
+ <string name="month_long_standalone_march">מרץ</string>
+ <string name="month_long_standalone_april">אפריל</string>
+ <string name="month_long_standalone_may">מאי</string>
+ <string name="month_long_standalone_june">יוני</string>
+ <string name="month_long_standalone_july">יולי</string>
+ <string name="month_long_standalone_august">אוגוסט</string>
+ <string name="month_long_standalone_september">ספטמבר</string>
+ <string name="month_long_standalone_october">אוקטובר</string>
+ <string name="month_long_standalone_november">נובמבר</string>
+ <string name="month_long_standalone_december">דצמבר</string>
+
+ <string name="month_long_january">ינואר</string>
+ <string name="month_long_february">פברואר</string>
+ <string name="month_long_march">מרץ</string>
+ <string name="month_long_april">אפריל</string>
+ <string name="month_long_may">מאי</string>
+ <string name="month_long_june">יוני</string>
+ <string name="month_long_july">יולי</string>
+ <string name="month_long_august">אוגוסט</string>
+ <string name="month_long_september">ספטמבר</string>
+ <string name="month_long_october">אוקטובר</string>
+ <string name="month_long_november">נובמבר</string>
+ <string name="month_long_december">דצמבר</string>
+
+ <string name="month_medium_january">ינו</string>
+ <string name="month_medium_february">פבר</string>
+ <string name="month_medium_march">מרץ</string>
+ <string name="month_medium_april">אפר</string>
+ <string name="month_medium_may">מאי</string>
+ <string name="month_medium_june">יונ</string>
+ <string name="month_medium_july">יול</string>
+ <string name="month_medium_august">אוג</string>
+ <string name="month_medium_september">ספט</string>
+ <string name="month_medium_october">אוק</string>
+ <string name="month_medium_november">נוב</string>
+ <string name="month_medium_december">דצמ</string>
+
+ <string name="month_shortest_january">י</string>
+ <string name="month_shortest_february">פ</string>
+ <string name="month_shortest_march">מ</string>
+ <string name="month_shortest_april">א</string>
+ <string name="month_shortest_may">מ</string>
+ <string name="month_shortest_june">י</string>
+ <string name="month_shortest_july">י</string>
+ <string name="month_shortest_august">א</string>
+ <string name="month_shortest_september">ס</string>
+ <string name="month_shortest_october">א</string>
+ <string name="month_shortest_november">נ</string>
+ <string name="month_shortest_december">ד</string>
+
+ <string name="day_of_week_long_sunday">יום ראשון</string>
+ <string name="day_of_week_long_monday">יום שני</string>
+ <string name="day_of_week_long_tuesday">יום שלישי</string>
+ <string name="day_of_week_long_wednesday">יום רביעי</string>
+ <string name="day_of_week_long_thursday">יום חמישי</string>
+ <string name="day_of_week_long_friday">יום שישי</string>
+ <string name="day_of_week_long_saturday">יום שבת</string>
+
+ <string name="day_of_week_medium_sunday">ראשון</string>
+ <string name="day_of_week_medium_monday">שני</string>
+ <string name="day_of_week_medium_tuesday">שלי</string>
+ <string name="day_of_week_medium_wednesday">רבי</string>
+ <string name="day_of_week_medium_thursday">חמי</string>
+ <string name="day_of_week_medium_friday">שיש</string>
+ <string name="day_of_week_medium_saturday">שבת</string>
+
+ <string name="day_of_week_short_sunday">Su</string>
+ <string name="day_of_week_short_monday">Mo</string>
+ <string name="day_of_week_short_tuesday">Tu</string>
+ <string name="day_of_week_short_wednesday">We</string>
+ <string name="day_of_week_short_thursday">Th</string>
+ <string name="day_of_week_short_friday">Fr</string>
+ <string name="day_of_week_short_saturday">Sa</string>
+
+ <string name="day_of_week_shortest_sunday">S</string>
+ <string name="day_of_week_shortest_monday">M</string>
+ <string name="day_of_week_shortest_tuesday">T</string>
+ <string name="day_of_week_shortest_wednesday">W</string>
+ <string name="day_of_week_shortest_thursday">T</string>
+ <string name="day_of_week_shortest_friday">F</string>
+ <string name="day_of_week_shortest_saturday">S</string>
+
+ <string name="am">am</string>
+ <string name="pm">pm</string>
+ <string name="yesterday">אתמול</string>
+ <string name="today">היום</string>
+ <string name="tomorrow">מחר</string>
+
+ <string name="hour_minute_24">%H:%M</string>
+ <string name="hour_minute_ampm">%-l:%M%p</string>
+ <string name="hour_minute_cap_ampm">%-l:%M%^p</string>
+ <string name="twelve_hour_time_format">h:mm a</string>
+ <string name="twenty_four_hour_time_format">HH:mm</string>
+ <string name="numeric_date">%-e/%-m/%Y</string>
+ <string name="numeric_date_format">d/M/yyyy</string>
+ <string name="numeric_date_template">"%s/%s/%s"</string>
+ <string name="month_day_year">%B %-e, %Y</string>
+ <string name="time_of_day">%-l:%M:%S %p</string>
+ <string name="date_and_time">%b %-e, %Y, %-l:%M:%S %p</string>
+ <string name="date_time">%1$s, %2$s</string>
+ <string name="time_date">%1$s, %3$s</string>
+ <string name="abbrev_month_day_year">%b %-e, %Y</string>
+ <string name="month_day">%B %-e</string>
+ <string name="month">%-B</string>
+ <string name="month_year">%B %Y</string>
+ <string name="abbrev_month_day">%b %-e</string>
+ <string name="abbrev_month">%-b</string>
+ <string name="abbrev_month_year">%b %Y</string>
+ <string name="time1_time2">%1$s – %2$s</string>
+ <string name="date1_date2">%2$s – %5$s</string>
+ <string name="numeric_md1_md2">%2$s/%3$s – %7$s/%8$s</string>
+ <string name="numeric_wday1_md1_wday2_md2">%1$s, %2$s/%3$s – %6$s, %7$s/%8$s</string>
+ <string name="numeric_mdy1_mdy2">%2$s/%3$s/%4$s – %7$s/%8$s/%9$s</string>
+ <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %2$s/%3$s/%4$s – %6$s, %7$s/%8$s/%9$s</string>
+ <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s/%3$s/%4$s, %5$s – %6$s, %7$s/%8$s/%9$s, %10$s</string>
+ <string name="numeric_md1_time1_md2_time2">%2$s/%3$s, %5$s – %7$s/%8$s, %10$s</string>
+ <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s/%3$s, %5$s – %6$s, %7$s/%8$s, %10$s</string>
+ <string name="numeric_mdy1_time1_mdy2_time2">%2$s/%3$s/%4$s, %5$s – %7$s/%8$s/%9$s, %10$s</string>
+ <string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s – %4$s, %5$s, %6$s</string>
+ <string name="wday1_date1_wday2_date2">%1$s, %2$s – %4$s, %5$s</string>
+ <string name="date1_time1_date2_time2">%2$s, %3$s – %5$s, %6$s</string>
+ <string name="time_wday_date">%1$s, %2$s, %3$s</string>
+ <string name="wday_date">%2$s, %3$s</string>
+ <string name="time_wday">%1$s, %2$s</string>
+ <string name="same_year_md1_md2">%2$s %3$s – %7$s %8$s</string>
+ <string name="same_year_wday1_md1_wday2_md2">%1$s, %2$s %3$s – %6$s, %7$s %8$s</string>
+ <string name="same_year_md1_time1_md2_time2">%2$s %3$s, %5$s – %7$s %8$s, %10$s</string>
+ <string name="same_month_md1_time1_md2_time2">%2$s %3$s, %5$s – %7$s %8$s, %10$s</string>
+ <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s – %6$s, %7$s %8$s, %10$s</string>
+ <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s – %6$s, %7$s %8$s, %10$s</string>
+ <string name="same_year_mdy1_time1_mdy2_time2">%2$s %3$s, %4$s, %5$s – %7$s %8$s, %9$s, %10$s</string>
+ <string name="same_month_mdy1_time1_mdy2_time2">%2$s %3$s, %4$s, %5$s – %7$s %8$s, %9$s, %10$s</string>
+ <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s – %6$s, %7$s %8$s, %9$s, %10$s</string>
+ <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s – %6$s, %7$s %8$s, %9$s, %10$s</string>
+ <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s, %4$s – %6$s, %7$s %8$s, %9$s</string>
+ <string name="same_month_md1_md2">%2$s %3$s – %8$s</string>
+ <string name="same_month_wday1_md1_wday2_md2">%1$s, %2$s %3$s – %6$s, %7$s %8$s</string>
+ <string name="same_year_mdy1_mdy2">%2$s %3$s – %7$s %8$s, %9$s</string>
+ <string name="same_month_mdy1_mdy2">%2$s %3$s – %8$s, %9$s</string>
+ <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s – %6$s, %7$s %8$s, %9$s</string>
+ <string name="short_format_month">%b</string>
+ <string name="full_wday_month_day_no_year">d, MMMM, EEEE</string>
+ <string name="abbrev_wday_month_day_year">d, MMM, EEE, yyyy</string>
+</resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index d0b3b8a..2dd5a37 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -134,11 +134,15 @@
<string name="power_off" msgid="4266614107412865048">"Spegni"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"Spegnimento..."</string>
<string name="shutdown_confirm" msgid="649792175242821353">"Il telefono verrà spento."</string>
+ <string name="reboot_system">Riavvia</string>
+ <string name="reboot_progress">Riavvio in corso\u2026</string>
+ <string name="reboot_confirm">Il telefono verrà riavviato.</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"Recenti"</string>
<string name="no_recent_tasks" msgid="279702952298056674">"Nessuna applicazione recente."</string>
<string name="global_actions" msgid="2406416831541615258">"Opzioni telefono"</string>
<string name="global_action_lock" msgid="2844945191792119712">"Blocco schermo"</string>
<string name="global_action_power_off" msgid="4471879440839879722">"Spegni"</string>
+ <string name="global_action_reboot">Riavvia</string>
<string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Modalità silenziosa"</string>
<string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Audio non attivo"</string>
<string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Audio attivo"</string>
@@ -861,4 +865,7 @@
<string name="throttle_warning_notification_message" msgid="2609734763845705708">"Tocca per informazioni sull\'utilizzo dati cell."</string>
<string name="throttled_notification_title" msgid="6269541897729781332">"Limite dati cell. superato"</string>
<string name="throttled_notification_message" msgid="4712369856601275146">"Tocca per informazioni sull\'utilizzo dati cell."</string>
+
+ <!-- Reboot recommended after applying color changes (CM) -->
+ <string name="toast_reboot_recommend">Attenzione: Riavvio richiesto dopo aver finito la personalizzazione!</string>
</resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 5816ef7..62cefcc 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -132,13 +132,17 @@
<string name="turn_off_radio" msgid="8198784949987062346">"ワイヤレス接続をOFFにする"</string>
<string name="screen_lock" msgid="799094655496098153">"画面をロック"</string>
<string name="power_off" msgid="4266614107412865048">"電源を切る"</string>
+ <string name="reboot_system">"再起動する"</string>
<string name="shutdown_progress" msgid="2281079257329981203">"シャットダウン中..."</string>
<string name="shutdown_confirm" msgid="649792175242821353">"携帯電話の電源を切ります。"</string>
+ <string name="reboot_progress">"再起動中..."</string>
+ <string name="reboot_confirm">"携帯電話を再起動します。"</string>
<string name="recent_tasks_title" msgid="3691764623638127888">"新着"</string>
<string name="no_recent_tasks" msgid="279702952298056674">"最近使ったアプリケーションはありません。"</string>
<string name="global_actions" msgid="2406416831541615258">"携帯電話オプション"</string>
<string name="global_action_lock" msgid="2844945191792119712">"画面ロック"</string>
<string name="global_action_power_off" msgid="4471879440839879722">"電源を切る"</string>
+ <string name="global_action_reboot">"再起動する"</string>
<string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"マナーモード"</string>
<string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"サウンドOFF"</string>
<string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"サウンドON"</string>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 4672c0e..4ec1f40 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -126,13 +126,14 @@
<item><xliff:g id="id">battery</xliff:g></item>
<item><xliff:g id="id">phone_signal</xliff:g></item>
<item><xliff:g id="id">phone_evdo_signal</xliff:g></item>
+ <item><xliff:g id="id">phone_dbm_signal</xliff:g></item>
<item><xliff:g id="id">data_connection</xliff:g></item>
<item><xliff:g id="id">cdma_eri</xliff:g></item>
+ <item><xliff:g id="id">wifi</xliff:g></item>
<item><xliff:g id="id">tty</xliff:g></item>
<item><xliff:g id="id">volume</xliff:g></item>
<item><xliff:g id="id">mute</xliff:g></item>
<item><xliff:g id="id">speakerphone</xliff:g></item>
- <item><xliff:g id="id">wifi</xliff:g></item>
<item><xliff:g id="id">tty</xliff:g></item>
<item><xliff:g id="id">bluetooth</xliff:g></item>
<item><xliff:g id="id">gps</xliff:g></item>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 088ab44..922defd 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -210,6 +210,12 @@
<item>10</item>
</integer-array>
+ <!-- Vibrator pattern for feedback about on a key release -->
+ <integer-array name="config_virtualKeyUpPattern">
+ <item>5</item>
+ <item>18</item>
+ </integer-array>
+
<bool name="config_use_strict_phone_number_comparation">false</bool>
<!-- Display low battery warning when battery level dips to this value -->
diff --git a/core/res/res/values/donottranslate-cldr.xml b/core/res/res/values/donottranslate-cldr.xml
index a94fb58..6131fbe 100644
--- a/core/res/res/values/donottranslate-cldr.xml
+++ b/core/res/res/values/donottranslate-cldr.xml
@@ -95,6 +95,7 @@
<string name="hour_minute_ampm">%-l:%M%p</string>
<string name="hour_minute_cap_ampm">%-l:%M%^p</string>
<string name="twelve_hour_time_format">h:mm a</string>
+ <string name="twelve_hour_time_format_no_period">h:mm</string>
<string name="twenty_four_hour_time_format">HH:mm</string>
<string name="numeric_date">%-m/%-e/%Y</string>
<string name="numeric_date_format">M/d/yyyy</string>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 86bfe94..776255c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -272,13 +272,21 @@
<string name="screen_lock">Screen lock</string>
<!-- Button to turn off the phone, within the Phone Options dialog -->
<string name="power_off">Power off</string>
+ <!-- Button to reboot the phone, within the Phone Options dialog -->
+ <string name="reboot_system">Reboot phone</string>
<!-- Shutdown Progress Dialog. This is shown if the user chooses to power off the phone. -->
<string name="shutdown_progress">Shutting down\u2026</string>
+ <!-- Reboot Progress Dialog. This is shown if the user chooses to reboot the phone. -->
+ <string name="reboot_progress">Rebooting\u2026</string>
+
<!-- Shutdown Confirmation Dialog. When the user chooses to power off the phone, there will be a confirmation dialog. This is the message. -->
<string name="shutdown_confirm">Your phone will shut down.</string>
+ <!-- Reboot Confirmation Dialog. When the user chooses to reboot the phone, there will be a confirmation dialog. This is the message. -->
+ <string name="reboot_confirm">Your phone will reboot.</string>
+
<!-- Recent Tasks dialog: title -->
<string name="recent_tasks_title">Recent</string>
<!-- Recent Tasks dialog: message when there are no recent applications -->
@@ -293,6 +301,9 @@
<!-- label for item that turns off power in phone options dialog -->
<string name="global_action_power_off">Power off</string>
+ <!-- label for item that reboots the phone in phone options dialog -->
+ <string name="global_action_reboot">Reboot</string>
+
<!-- label for item that enables silent mode in phone options dialog -->
<string name="global_action_toggle_silent_mode">Silent mode</string>
@@ -2235,6 +2246,7 @@
<string name="l2tp_vpn_description">Layer 2 Tunneling Protocol</string>
<string name="l2tp_ipsec_psk_vpn_description">Pre-shared key based L2TP/IPSec VPN</string>
<string name="l2tp_ipsec_crt_vpn_description">Certificate based L2TP/IPSec VPN</string>
+ <string name="openvpn_vpn_description">OpenVPN SSL VPN</string>
<!-- Localized strings for WebView -->
<!-- Label for button in a WebView that will open a chooser to choose a file to upload -->
@@ -2269,4 +2281,7 @@
<!-- Shown when the users bandwidth is reduced because of excessive data use -->
<string name="throttled_notification_title">Mobile data limit exceeded</string>
<string name="throttled_notification_message">Touch to learn more about mobile data use</string>
+
+ <!-- Reboot recommended after applying color changes (CM) -->
+ <string name="toast_reboot_recommend">Caution: Reboot recommended after finishing customization!</string>
</resources>
diff --git a/core/tests/coretests/src/android/preference/ListPreferenceTest.java b/core/tests/coretests/src/android/preference/ListPreferenceTest.java
new file mode 100644
index 0000000..41f8e03
--- /dev/null
+++ b/core/tests/coretests/src/android/preference/ListPreferenceTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.preference;
+
+import android.preference.ListPreference;
+import android.test.AndroidTestCase;
+
+public class ListPreferenceTest extends AndroidTestCase {
+ public void testListPreferenceSummaryFromEntries() {
+ String[] entries = { "one", "two", "three" };
+ String[] entryValues = { "1" , "2", "3" };
+ ListPreference lp = new ListPreference(getContext());
+ lp.setEntries(entries);
+ lp.setEntryValues(entryValues);
+
+ lp.setValue(entryValues[1]);
+ assertTrue(lp.getSummary() == null);
+
+ lp.setSummary("%1$s");
+ assertEquals(entries[1], lp.getSummary());
+
+ lp.setValue(entryValues[2]);
+ assertEquals(entries[2], lp.getSummary());
+
+ lp.setSummary(null);
+ assertTrue(lp.getSummary() == null);
+
+ lp.setSummary("The color is %1$s");
+ assertEquals("The color is " + entries[2], lp.getSummary());
+ }
+}
diff --git a/docs/html/resources/articles/painless-threading.jd b/docs/html/resources/articles/painless-threading.jd
index 921f4df..17cec35 100644
--- a/docs/html/resources/articles/painless-threading.jd
+++ b/docs/html/resources/articles/painless-threading.jd
@@ -108,7 +108,7 @@ you. Our previous example can easily be rewritten with
new DownloadImageTask().execute("http://example.com/image.png");
}
-private class DownloadImageTask extends AsyncTask&lt;string, void,="" bitmap=""&gt; {
+private class DownloadImageTask extends AsyncTask&lt;String, Void, Bitmap&gt; {
protected Bitmap doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 345f810..061b55f 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -34,7 +34,9 @@ import javax.microedition.khronos.opengles.GL;
public class Canvas {
// assigned in constructors, freed in finalizer
final int mNativeCanvas;
-
+ private static final char FIRST_RIGHT_TO_LEFT = '\u0590';
+ private static final char LAST_RIGHT_TO_LEFT = '\u07b1';
+
/* Our native canvas can be either a raster, gl, or picture canvas.
If we are raster, then mGL will be null, and mBitmap may or may not be
present (our default constructor creates a raster canvas but no
@@ -44,7 +46,7 @@ public class Canvas {
*/
private Bitmap mBitmap; // if not null, mGL must be null
private GL mGL; // if not null, mBitmap must be null
-
+
// optional field set by the caller
private DrawFilter mDrawFilter;
@@ -53,7 +55,7 @@ public class Canvas {
// Used to determine when compatibility scaling is in effect.
private int mScreenDensity = Bitmap.DENSITY_NONE;
-
+
// Used by native code
@SuppressWarnings({"UnusedDeclaration"})
private int mSurfaceFormat;
@@ -72,7 +74,7 @@ public class Canvas {
/**
* Construct a canvas with the specified bitmap to draw into. The bitmap
* must be mutable.
- *
+ *
* <p>The initial target density of the canvas is the same as the given
* bitmap's density.
*
@@ -88,7 +90,7 @@ public class Canvas {
mBitmap = bitmap;
mDensity = bitmap.mDensity;
}
-
+
/*package*/ Canvas(int nativeCanvas) {
if (nativeCanvas == 0) {
throw new IllegalStateException();
@@ -96,14 +98,14 @@ public class Canvas {
mNativeCanvas = nativeCanvas;
mDensity = Bitmap.getDefaultDensity();
}
-
+
/**
* Construct a canvas with the specified gl context. All drawing through
* this canvas will be redirected to OpenGL. Note: some features may not
* be supported in this mode (e.g. some GL implementations may not support
* antialiasing or certain effects like ColorMatrix or certain Xfermodes).
* However, no exception will be thrown in those cases.
- *
+ *
* <p>The initial target density of the canvas is the same as the initial
* density of bitmaps as per {@link Bitmap#getDensity() Bitmap.getDensity()}.
*/
@@ -112,7 +114,7 @@ public class Canvas {
mGL = gl;
mDensity = Bitmap.getDefaultDensity();
}
-
+
/**
* Return the GL object associated with this canvas, or null if it is not
* backed by GL.
@@ -120,7 +122,7 @@ public class Canvas {
public GL getGL() {
return mGL;
}
-
+
/**
* Call this to free up OpenGL resources that may be cached or allocated
* on behalf of the Canvas. Any subsequent drawing with a GL-backed Canvas
@@ -129,13 +131,13 @@ public class Canvas {
public static void freeGlCaches() {
freeCaches();
}
-
+
/**
* Specify a bitmap for the canvas to draw into. As a side-effect, also
* updates the canvas's target density to match that of the bitmap.
*
* @param bitmap Specifies a mutable bitmap for the canvas to draw into.
- *
+ *
* @see #setDensity(int)
* @see #getDensity()
*/
@@ -152,7 +154,7 @@ public class Canvas {
mBitmap = bitmap;
mDensity = bitmap.mDensity;
}
-
+
/**
* Set the viewport dimensions if this canvas is GL based. If it is not,
* this method is ignored and no exception is thrown.
@@ -197,7 +199,7 @@ public class Canvas {
* to determine the scaling factor when drawing a bitmap into it.
*
* @see #setDensity(int)
- * @see Bitmap#getDensity()
+ * @see Bitmap#getDensity()
*/
public int getDensity() {
return mDensity;
@@ -213,7 +215,7 @@ public class Canvas {
* {@link Bitmap#DENSITY_NONE} to disable bitmap scaling.
*
* @see #getDensity()
- * @see Bitmap#setDensity(int)
+ * @see Bitmap#setDensity(int)
*/
public void setDensity(int density) {
if (mBitmap != null) {
@@ -226,7 +228,7 @@ public class Canvas {
public void setScreenDensity(int density) {
mScreenDensity = density;
}
-
+
// the SAVE_FLAG constants must match their native equivalents
/** restore the current matrix when restore() is called */
@@ -240,8 +242,8 @@ public class Canvas {
/** clip against the layer's bounds */
public static final int CLIP_TO_LAYER_SAVE_FLAG = 0x10;
/** restore everything when restore() is called */
- public static final int ALL_SAVE_FLAG = 0x1F;
-
+ public static final int ALL_SAVE_FLAG = 0x1F;
+
/**
* Saves the current matrix and clip onto a private stack. Subsequent
* calls to translate,scale,rotate,skew,concat or clipRect,clipPath
@@ -252,7 +254,7 @@ public class Canvas {
* @return The value to pass to restoreToCount() to balance this save()
*/
public native int save();
-
+
/**
* Based on saveFlags, can save the current matrix and clip onto a private
* stack. Subsequent calls to translate,scale,rotate,skew,concat or
@@ -287,7 +289,7 @@ public class Canvas {
paint != null ? paint.mNativePaint : 0,
saveFlags);
}
-
+
/**
* Helper version of saveLayer() that takes 4 values rather than a RectF.
*/
@@ -318,7 +320,7 @@ public class Canvas {
alpha = Math.min(255, Math.max(0, alpha));
return native_saveLayerAlpha(mNativeCanvas, bounds, alpha, saveFlags);
}
-
+
/**
* Helper for saveLayerAlpha() that takes 4 values instead of a RectF.
*/
@@ -422,7 +424,7 @@ public class Canvas {
public void concat(Matrix matrix) {
native_concat(mNativeCanvas, matrix.native_instance);
}
-
+
/**
* Completely replace the current matrix with the specified matrix. If the
* matrix parameter is null, then the current matrix is reset to identity.
@@ -434,7 +436,7 @@ public class Canvas {
native_setMatrix(mNativeCanvas,
matrix == null ? 0 : matrix.native_instance);
}
-
+
/**
* Return, in ctm, the current transformation matrix. This does not alter
* the matrix in the canvas, but just returns a copy of it.
@@ -442,7 +444,7 @@ public class Canvas {
public void getMatrix(Matrix ctm) {
native_getCTM(mNativeCanvas, ctm.native_instance);
}
-
+
/**
* Return a new matrix with a copy of the canvas' current transformation
* matrix.
@@ -452,7 +454,7 @@ public class Canvas {
getMatrix(m);
return m;
}
-
+
/**
* Modify the current clip with the specified rectangle.
*
@@ -488,7 +490,7 @@ public class Canvas {
* @return true if the resulting clip is non-empty
*/
public native boolean clipRect(RectF rect);
-
+
/**
* Intersect the current clip with the specified rectangle, which is
* expressed in local coordinates.
@@ -497,7 +499,7 @@ public class Canvas {
* @return true if the resulting clip is non-empty
*/
public native boolean clipRect(Rect rect);
-
+
/**
* Modify the current clip with the specified rectangle, which is
* expressed in local coordinates.
@@ -534,7 +536,7 @@ public class Canvas {
*/
public native boolean clipRect(float left, float top,
float right, float bottom);
-
+
/**
* Intersect the current clip with the specified rectangle, which is
* expressed in local coordinates.
@@ -550,7 +552,7 @@ public class Canvas {
*/
public native boolean clipRect(int left, int top,
int right, int bottom);
-
+
/**
* Modify the current clip with the specified path.
*
@@ -561,7 +563,7 @@ public class Canvas {
public boolean clipPath(Path path, Region.Op op) {
return native_clipPath(mNativeCanvas, path.ni(), op.nativeInt);
}
-
+
/**
* Intersect the current clip with the specified path.
*
@@ -571,7 +573,7 @@ public class Canvas {
public boolean clipPath(Path path) {
return clipPath(path, Region.Op.INTERSECT);
}
-
+
/**
* Modify the current clip with the specified region. Note that unlike
* clipRect() and clipPath() which transform their arguments by the
@@ -600,11 +602,11 @@ public class Canvas {
public boolean clipRegion(Region region) {
return clipRegion(region, Region.Op.INTERSECT);
}
-
+
public DrawFilter getDrawFilter() {
return mDrawFilter;
}
-
+
public void setDrawFilter(DrawFilter filter) {
int nativeFilter = 0;
if (filter != null) {
@@ -617,7 +619,7 @@ public class Canvas {
public enum EdgeType {
BW(0), //!< treat edges by just rounding to nearest pixel boundary
AA(1); //!< treat edges by rounding-out, since they may be antialiased
-
+
EdgeType(int nativeInt) {
this.nativeInt = nativeInt;
}
@@ -695,7 +697,7 @@ public class Canvas {
public boolean getClipBounds(Rect bounds) {
return native_getClipBounds(mNativeCanvas, bounds);
}
-
+
/**
* Retrieve the clip bounds.
*
@@ -706,7 +708,7 @@ public class Canvas {
getClipBounds(r);
return r;
}
-
+
/**
* Fill the entire canvas' bitmap (restricted to the current clip) with the
* specified RGB color, using srcover porterduff mode.
@@ -763,7 +765,7 @@ public class Canvas {
public void drawPaint(Paint paint) {
native_drawPaint(mNativeCanvas, paint.mNativePaint);
}
-
+
/**
* Draw a series of points. Each point is centered at the coordinate
* specified by pts[], and its diameter is specified by the paint's stroke
@@ -853,7 +855,7 @@ public class Canvas {
public void drawRect(Rect r, Paint paint) {
drawRect(r.left, r.top, r.right, r.bottom, paint);
}
-
+
/**
* Draw the specified Rect using the specified paint. The rectangle will
@@ -949,7 +951,7 @@ public class Canvas {
public void drawPath(Path path, Paint paint) {
native_drawPath(mNativeCanvas, path.ni(), paint.mNativePaint);
}
-
+
private static void throwIfRecycled(Bitmap bitmap) {
if (bitmap.isRecycled()) {
throw new RuntimeException(
@@ -960,7 +962,7 @@ public class Canvas {
/**
* Draw the specified bitmap, with its top/left corner at (x,y), using
* the specified paint, transformed by the current matrix.
- *
+ *
* <p>Note: if the paint contains a maskfilter that generates a mask which
* extends beyond the bitmap's original width/height (e.g. BlurMaskFilter),
* then the bitmap will be drawn as if it were in a Shader with CLAMP mode.
@@ -970,7 +972,7 @@ public class Canvas {
* <p>If the bitmap and canvas have different densities, this function
* will take care of automatically scaling the bitmap to draw at the
* same density as the canvas.
- *
+ *
* @param bitmap The bitmap to be drawn
* @param left The position of the left side of the bitmap being drawn
* @param top The position of the top side of the bitmap being drawn
@@ -987,7 +989,7 @@ public class Canvas {
* Draw the specified bitmap, scaling/translating automatically to fill
* the destination rectangle. If the source rectangle is not null, it
* specifies the subset of the bitmap to draw.
- *
+ *
* <p>Note: if the paint contains a maskfilter that generates a mask which
* extends beyond the bitmap's original width/height (e.g. BlurMaskFilter),
* then the bitmap will be drawn as if it were in a Shader with CLAMP mode.
@@ -998,7 +1000,7 @@ public class Canvas {
* This is because the source and destination rectangle coordinate
* spaces are in their respective densities, so must already have the
* appropriate scaling factor applied.
- *
+ *
* @param bitmap The bitmap to be drawn
* @param src May be null. The subset of the bitmap to be drawn
* @param dst The rectangle that the bitmap will be scaled/translated
@@ -1019,7 +1021,7 @@ public class Canvas {
* Draw the specified bitmap, scaling/translating automatically to fill
* the destination rectangle. If the source rectangle is not null, it
* specifies the subset of the bitmap to draw.
- *
+ *
* <p>Note: if the paint contains a maskfilter that generates a mask which
* extends beyond the bitmap's original width/height (e.g. BlurMaskFilter),
* then the bitmap will be drawn as if it were in a Shader with CLAMP mode.
@@ -1030,7 +1032,7 @@ public class Canvas {
* This is because the source and destination rectangle coordinate
* spaces are in their respective densities, so must already have the
* appropriate scaling factor applied.
- *
+ *
* @param bitmap The bitmap to be drawn
* @param src May be null. The subset of the bitmap to be drawn
* @param dst The rectangle that the bitmap will be scaled/translated
@@ -1046,7 +1048,7 @@ public class Canvas {
paint != null ? paint.mNativePaint : 0,
mScreenDensity, bitmap.mDensity);
}
-
+
/**
* Treat the specified array of colors as a bitmap, and draw it. This gives
* the same result as first creating a bitmap from the array, and then
@@ -1093,7 +1095,7 @@ public class Canvas {
native_drawBitmap(mNativeCanvas, colors, offset, stride, x, y, width, height, hasAlpha,
paint != null ? paint.mNativePaint : 0);
}
-
+
/** Legacy version of drawBitmap(int[] colors, ...) that took ints for x,y
*/
public void drawBitmap(int[] colors, int offset, int stride, int x, int y,
@@ -1103,7 +1105,7 @@ public class Canvas {
drawBitmap(colors, offset, stride, (float)x, (float)y, width, height,
hasAlpha, paint);
}
-
+
/**
* Draw the bitmap using the specified matrix.
*
@@ -1115,13 +1117,13 @@ public class Canvas {
nativeDrawBitmapMatrix(mNativeCanvas, bitmap.ni(), matrix.ni(),
paint != null ? paint.mNativePaint : 0);
}
-
+
private static void checkRange(int length, int offset, int count) {
if ((offset | count) < 0 || offset + count > length) {
throw new ArrayIndexOutOfBoundsException();
}
}
-
+
/**
* Draw the bitmap through the mesh, where mesh vertices are evenly
* distributed across the bitmap. There are meshWidth+1 vertices across, and
@@ -1168,18 +1170,18 @@ public class Canvas {
verts, vertOffset, colors, colorOffset,
paint != null ? paint.mNativePaint : 0);
}
-
+
public enum VertexMode {
TRIANGLES(0),
TRIANGLE_STRIP(1),
TRIANGLE_FAN(2);
-
+
VertexMode(int nativeInt) {
this.nativeInt = nativeInt;
}
final int nativeInt;
}
-
+
/**
* Draw the array of vertices, interpreted as triangles (based on mode). The
* verts array is required, and specifies the x,y pairs for each vertex. If
@@ -1208,7 +1210,7 @@ public class Canvas {
* @param indices If not null, array of indices to reference into the
* vertex (texs, colors) array.
* @param indexCount number of entries in the indices array (if not null).
- * @param paint Specifies the shader to use if the texs array is non-null.
+ * @param paint Specifies the shader to use if the texs array is non-null.
*/
public void drawVertices(VertexMode mode, int vertexCount,
float[] verts, int vertOffset,
@@ -1230,7 +1232,131 @@ public class Canvas {
vertOffset, texs, texOffset, colors, colorOffset,
indices, indexOffset, indexCount, paint.mNativePaint);
}
-
+
+ /** @hide */
+ public char[] bidiProcess(char[] text,int start,int src_count) {
+ String str;
+ String oldstr=new String(text,start,src_count);
+ boolean hasbidi=false;
+ int strlen=oldstr.length();
+ char[] ca=new char[strlen];
+
+ oldstr.getChars(0, strlen, ca, 0);
+ for (int i=0;i<oldstr.length();i++){
+ if (ca[i]>=FIRST_RIGHT_TO_LEFT&&ca[i]<=LAST_RIGHT_TO_LEFT){
+ hasbidi=true;
+ break;
+ }
+ }
+ if (hasbidi) {
+ char[] ca2=new char[strlen];
+ int count=0,srcindex=0;
+ boolean rtlmode=true;
+ for (int i=0;i<strlen;i++){
+ srcindex=strlen-1-i;
+ if (ca[srcindex]>=FIRST_RIGHT_TO_LEFT&&ca[srcindex]<=LAST_RIGHT_TO_LEFT){
+ ca2[i]=ca[srcindex];
+ rtlmode=true;
+ }
+ else {
+ srcindex=strlen-1-i;
+ if (count==0) {
+ if (ca[srcindex]<='\u002f' ||
+ (ca[srcindex]>'\u0039' && ca[srcindex]<='\u0040') ||
+ (ca[srcindex]>'\u005a' && ca[srcindex]<='\u0060')||
+ (ca[srcindex]>'\u007a' && ca[srcindex]<='\u00BF')) {
+
+ if (rtlmode){
+ switch (ca[srcindex]) {
+ case '[':
+ ca2[i]=']';
+ break;
+ case ']':
+ ca2[i]='[';
+ break;
+ case '}':
+ ca2[i]='{';
+ break;
+ case '{':
+ ca2[i]='}';
+ break;
+ case '(':
+ ca2[i]=')';
+ break;
+ case ')':
+ ca2[i]='(';
+ break;
+ case '>':
+ ca2[i]='<';
+ break;
+ case '<':
+ ca2[i]='>';
+ break;
+ default:
+ ca2[i]=ca[srcindex];
+ break;
+ }
+ } else ca2[i]=ca[srcindex];
+ } else {
+
+ while (((srcindex-count)>=0)&&((ca[srcindex-count]<FIRST_RIGHT_TO_LEFT)||(ca[srcindex-count]>LAST_RIGHT_TO_LEFT))){
+ count++;
+ }
+ int index=0;
+ int punctuation_marks=0;
+
+ while (count>0 && (srcindex-(count)>=0) &&
+ (ca[srcindex-(count-1)]<='\u002f' ||
+ (ca[srcindex-(count-1)]>'\u0039' && ca[srcindex-(count-1)]<='\u0040') ||
+ (ca[srcindex-(count-1)]>'\u005a' && ca[srcindex-(count-1)]<='\u0060')||
+ (ca[srcindex-(count-1)]>'\u007a' && ca[srcindex-(count-1)]<='\u00BF'))){
+ ca2[i+(count-1)]=ca[srcindex-(count-1)];
+ count--;
+ punctuation_marks++;
+ }
+
+ while (count>0){
+ ca2[i+index]=ca[srcindex-(count-1)];
+ count--;
+ index++;
+ }
+ count=index+punctuation_marks-1;
+ }
+ }
+ else {
+ count--;
+ }
+ rtlmode=false;
+ }
+ }
+ str=new String(ca2);
+ } else
+ {
+ str=new String(oldstr);
+ }
+ return str.toCharArray();
+
+ }
+
+ /** @hide **/
+ public void drawText(char[] text, int index, int count, float x, float y,
+ Paint paint,boolean bidi) {
+ if ((index | count | (index + count) |
+ (text.length - index - count)) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (bidi) {
+ char[] bidiText;
+ bidiText=bidiProcess(text,index,count);
+ native_drawText(mNativeCanvas, bidiText, 0, count, x, y,
+ paint.mNativePaint);
+ } else {
+ native_drawText(mNativeCanvas, text, index, count, x, y,
+ paint.mNativePaint);
+ }
+ }
+
/**
* Draw the text, with origin at (x,y), using the specified paint. The
* origin is interpreted based on the Align setting in the paint.
@@ -1246,7 +1372,10 @@ public class Canvas {
(text.length - index - count)) < 0) {
throw new IndexOutOfBoundsException();
}
- native_drawText(mNativeCanvas, text, index, count, x, y,
+
+ char[] bidiText;
+ bidiText=bidiProcess(text,index,count);
+ native_drawText(mNativeCanvas, bidiText, 0, count, x, y,
paint.mNativePaint);
}
@@ -1259,7 +1388,23 @@ public class Canvas {
* @param y The y-coordinate of the origin of the text being drawn
* @param paint The paint used for the text (e.g. color, size, style)
*/
- public native void drawText(String text, float x, float y, Paint paint);
+ private native void native_drawText(String text, float x, float y, Paint paint);
+
+ /** @hide */
+ public void drawText(String text, float x, float y, Paint paint,boolean bidi){
+ if (!bidi) {
+ native_drawText(text,x,y,paint);
+ } else {
+ if (text.length() > 0) {
+ String bidiText;
+ bidiText=new String(bidiProcess(text.toCharArray(),0,text.length()));
+ native_drawText(bidiText,x,y,paint);
+ }
+ }
+ }
+ public void drawText(String text, float x, float y, Paint paint){
+ drawText(text,x,y,paint,true);
+ }
/**
* Draw the text, with origin at (x,y), using the specified paint.
@@ -1277,7 +1422,10 @@ public class Canvas {
if ((start | end | (end - start) | (text.length() - end)) < 0) {
throw new IndexOutOfBoundsException();
}
- native_drawText(mNativeCanvas, text, start, end, x, y,
+ int i = 0;
+ String bidiText;
+ bidiText=new String(bidiProcess(text.toCharArray(),start,end-start));
+ native_drawText(mNativeCanvas, bidiText, i, end-start, x, y,
paint.mNativePaint);
}
@@ -1298,8 +1446,10 @@ public class Canvas {
float y, Paint paint) {
if (text instanceof String || text instanceof SpannedString ||
text instanceof SpannableString) {
- native_drawText(mNativeCanvas, text.toString(), start, end, x, y,
- paint.mNativePaint);
+ String bidiText;
+ bidiText=new String(bidiProcess(text.toString().toCharArray(),start,end-start));
+ native_drawText(mNativeCanvas, bidiText.toString(), 0, end-start, x, y,
+ paint.mNativePaint);
}
else if (text instanceof GraphicsOperations) {
((GraphicsOperations) text).drawText(this, start, end, x, y,
@@ -1308,11 +1458,38 @@ public class Canvas {
else {
char[] buf = TemporaryBuffer.obtain(end - start);
TextUtils.getChars(text, start, end, buf, 0);
- drawText(buf, 0, end - start, x, y, paint);
+ drawText(buf, 0, end - start, x, y, paint,false);
TemporaryBuffer.recycle(buf);
}
}
+ /** @hide */
+ public void drawText(CharSequence text, int start, int end, float x,
+ float y, Paint paint,boolean bidi) {
+ if (text instanceof String || text instanceof SpannedString ||
+ text instanceof SpannableString) {
+ if (bidi) {
+ String bidiText;
+ bidiText=new String(bidiProcess(text.toString().toCharArray(),start,end-start));
+ native_drawText(mNativeCanvas, bidiText.toString(), 0, end-start, x, y,
+ paint.mNativePaint);
+ } else {
+ native_drawText(mNativeCanvas, text.toString(), start, end, x, y,
+ paint.mNativePaint);
+ }
+ }
+ else if (text instanceof GraphicsOperations) {
+ ((GraphicsOperations) text).drawText(this, start, end, x, y,
+ paint);
+ }
+ else {
+ char[] buf = TemporaryBuffer.obtain(end - start);
+ TextUtils.getChars(text, start, end, buf, 0);
+ drawText(buf, 0, end - start, x, y, paint,false);
+ TemporaryBuffer.recycle(buf);
+ }
+ }
+
/**
* Draw the text in the array, with each character's origin specified by
* the pos array.
@@ -1329,8 +1506,12 @@ public class Canvas {
if (index < 0 || index + count > text.length || count*2 > pos.length) {
throw new IndexOutOfBoundsException();
}
- native_drawPosText(mNativeCanvas, text, index, count, pos,
+
+ char[] bidiText;
+ bidiText=bidiProcess(text,index,count);
+ native_drawPosText(mNativeCanvas, bidiText, 0, count, pos,
paint.mNativePaint);
+ // TODO: handle starting from higher index
}
/**
@@ -1345,7 +1526,10 @@ public class Canvas {
if (text.length()*2 > pos.length) {
throw new ArrayIndexOutOfBoundsException();
}
- native_drawPosText(mNativeCanvas, text, pos, paint.mNativePaint);
+
+ String bidiText;
+ bidiText=new String(bidiProcess(text.toCharArray(),0,text.length()));
+ native_drawPosText(mNativeCanvas, bidiText, pos, paint.mNativePaint);
}
/**
@@ -1366,7 +1550,10 @@ public class Canvas {
if (index < 0 || index + count > text.length) {
throw new ArrayIndexOutOfBoundsException();
}
- native_drawTextOnPath(mNativeCanvas, text, index, count,
+ int i = 0;
+ char[] bidiText;
+ bidiText=bidiProcess(text,index,count);
+ native_drawTextOnPath(mNativeCanvas, bidiText, i, count,
path.ni(), hOffset, vOffset,
paint.mNativePaint);
}
@@ -1387,7 +1574,10 @@ public class Canvas {
public void drawTextOnPath(String text, Path path, float hOffset,
float vOffset, Paint paint) {
if (text.length() > 0) {
- native_drawTextOnPath(mNativeCanvas, text, path.ni(),
+ int i = 0;
+ String bidiText;
+ bidiText=new String(bidiProcess(text.toCharArray(),0,text.length()));
+ native_drawTextOnPath(mNativeCanvas, bidiText, path.ni(),
hOffset, vOffset, paint.mNativePaint);
}
}
@@ -1396,14 +1586,14 @@ public class Canvas {
* Save the canvas state, draw the picture, and restore the canvas state.
* This differs from picture.draw(canvas), which does not perform any
* save/restore.
- *
+ *
* @param picture The picture to be drawn
*/
public void drawPicture(Picture picture) {
picture.endRecording();
native_drawPicture(mNativeCanvas, picture.ni());
}
-
+
/**
* Draw the picture, stretched to fit into the dst rectangle.
*/
@@ -1417,7 +1607,7 @@ public class Canvas {
drawPicture(picture);
restore();
}
-
+
/**
* Draw the picture, stretched to fit into the dst rectangle.
*/
@@ -1431,7 +1621,7 @@ public class Canvas {
drawPicture(picture);
restore();
}
-
+
protected void finalize() throws Throwable {
super.finalize();
// If the constructor threw an exception before setting mNativeCanvas, the native finalizer
@@ -1552,7 +1742,7 @@ public class Canvas {
float[] verts, int vertOffset, float[] texs, int texOffset,
int[] colors, int colorOffset, short[] indices,
int indexOffset, int indexCount, int nPaint);
-
+
private static native void native_drawText(int nativeCanvas, char[] text,
int index, int count, float x,
float y, int paint);
diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java
index 5cefaa3..26aecba 100644
--- a/graphics/java/android/graphics/Color.java
+++ b/graphics/java/android/graphics/Color.java
@@ -202,7 +202,7 @@ public class Color {
* 'yellow', 'lightgray', 'darkgray'
*/
public static int parseColor(String colorString) {
- if (colorString.charAt(0) == '#') {
+ if (colorString.startsWith("#")) {
// Use a long to avoid rollovers on #ffXXXXXX
long color = Long.parseLong(colorString.substring(1), 16);
if (colorString.length() == 7) {
diff --git a/graphics/jni/Android.mk b/graphics/jni/Android.mk
index 8476be1..13ee169 100644
--- a/graphics/jni/Android.mk
+++ b/graphics/jni/Android.mk
@@ -19,8 +19,12 @@ LOCAL_SHARED_LIBRARIES := \
libcutils \
libskia \
libutils \
- libui \
- libsurfaceflinger_client
+ libui
+
+ifneq ($(BOARD_USES_ECLAIR_LIBCAMERA),true)
+ LOCAL_SHARED_LIBRARIES += \
+ libsurfaceflinger_client
+endif
LOCAL_STATIC_LIBRARIES :=
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index 5ea83a5..dde56a9 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -25,6 +25,12 @@ namespace android {
class CameraParameters
{
public:
+ enum {
+ CAMERA_ORIENTATION_UNKNOWN = 0,
+ CAMERA_ORIENTATION_PORTRAIT = 1,
+ CAMERA_ORIENTATION_LANDSCAPE = 2,
+ };
+
CameraParameters();
CameraParameters(const String8 &params) { unflatten(params); }
~CameraParameters();
@@ -52,6 +58,9 @@ public:
void setPictureFormat(const char *format);
const char *getPictureFormat() const;
+ int getOrientation() const;
+ void setOrientation(int orientation);
+
void dump() const;
status_t dump(int fd, const Vector<String16>& args) const;
@@ -95,6 +104,10 @@ public:
// The height (in pixels) of EXIF thumbnail in Jpeg picture.
// Example value: "384". Read/write.
static const char KEY_JPEG_THUMBNAIL_HEIGHT[];
+
+ //++TODO is the following parameter is needed when jpeg thumbnail is available
+ static const char KEY_SUPPORTED_THUMBNAIL_SIZES[];
+
// Supported EXIF thumbnail sizes (width x height). 0x0 means not thumbnail
// in EXIF.
// Example value: "512x384,320x240,0x0". Read only.
@@ -128,6 +141,33 @@ public:
// GPS altitude. This will be stored in JPEG EXIF header.
// Example value: "21.0". Write only.
static const char KEY_GPS_ALTITUDE[];
+
+ static const char KEY_GPS_LATITUDE_REF[];
+ static const char KEY_GPS_LONGITUDE_REF[];
+ static const char KEY_GPS_ALTITUDE_REF[];
+ static const char KEY_GPS_STATUS[];
+ static const char KEY_EXIF_DATETIME[];
+
+ static const char KEY_AUTO_EXPOSURE[];
+ static const char KEY_SUPPORTED_AUTO_EXPOSURE[];
+ static const char KEY_ISO_MODE[];
+ static const char KEY_SUPPORTED_ISO_MODES[];
+ static const char KEY_LENSSHADE[] ;
+ static const char KEY_SUPPORTED_LENSSHADE_MODES[] ;
+ static const char KEY_SHARPNESS[];
+ static const char KEY_MAX_SHARPNESS[];
+ static const char KEY_CONTRAST[];
+ static const char KEY_MAX_CONTRAST[];
+ static const char KEY_SATURATION[];
+ static const char KEY_MAX_SATURATION[];
+
+ // Values for auto exposure settings.
+ static const char AUTO_EXPOSURE_FRAME_AVG[];
+ static const char AUTO_EXPOSURE_CENTER_WEIGHTED[];
+ static const char AUTO_EXPOSURE_SPOT_METERING[];
+
+
+
// GPS timestamp (UTC in seconds since January 1, 1970). This should be
// stored in JPEG EXIF header.
// Example value: "1251192757". Write only.
@@ -292,6 +332,7 @@ public:
static const char PIXEL_FORMAT_YUV422I[]; // YUY2
static const char PIXEL_FORMAT_RGB565[];
static const char PIXEL_FORMAT_JPEG[];
+ static const char PIXEL_FORMAT_RAW[];
// Values for focus mode settings.
// Auto-focus mode.
@@ -299,6 +340,7 @@ public:
// Focus is set at infinity. Applications should not call
// CameraHardwareInterface.autoFocus in this mode.
static const char FOCUS_MODE_INFINITY[];
+ static const char FOCUS_MODE_NORMAL[];
static const char FOCUS_MODE_MACRO[];
// Focus is fixed. The camera is always in this mode if the focus is not
// adjustable. If the camera has auto-focus, this mode can fix the
@@ -310,6 +352,16 @@ public:
// CameraHardwareInterface.autoFocus in this mode.
static const char FOCUS_MODE_EDOF[];
+ static const char ISO_AUTO[];
+ static const char ISO_HJR[] ;
+ static const char ISO_100[];
+ static const char ISO_200[] ;
+ static const char ISO_400[];
+ static const char ISO_800[];
+ static const char ISO_1600[];
+ // Values for Lens Shading
+ static const char LENSSHADE_ENABLE[] ;
+ static const char LENSSHADE_DISABLE[] ;
private:
DefaultKeyedVector<String8,String8> mMap;
};
@@ -317,3 +369,4 @@ private:
}; // namespace android
#endif
+
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 92bc126..18347d5 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -129,9 +129,9 @@ public:
*/
enum record_flags {
- RECORD_AGC_ENABLE = AudioSystem::AGC_ENABLE,
- RECORD_NS_ENABLE = AudioSystem::NS_ENABLE,
- RECORD_IIR_ENABLE = AudioSystem::TX_IIR_ENABLE
+ RECORD_AGC_ENABLE = 0x0001, // AudioSystem::AGC_ENABLE,
+ RECORD_NS_ENABLE = 0x0002, // AudioSystem::NS_ENABLE,
+ RECORD_IIR_ENABLE = 0x0004, // AudioSystem::TX_IIR_ENABLE
};
AudioRecord(int inputSource,
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 9e606d9..a50ce35 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -45,6 +45,7 @@ enum player_type {
// The shared library with the test player is passed passed as an
// argument to the 'test:' url in the setDataSource call.
TEST_PLAYER = 5,
+ FLAC_PLAYER = 6,
};
diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h
index a4eea2a..5354937 100644
--- a/include/media/MediaProfiles.h
+++ b/include/media/MediaProfiles.h
@@ -24,8 +24,9 @@
namespace android {
enum camcorder_quality {
- CAMCORDER_QUALITY_LOW = 0,
- CAMCORDER_QUALITY_HIGH = 1
+ CAMCORDER_QUALITY_LOW = 0,
+ CAMCORDER_QUALITY_HIGH = 1,
+ CAMCORDER_QUALITY_FRONT = 2
};
enum video_decoder {
diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h
index 3b18c77..3896485 100644
--- a/include/ui/EventHub.h
+++ b/include/ui/EventHub.h
@@ -57,7 +57,8 @@ public:
CLASS_TOUCHSCREEN = 0x00000004,
CLASS_TRACKBALL = 0x00000008,
CLASS_TOUCHSCREEN_MT= 0x00000010,
- CLASS_DPAD = 0x00000020
+ CLASS_DPAD = 0x00000020,
+ CLASS_MOUSE = 0x00000040
};
uint32_t getDeviceClasses(int32_t deviceId) const;
diff --git a/include/ui/Overlay.h b/include/ui/Overlay.h
index a9ae1c4..9156e80 100644
--- a/include/ui/Overlay.h
+++ b/include/ui/Overlay.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -91,6 +92,7 @@ public:
/* set the buffer attributes */
status_t setParameter(int param, int value);
+ status_t setFd(int fd);
/* returns the address of a given buffer if supported, NULL otherwise. */
void* getBufferAddress(overlay_buffer_t buffer);
diff --git a/include/utils/Asset.h b/include/utils/Asset.h
index 5908bcc..b2697d4 100644
--- a/include/utils/Asset.h
+++ b/include/utils/Asset.h
@@ -63,11 +63,7 @@ public:
enum {
/* data larger than this does not get uncompressed into a buffer */
-#ifdef HAVE_ANDROID_OS
- UNCOMPRESS_DATA_MAX = 1 * 1024 * 1024
-#else
- UNCOMPRESS_DATA_MAX = 2 * 1024 * 1024
-#endif
+ UNCOMPRESS_DATA_MAX = 3 * 1024 * 1024
};
/*
diff --git a/libs/camera/Android.mk b/libs/camera/Android.mk
index 03ff229..3691bde 100644
--- a/libs/camera/Android.mk
+++ b/libs/camera/Android.mk
@@ -8,6 +8,10 @@ LOCAL_SRC_FILES:= \
ICameraClient.cpp \
ICameraService.cpp
+LOCAL_MODULE:= libcamera_client
+
+ifneq ($(BOARD_USES_ECLAIR_LIBCAMERA),true)
+
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
@@ -16,10 +20,14 @@ LOCAL_SHARED_LIBRARIES := \
libsurfaceflinger_client \
libui
-LOCAL_MODULE:= libcamera_client
-
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_LDLIBS += -lpthread
endif
include $(BUILD_SHARED_LIBRARY)
+
+else
+
+include $(BUILD_STATIC_LIBRARY)
+
+endif
diff --git a/libs/camera/CameraParameters.cpp b/libs/camera/CameraParameters.cpp
index 65fd7ac..2458213 100644
--- a/libs/camera/CameraParameters.cpp
+++ b/libs/camera/CameraParameters.cpp
@@ -130,6 +130,8 @@ const char CameraParameters::PIXEL_FORMAT_YUV420SP[] = "yuv420sp";
const char CameraParameters::PIXEL_FORMAT_YUV422I[] = "yuv422i-yuyv";
const char CameraParameters::PIXEL_FORMAT_RGB565[] = "rgb565";
const char CameraParameters::PIXEL_FORMAT_JPEG[] = "jpeg";
+const char CameraParameters::PIXEL_FORMAT_RAW[] = "raw";
+
// Values for focus mode settings.
const char CameraParameters::FOCUS_MODE_AUTO[] = "auto";
@@ -137,6 +139,51 @@ const char CameraParameters::FOCUS_MODE_INFINITY[] = "infinity";
const char CameraParameters::FOCUS_MODE_MACRO[] = "macro";
const char CameraParameters::FOCUS_MODE_FIXED[] = "fixed";
const char CameraParameters::FOCUS_MODE_EDOF[] = "edof";
+const char CameraParameters::FOCUS_MODE_NORMAL[] = "normal";
+
+
+const char CameraParameters::KEY_SUPPORTED_THUMBNAIL_SIZES[] = "jpeg-thumbnail-size-values";
+const char CameraParameters::KEY_GPS_LATITUDE_REF[] = "gps-latitude-ref";
+const char CameraParameters::KEY_GPS_LONGITUDE_REF[] = "gps-longitude-ref";
+const char CameraParameters::KEY_GPS_ALTITUDE_REF[] = "gps-altitude-ref";
+const char CameraParameters::KEY_GPS_STATUS[] = "gps-status";
+const char CameraParameters::KEY_EXIF_DATETIME[] = "exif-datetime";
+
+const char CameraParameters::KEY_AUTO_EXPOSURE[] = "auto-exposure";
+const char CameraParameters::KEY_SUPPORTED_AUTO_EXPOSURE[] = "auto-exposure-values";
+
+const char CameraParameters::KEY_ISO_MODE[] = "iso";
+const char CameraParameters::KEY_SUPPORTED_ISO_MODES[] = "iso-values";
+const char CameraParameters::KEY_LENSSHADE[] = "lensshade";
+const char CameraParameters::KEY_SUPPORTED_LENSSHADE_MODES[] = "lensshade-values";
+const char CameraParameters::KEY_SHARPNESS[] = "sharpness";
+const char CameraParameters::KEY_MAX_SHARPNESS[] = "max-sharpness";
+const char CameraParameters::KEY_CONTRAST[] = "contrast";
+const char CameraParameters::KEY_MAX_CONTRAST[] = "max-contrast";
+const char CameraParameters::KEY_SATURATION[] = "saturation";
+const char CameraParameters::KEY_MAX_SATURATION[] = "max-saturation";
+
+
+// Values for auto exposure settings.
+const char CameraParameters::AUTO_EXPOSURE_FRAME_AVG[] = "frame-average";
+const char CameraParameters::AUTO_EXPOSURE_CENTER_WEIGHTED[] = "center-weighted";
+const char CameraParameters::AUTO_EXPOSURE_SPOT_METERING[] = "spot-metering";
+
+ // Values for ISO Settings
+const char CameraParameters::ISO_AUTO[] = "auto";
+const char CameraParameters::ISO_HJR[] = "ISO_HJR";
+const char CameraParameters::ISO_100[] = "ISO100";
+const char CameraParameters::ISO_200[] = "ISO200";
+const char CameraParameters::ISO_400[] = "ISO400";
+const char CameraParameters::ISO_800[] = "ISO800";
+const char CameraParameters::ISO_1600[] = "ISO1600";
+
+ //Values for Lens Shading
+const char CameraParameters::LENSSHADE_ENABLE[] = "enable";
+const char CameraParameters::LENSSHADE_DISABLE[] = "disable";
+
+static const char* portrait = "portrait";
+static const char* landscape = "landscape";
CameraParameters::CameraParameters()
: mMap()
@@ -315,6 +362,23 @@ void CameraParameters::setPreviewFormat(const char *format)
set(KEY_PREVIEW_FORMAT, format);
}
+int CameraParameters::getOrientation() const
+{
+ const char* orientation = get("orientation");
+ if (orientation && !strcmp(orientation, portrait))
+ return CAMERA_ORIENTATION_PORTRAIT;
+ return CAMERA_ORIENTATION_LANDSCAPE;
+}
+
+void CameraParameters::setOrientation(int orientation)
+{
+ if (orientation == CAMERA_ORIENTATION_PORTRAIT) {
+ set("orientation", portrait);
+ } else {
+ set("orientation", landscape);
+ }
+}
+
const char *CameraParameters::getPreviewFormat() const
{
return get(KEY_PREVIEW_FORMAT);
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index 86eb78d..bf74089 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -38,8 +38,12 @@ LOCAL_SHARED_LIBRARIES := \
libEGL \
libGLESv1_CM \
libbinder \
- libui \
- libsurfaceflinger_client
+ libui
+
+ifneq ($(BOARD_USES_ECLAIR_LIBCAMERA),true)
+ LOCAL_SHARED_LIBRARIES += \
+ libsurfaceflinger_client
+endif
LOCAL_C_INCLUDES := \
$(call include-path-for, corecg graphics)
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index ce7e9aa..2c7b4af 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -133,10 +133,14 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
mNeedsBlending = (info.h_alpha - info.l_alpha) > 0;
mNoEGLImageForSwBuffers = !(hwFlags & DisplayHardware::CACHED_BUFFERS);
- // we use the red index
- int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);
- int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
- mNeedsDithering = layerRedsize > displayRedSize;
+ if (mFlinger->getUseDithering()) {
+ // we use the red index
+ int displayRedSize = displayInfo.getSize(PixelFormatInfo::INDEX_RED);
+ int layerRedsize = info.getSize(PixelFormatInfo::INDEX_RED);
+ mNeedsDithering = layerRedsize > displayRedSize;
+ } else {
+ mNeedsDithering = false;
+ }
for (size_t i=0 ; i<NUM_BUFFERS ; i++) {
mBuffers[i] = new GraphicBuffer();
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index a8b735e..f78d140 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -33,6 +33,12 @@
#include "SurfaceFlinger.h"
#include "DisplayHardware/DisplayHardware.h"
+#define RENDER_EFFECT_NIGHT 1
+#define RENDER_EFFECT_TERMINAL 2
+#define RENDER_EFFECT_BLUE 3
+#define RENDER_EFFECT_AMBER 4
+#define RENDER_EFFECT_SALMON 5
+#define RENDER_EFFECT_FUSCIA 6
namespace android {
@@ -401,7 +407,10 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
glEnable(GL_TEXTURE_2D);
- if (UNLIKELY(s.alpha < 0xFF)) {
+ int renderEffect = mFlinger->getRenderEffect();
+ bool noEffect = renderEffect == 0;
+
+ if (UNLIKELY(s.alpha < 0xFF) && noEffect) {
// We have an alpha-modulation. We need to modulate all
// texture components by alpha because we're always using
// premultiplied alpha.
@@ -423,7 +432,7 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
glEnable(GL_BLEND);
glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env);
- } else {
+ } else if (noEffect) {
glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glColor4x(0x10000, 0x10000, 0x10000, 0x10000);
if (needsBlending()) {
@@ -433,6 +442,35 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const
} else {
glDisable(GL_BLEND);
}
+ } else {
+ // Apply a render effect, which is simple color masks for now.
+ GLenum env, src;
+ env = GL_MODULATE;
+ src = mPremultipliedAlpha ? GL_ONE : GL_SRC_ALPHA;
+ const GGLfixed alpha = (s.alpha << 16)/255;
+ switch (renderEffect) {
+ case RENDER_EFFECT_NIGHT:
+ glColor4x(alpha, 0, 0, alpha);
+ break;
+ case RENDER_EFFECT_TERMINAL:
+ glColor4x(0, alpha, 0, alpha);
+ break;
+ case RENDER_EFFECT_BLUE:
+ glColor4x(0, 0, alpha, alpha);
+ break;
+ case RENDER_EFFECT_AMBER:
+ glColor4x(alpha, alpha*0.75, 0, alpha);
+ break;
+ case RENDER_EFFECT_SALMON:
+ glColor4x(alpha, alpha*0.5, alpha*0.5, alpha);
+ break;
+ case RENDER_EFFECT_FUSCIA:
+ glColor4x(alpha, 0, alpha*0.5, alpha);
+ break;
+ }
+ glEnable(GL_BLEND);
+ glBlendFunc(src, GL_ONE_MINUS_SRC_ALPHA);
+ glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env);
}
Region::const_iterator it = clip.begin();
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 0722fda..b868cd1 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -184,13 +184,15 @@ SurfaceFlinger::SurfaceFlinger()
mFreezeDisplayTime(0),
mDebugRegion(0),
mDebugBackground(0),
+ mRenderEffect(0),
mDebugInSwapBuffers(0),
mLastSwapBufferTime(0),
mDebugInTransaction(0),
mLastTransactionTime(0),
mBootFinished(false),
mConsoleSignals(0),
- mSecureFrameBuffer(0)
+ mSecureFrameBuffer(0),
+ mUseDithering(true)
{
init();
}
@@ -205,9 +207,14 @@ void SurfaceFlinger::init()
mDebugRegion = atoi(value);
property_get("debug.sf.showbackground", value, "0");
mDebugBackground = atoi(value);
+ property_get("debug.sf.render_effect", value, "0");
+ mRenderEffect = atoi(value);
+ property_get("persist.sys.use_dithering", value, "1");
+ mUseDithering = atoi(value) == 1;
LOGI_IF(mDebugRegion, "showupdates enabled");
LOGI_IF(mDebugBackground, "showbackground enabled");
+ LOGI_IF(mUseDithering, "dithering enabled");
}
SurfaceFlinger::~SurfaceFlinger()
@@ -1692,12 +1699,18 @@ status_t SurfaceFlinger::onTransact(
reply->writeInt32(0);
reply->writeInt32(mDebugRegion);
reply->writeInt32(mDebugBackground);
+ reply->writeInt32(mRenderEffect);
return NO_ERROR;
case 1013: {
Mutex::Autolock _l(mStateLock);
const DisplayHardware& hw(graphicPlane(0).displayHardware());
reply->writeInt32(hw.getPageFlipCount());
}
+ case 1014: { // RENDER_EFFECT
+ // TODO: filter to only allow valid effects
+ mRenderEffect = data.readInt32();
+ return NO_ERROR;
+ }
return NO_ERROR;
}
}
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index d75dc15..812fd43 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -174,6 +174,9 @@ public:
overlay_control_device_t* getOverlayEngine() const;
+ inline int getRenderEffect() const { return mRenderEffect; }
+ inline int getUseDithering() const { return mUseDithering; }
+
status_t removeLayer(const sp<LayerBase>& layer);
status_t addLayer(const sp<LayerBase>& layer);
@@ -354,6 +357,7 @@ private:
// don't use a lock for these, we don't care
int mDebugRegion;
int mDebugBackground;
+ int mRenderEffect;
volatile nsecs_t mDebugInSwapBuffers;
nsecs_t mLastSwapBufferTime;
volatile nsecs_t mDebugInTransaction;
@@ -372,6 +376,7 @@ private:
// only written in the main thread, only read in other threads
volatile int32_t mSecureFrameBuffer;
+ bool mUseDithering;
};
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger_client/Android.mk b/libs/surfaceflinger_client/Android.mk
index fe85b34..5368280 100644
--- a/libs/surfaceflinger_client/Android.mk
+++ b/libs/surfaceflinger_client/Android.mk
@@ -10,6 +10,10 @@ LOCAL_SRC_FILES:= \
Surface.cpp \
SurfaceComposerClient.cpp
+LOCAL_MODULE:= libsurfaceflinger_client
+
+ifneq ($(BOARD_USES_ECLAIR_LIBCAMERA),true)
+
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
@@ -17,10 +21,15 @@ LOCAL_SHARED_LIBRARIES := \
libhardware \
libui
-LOCAL_MODULE:= libsurfaceflinger_client
ifeq ($(TARGET_SIMULATOR),true)
LOCAL_LDLIBS += -lpthread
endif
include $(BUILD_SHARED_LIBRARY)
+
+else
+
+include $(BUILD_STATIC_LIBRARY)
+
+endif
diff --git a/libs/ui/Android.mk b/libs/ui/Android.mk
index f7acd97..c5bc8bd 100644
--- a/libs/ui/Android.mk
+++ b/libs/ui/Android.mk
@@ -26,6 +26,27 @@ LOCAL_SHARED_LIBRARIES := \
libhardware \
libhardware_legacy
+
+ifeq ($(BOARD_USES_ECLAIR_LIBCAMERA),true)
+
+LOCAL_SRC_FILES+= \
+ ../camera/Camera.cpp \
+ ../camera/CameraParameters.cpp \
+ ../camera/ICamera.cpp \
+ ../camera/ICameraClient.cpp \
+ ../camera/ICameraService.cpp
+
+LOCAL_SRC_FILES+= \
+ ../surfaceflinger_client/ISurfaceComposer.cpp \
+ ../surfaceflinger_client/ISurface.cpp \
+ ../surfaceflinger_client/ISurfaceFlingerClient.cpp \
+ ../surfaceflinger_client/LayerState.cpp \
+ ../surfaceflinger_client/SharedBufferStack.cpp \
+ ../surfaceflinger_client/Surface.cpp \
+ ../surfaceflinger_client/SurfaceComposerClient.cpp
+
+endif
+
LOCAL_MODULE:= libui
ifeq ($(TARGET_SIMULATOR),true)
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index d45eaf0..0a98cb2 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -642,7 +642,10 @@ int EventHub::open_device(const char *deviceName)
if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0)
{
if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
- device->classes |= CLASS_TRACKBALL;
+ if (test_bit(BTN_LEFT, key_bitmask) && test_bit(BTN_RIGHT, key_bitmask))
+ device->classes |= CLASS_MOUSE;
+ else
+ device->classes |= CLASS_TRACKBALL;
}
}
}
diff --git a/libs/ui/Overlay.cpp b/libs/ui/Overlay.cpp
index 3aa8950..96f8006 100644
--- a/libs/ui/Overlay.cpp
+++ b/libs/ui/Overlay.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -83,6 +84,12 @@ status_t Overlay::getCrop(uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h)
return mOverlayData->getCrop(mOverlayData, x, y, w, h);
}
+status_t Overlay::setFd(int fd)
+{
+ if (mStatus != NO_ERROR) return mStatus;
+ return mOverlayData->setFd(mOverlayData, fd);
+}
+
int32_t Overlay::getBufferCount() const
{
if (mStatus != NO_ERROR) return mStatus;
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index 7e0f881..1a40deb 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -4393,7 +4393,6 @@ void ResTable::print(bool inclValues) const
}
printf("\n");
- if (inclValues) {
if (valuePtr != NULL) {
printf(" ");
print_value(pkg, value);
@@ -4413,7 +4412,6 @@ void ResTable::print(bool inclValues) const
+ size + sizeof(*mapPtr)-sizeof(mapPtr->value));
}
}
- }
}
}
}
diff --git a/location/java/android/location/Address.java b/location/java/android/location/Address.java
index ac275c6..b152f48 100644
--- a/location/java/android/location/Address.java
+++ b/location/java/android/location/Address.java
@@ -500,7 +500,10 @@ public class Address implements Parcelable {
a.mAdminArea = in.readString();
a.mSubAdminArea = in.readString();
a.mLocality = in.readString();
+ a.mSubLocality = in.readString();
a.mThoroughfare = in.readString();
+ a.mSubThoroughfare = in.readString();
+ a.mPremises = in.readString();
a.mPostalCode = in.readString();
a.mCountryCode = in.readString();
a.mCountryName = in.readString();
@@ -544,7 +547,10 @@ public class Address implements Parcelable {
parcel.writeString(mAdminArea);
parcel.writeString(mSubAdminArea);
parcel.writeString(mLocality);
+ parcel.writeString(mSubLocality);
parcel.writeString(mThoroughfare);
+ parcel.writeString(mSubThoroughfare);
+ parcel.writeString(mPremises);
parcel.writeString(mPostalCode);
parcel.writeString(mCountryCode);
parcel.writeString(mCountryName);
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index bbbba74..1cd8fd0 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1215,6 +1215,13 @@ public class AudioManager {
return Settings.System.getInt(mContext.getContentResolver(), Settings.System.SOUND_EFFECTS_ENABLED, 0) != 0;
}
+ /**
+ * See if haptic feedback is enabled for screen touches of objects (called by ViewRoot)
+ * @hide
+ */
+ public boolean queryHapticsAllEnabled() {
+ return Settings.System.getInt(mContext.getContentResolver(), Settings.System.HAPTIC_FEEDBACK_ALL_ENABLED, 0) != 0;
+ }
/**
* Load Sound effects.
diff --git a/media/java/android/media/CamcorderProfile.java b/media/java/android/media/CamcorderProfile.java
index 64d6460..5915494 100644
--- a/media/java/android/media/CamcorderProfile.java
+++ b/media/java/android/media/CamcorderProfile.java
@@ -48,12 +48,16 @@ public class CamcorderProfile
* resolution and higher audio sampling rate, etc, than those with low quality
* level.
*
+ * An optional profile, "front" is defined as a high quality profile for devices
+ * with a front-facing camera.
+ *
* Do not change these values/ordinals without updating their counterpart
* in include/media/MediaProfiles.h!
*/
public static final int QUALITY_LOW = 0;
public static final int QUALITY_HIGH = 1;
-
+ public static final int QUALITY_FRONT = 2;
+
/**
* Default recording duration in seconds before the session is terminated.
* This is useful for applications like MMS has limited file size requirement.
@@ -123,7 +127,7 @@ public class CamcorderProfile
* @param quality the target quality level for the camcorder profile
*/
public static CamcorderProfile get(int quality) {
- if (quality < QUALITY_LOW || quality > QUALITY_HIGH) {
+ if (quality < QUALITY_LOW || quality > QUALITY_FRONT) {
String errMessage = "Unsupported quality level: " + quality;
throw new IllegalArgumentException(errMessage);
}
diff --git a/media/java/android/media/EncoderCapabilities.java b/media/java/android/media/EncoderCapabilities.java
index 71cb1b3..1f285bb 100644
--- a/media/java/android/media/EncoderCapabilities.java
+++ b/media/java/android/media/EncoderCapabilities.java
@@ -24,7 +24,6 @@ import android.util.Log;
* The EncoderCapabilities class is used to retrieve the
* capabilities for different video and audio
* encoders supported on a specific Android platform.
- * {@hide}
*/
public class EncoderCapabilities
{
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index 9d1d420..aece959 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -46,8 +46,9 @@ public class MediaFile {
public static final int FILE_TYPE_WMA = 6;
public static final int FILE_TYPE_OGG = 7;
public static final int FILE_TYPE_AAC = 8;
+ public static final int FILE_TYPE_FLAC = 9;
private static final int FIRST_AUDIO_FILE_TYPE = FILE_TYPE_MP3;
- private static final int LAST_AUDIO_FILE_TYPE = FILE_TYPE_AAC;
+ private static final int LAST_AUDIO_FILE_TYPE = FILE_TYPE_FLAC;
// MIDI file types
public static final int FILE_TYPE_MID = 11;
@@ -134,6 +135,7 @@ public class MediaFile {
addFileType("OGG", FILE_TYPE_OGG, "application/ogg");
addFileType("OGA", FILE_TYPE_OGG, "application/ogg");
addFileType("AAC", FILE_TYPE_AAC, "audio/aac");
+ addFileType("FLAC", FILE_TYPE_FLAC, "audio/flac");
addFileType("MID", FILE_TYPE_MID, "audio/midi");
addFileType("MIDI", FILE_TYPE_MID, "audio/midi");
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 47a8cfc..5f90473 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -204,7 +204,7 @@ public class MediaRecorder
public static final int AMR_NB = 1;
/** @hide AMR (Wideband) audio codec */
public static final int AMR_WB = 2;
- /** @hide AAC audio codec */
+ /** AAC audio codec */
public static final int AAC = 3;
/** @hide enhanced AAC audio codec */
public static final int AAC_PLUS = 4;
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index 0ce3526..0cecc3f 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -166,6 +166,9 @@ public class Ringtone {
}
private void openMediaPlayer() throws IOException {
+ if (mAudio != null) {
+ return;
+ }
mAudio = new MediaPlayer();
if (mUri != null) {
mAudio.setDataSource(mContext, mUri);
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index a6a25cd..29bb027 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -21,9 +21,13 @@ LOCAL_SHARED_LIBRARIES := \
libmedia \
libskia \
libui \
- libcutils \
- libsurfaceflinger_client \
- libcamera_client
+ libcutils
+
+ifneq ($(BOARD_USES_ECLAIR_LIBCAMERA),true)
+ LOCAL_SHARED_LIBRARIES += \
+ libsurfaceflinger_client \
+ libcamera_client
+endif
ifneq ($(BUILD_WITHOUT_PV),true)
diff --git a/media/jni/android_media_MediaProfiles.cpp b/media/jni/android_media_MediaProfiles.cpp
index 7d7533a..ff3379e 100644
--- a/media/jni/android_media_MediaProfiles.cpp
+++ b/media/jni/android_media_MediaProfiles.cpp
@@ -165,7 +165,7 @@ static jobject
android_media_MediaProfiles_native_get_camcorder_profile(JNIEnv *env, jobject thiz, jint quality)
{
LOGV("native_get_camcorder_profile: %d", quality);
- if (quality != CAMCORDER_QUALITY_HIGH && quality != CAMCORDER_QUALITY_LOW) {
+ if (quality != CAMCORDER_QUALITY_HIGH && quality != CAMCORDER_QUALITY_LOW && quality != CAMCORDER_QUALITY_FRONT) {
jniThrowException(env, "java/lang/RuntimeException", "Unknown camcorder profile quality");
return NULL;
}
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index 3adabcc..b660eec 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -29,7 +29,13 @@ LOCAL_SRC_FILES:= \
MediaProfiles.cpp
LOCAL_SHARED_LIBRARIES := \
- libui libcutils libutils libbinder libsonivox libicuuc libexpat libsurfaceflinger_client libcamera_client
+ libui libcutils libutils libbinder libsonivox libicuuc libexpat
+
+ifneq ($(BOARD_USES_ECLAIR_LIBCAMERA),true)
+ LOCAL_SHARED_LIBRARIES += \
+ libsurfaceflinger_client \
+ libcamera_client
+endif
LOCAL_MODULE:= libmedia
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 1263373..1b3be41 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -59,8 +59,9 @@ const MediaProfiles::NameToTagMap MediaProfiles::sAudioDecoderNameMap[] = {
};
const MediaProfiles::NameToTagMap MediaProfiles::sCamcorderQualityNameMap[] = {
- {"high", CAMCORDER_QUALITY_HIGH},
- {"low", CAMCORDER_QUALITY_LOW}
+ {"high", CAMCORDER_QUALITY_HIGH},
+ {"low", CAMCORDER_QUALITY_LOW},
+ {"front", CAMCORDER_QUALITY_FRONT}
};
/*static*/ void
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index cf97b23..ecd1d2e 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -13,7 +13,8 @@ LOCAL_SRC_FILES:= \
TestPlayerStub.cpp \
VorbisPlayer.cpp \
VorbisMetadataRetriever.cpp \
- MidiMetadataRetriever.cpp \
+ FLACPlayer.cpp \
+ MidiMetadataRetriever.cpp \
MidiFile.cpp
ifeq ($(BUILD_WITH_FULL_STAGEFRIGHT),true)
@@ -40,12 +41,17 @@ LOCAL_SHARED_LIBRARIES := \
libandroid_runtime \
libstagefright \
libstagefright_omx \
- libstagefright_color_conversion \
- libsurfaceflinger_client
+ libstagefright_color_conversion
+
+ifneq ($(BOARD_USES_ECLAIR_LIBCAMERA),true)
+ LOCAL_SHARED_LIBRARIES += \
+ libsurfaceflinger_client
+endif
ifneq ($(BUILD_WITHOUT_PV),true)
LOCAL_SHARED_LIBRARIES += \
libopencore_player \
+ libFLAC \
libopencore_author
else
LOCAL_CFLAGS += -DNO_OPENCORE
@@ -56,6 +62,7 @@ LOCAL_SHARED_LIBRARIES += libdl
endif
LOCAL_C_INCLUDES := \
+ external/flac/include \
$(JNI_H_INCLUDE) \
$(call include-path-for, graphics corecg) \
$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
diff --git a/media/libmediaplayerservice/FLACPlayer.cpp b/media/libmediaplayerservice/FLACPlayer.cpp
new file mode 100644
index 0000000..1f8e3b6
--- /dev/null
+++ b/media/libmediaplayerservice/FLACPlayer.cpp
@@ -0,0 +1,577 @@
+/*
+** Copyright 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.
+*/
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "FLACPlayer"
+#include "utils/Log.h"
+
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+
+#include "FLACPlayer.h"
+
+#ifdef HAVE_GETTID
+static pid_t myTid() { return gettid(); }
+#else
+static pid_t myTid() { return getpid(); }
+#endif
+
+// ----------------------------------------------------------------------------
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+// TODO: Determine appropriate return codes
+static status_t ERROR_NOT_OPEN = -1;
+static status_t ERROR_OPEN_FAILED = -2;
+static status_t ERROR_ALLOCATE_FAILED = -4;
+static status_t ERROR_NOT_SUPPORTED = -8;
+static status_t ERROR_NOT_READY = -16;
+static status_t STATE_INIT = 0;
+static status_t STATE_ERROR = 1;
+static status_t STATE_OPEN = 2;
+
+
+FLACPlayer::FLACPlayer() :
+ mTotalSamples(-1), mCurrentSample(0), mBytesPerSample(-1),
+ mChannels(-1), mSampleRate(-1), mAudioBuffer(NULL),
+ mAudioBufferSize(0), mAudioBufferFilled(0),
+ mState(STATE_ERROR), mStreamType(AudioSystem::MUSIC),
+ mLoop(false), mAndroidLoop(false), mExit(false), mPaused(false),
+ mRender(false), mRenderTid(-1)
+{
+ LOGV("constructor");
+}
+
+void FLACPlayer::onFirstRef()
+{
+ LOGV("onFirstRef");
+ // create playback thread
+ Mutex::Autolock l(mMutex);
+ createThreadEtc(renderThread, this, "FLAC decoder", ANDROID_PRIORITY_AUDIO);
+ mCondition.wait(mMutex);
+ if (mRenderTid > 0) {
+ LOGV("render thread(%d) started", mRenderTid);
+ mState = STATE_INIT;
+ }
+}
+
+status_t FLACPlayer::initCheck()
+{
+ if (mState != STATE_ERROR) return NO_ERROR;
+ return ERROR_NOT_READY;
+}
+
+FLACPlayer::~FLACPlayer() {
+ LOGV("FLACPlayer destructor");
+ release();
+}
+
+status_t FLACPlayer::setDataSource(
+ const char *uri, const KeyedVector<String8, String8> *headers) {
+ return setdatasource(uri, -1, 0, 0x7ffffffffffffffLL); // intentionally less than LONG_MAX
+}
+
+status_t FLACPlayer::setDataSource(int fd, int64_t offset, int64_t length)
+{
+ return setdatasource(NULL, fd, offset, length);
+}
+
+status_t FLACPlayer::setdatasource(const char *path, int fd, int64_t offset, int64_t length)
+{
+ LOGV("setDataSource url=%s, fd=%d", path, fd);
+
+ // file still open?
+ Mutex::Autolock l(mMutex);
+ if (mState == STATE_OPEN) {
+ reset_nosync();
+ }
+
+ // open file and set paused state
+ if (path) {
+ mFile = fopen(path, "r");
+ } else {
+ mFile = fdopen(dup(fd), "r");
+ }
+ if (mFile == NULL) {
+ return ERROR_OPEN_FAILED;
+ }
+
+ struct stat sb;
+ int ret;
+ if (path) {
+ ret = stat(path, &sb);
+ } else {
+ ret = fstat(fd, &sb);
+ }
+ if (ret != 0) {
+ mState = STATE_ERROR;
+ fclose(mFile);
+ return ERROR_OPEN_FAILED;
+ }
+
+ fseek(mFile, offset, SEEK_SET);
+
+ mDecoder = FLAC__stream_decoder_new();
+ if (mDecoder == NULL) {
+ LOGE("failed to allocate decoder\n");
+ mState = STATE_ERROR;
+ fclose(mFile);
+ return ERROR_OPEN_FAILED;
+ }
+
+ FLAC__stream_decoder_set_md5_checking(mDecoder, false);
+ FLAC__stream_decoder_set_metadata_ignore_all(mDecoder);
+ FLAC__stream_decoder_set_metadata_respond(mDecoder, FLAC__METADATA_TYPE_STREAMINFO);
+ FLAC__stream_decoder_set_metadata_respond(mDecoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
+
+ FLAC__StreamDecoderInitStatus init_status;
+ init_status = FLAC__stream_decoder_init_FILE(mDecoder, mFile, vp_write, vp_metadata, vp_error, this);
+ if (init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
+ LOGE("FLAC__stream_decoder_init_FILE failed: [%d]\n", (int)init_status);
+ mState = STATE_ERROR;
+ fclose(mFile);
+ return ERROR_OPEN_FAILED;
+ }
+
+ if (!FLAC__stream_decoder_process_until_end_of_metadata(mDecoder)) {
+ LOGE("FLAC__stream_decoder_process_until_end_of_metadata failed\n");
+ mState = STATE_ERROR;
+ fclose(mFile);
+ return ERROR_OPEN_FAILED;
+ }
+
+ mState = STATE_OPEN;
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::prepare()
+{
+ LOGV("prepare");
+ if (mState != STATE_OPEN ) {
+ return ERROR_NOT_OPEN;
+ }
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::prepareAsync() {
+ LOGV("prepareAsync");
+ // can't hold the lock here because of the callback
+ // it's safe because we don't change state
+ if (mState != STATE_OPEN) {
+ sendEvent(MEDIA_ERROR);
+ return NO_ERROR;
+ }
+ sendEvent(MEDIA_PREPARED);
+ return NO_ERROR;
+}
+
+void FLACPlayer::vp_metadata(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) {
+ FLACPlayer *self = (FLACPlayer *)client_data;
+
+ if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
+ self->mTotalSamples = metadata->data.stream_info.total_samples;
+ self->mBytesPerSample = metadata->data.stream_info.bits_per_sample / 8;
+ self->mChannels = metadata->data.stream_info.channels;
+ self->mSampleRate = metadata->data.stream_info.sample_rate;
+
+ if (self->mBytesPerSample != 2) {
+ LOGE("Can only support 16 bits per sample; input is %d\n", self->mBytesPerSample * 8);
+ self->mState = STATE_ERROR;
+ return;
+ }
+
+ self->mLengthInMsec = self->mTotalSamples / self->mSampleRate * 1000 +
+ self->mTotalSamples % self->mSampleRate / ( self->mSampleRate / 1000 );
+ } else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
+ for (unsigned int i = 0; i < metadata->data.vorbis_comment.num_comments; i++) {
+ char *ptr = (char *)metadata->data.vorbis_comment.comments[i].entry;
+
+ // does the comment start with ANDROID_LOOP_TAG
+ if (strncmp(ptr, ANDROID_LOOP_TAG, strlen(ANDROID_LOOP_TAG)) == 0) {
+ // read the value of the tag
+ char *val = ptr + strlen(ANDROID_LOOP_TAG) + 1;
+ self->mAndroidLoop = (strncmp(val, "true", 4) == 0);
+ }
+
+ LOGV_IF(self->mAndroidLoop, "looped sound");
+ }
+ }
+}
+
+void FLACPlayer::vp_error(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) {
+ LOGV("vp_error");
+ FLACPlayer *self = (FLACPlayer *)client_data;
+ self->sendEvent(MEDIA_ERROR);
+ self->mState = STATE_ERROR;
+}
+
+status_t FLACPlayer::start()
+{
+ LOGV("start\n");
+ Mutex::Autolock l(mMutex);
+ if (mState != STATE_OPEN) {
+ return ERROR_NOT_OPEN;
+ }
+
+ mPaused = false;
+ mRender = true;
+
+ // wake up render thread
+ LOGV(" wakeup render thread\n");
+ mCondition.signal();
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::stop()
+{
+ LOGV("stop\n");
+ Mutex::Autolock l(mMutex);
+ if (mState != STATE_OPEN) {
+ return ERROR_NOT_OPEN;
+ }
+ mPaused = true;
+ mRender = false;
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::seekTo(int msec)
+{
+ LOGV("seekTo %d\n", msec);
+ Mutex::Autolock l(mMutex);
+ if (mState != STATE_OPEN) {
+ return ERROR_NOT_OPEN;
+ }
+
+ FLAC__uint64 target_sample = mTotalSamples * msec / mLengthInMsec;
+
+ if (mTotalSamples > 0 && target_sample >= mTotalSamples && target_sample > 0)
+ target_sample = mTotalSamples - 1;
+
+ if (!FLAC__stream_decoder_seek_absolute(mDecoder, target_sample)) {
+ LOGE("FLAC__stream_decoder_seek_absolute failed\n");
+ if (FLAC__stream_decoder_get_state(mDecoder) == FLAC__STREAM_DECODER_SEEK_ERROR) {
+ FLAC__stream_decoder_flush(mDecoder);
+ }
+ return ERROR_NOT_SUPPORTED;
+ }
+
+ mCurrentSample = target_sample;
+
+ sendEvent(MEDIA_SEEK_COMPLETE);
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::pause()
+{
+ LOGV("pause\n");
+ Mutex::Autolock l(mMutex);
+ if (mState != STATE_OPEN) {
+ return ERROR_NOT_OPEN;
+ }
+ mPaused = true;
+ return NO_ERROR;
+}
+
+bool FLACPlayer::isPlaying()
+{
+ LOGV("isPlaying\n");
+ if (mState == STATE_OPEN) {
+ return mRender;
+ }
+ return false;
+}
+
+status_t FLACPlayer::getCurrentPosition(int* msec)
+{
+ LOGV("getCurrentPosition\n");
+ Mutex::Autolock l(mMutex);
+ if (mState != STATE_OPEN) {
+ LOGE("getCurrentPosition(): file not open");
+ return ERROR_NOT_OPEN;
+ }
+
+ *msec = (int)(mCurrentSample * 1000 / mSampleRate);
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::getDuration(int* duration)
+{
+ LOGV("getDuration\n");
+ if (mState != STATE_OPEN) {
+ return ERROR_NOT_OPEN;
+ }
+
+ *duration = mLengthInMsec;
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::release()
+{
+ LOGV("release\n");
+ Mutex::Autolock l(mMutex);
+ reset_nosync();
+
+ // TODO: timeout when thread won't exit
+ // wait for render thread to exit
+ if (mRenderTid > 0) {
+ mExit = true;
+ mCondition.signal();
+ mCondition.wait(mMutex);
+ }
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::reset()
+{
+ LOGV("reset\n");
+ Mutex::Autolock l(mMutex);
+ return reset_nosync();
+}
+
+// always call with lock held
+status_t FLACPlayer::reset_nosync()
+{
+ // close file
+ if (mFile != NULL) {
+ FLAC__stream_decoder_delete(mDecoder);
+ fclose(mFile);
+ mFile = NULL;
+ }
+ mState = STATE_ERROR;
+
+ mTotalSamples = -1;
+ mBytesPerSample = -1;
+ mChannels = -1;
+ mSampleRate = -1;
+ mLoop = false;
+ mAndroidLoop = false;
+ mPaused = false;
+ mRender = false;
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::setLooping(int loop)
+{
+ LOGV("setLooping\n");
+ Mutex::Autolock l(mMutex);
+ mLoop = (loop != 0);
+ return NO_ERROR;
+}
+
+status_t FLACPlayer::createOutputTrack() {
+ LOGV("Create AudioTrack object: rate=%ld, channels=%d\n",
+ mSampleRate, mChannels);
+ if (mAudioSink->open(mSampleRate, mChannels, AudioSystem::PCM_16_BIT, DEFAULT_AUDIOSINK_BUFFERCOUNT) != NO_ERROR) {
+ LOGE("mAudioSink open failed\n");
+ return ERROR_OPEN_FAILED;
+ }
+ return NO_ERROR;
+}
+
+FLAC__StreamDecoderWriteStatus FLACPlayer::vp_write(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data) {
+ FLACPlayer *self = (FLACPlayer *)client_data;
+
+ const uint32_t bytes_per_sample = self->mBytesPerSample;
+ const uint32_t incr = bytes_per_sample * self->mChannels;
+ const uint32_t wide_samples = frame->header.blocksize;
+ const uint32_t frame_size = incr * wide_samples;
+
+ self->mCurrentSample = frame->header.number.sample_number;
+
+ uint32_t sample, wide_sample, channel;
+
+ if (self->mAudioBufferSize < frame_size) {
+ if (self->mAudioBuffer != NULL) {
+ delete [] self->mAudioBuffer;
+ }
+ self->mAudioBuffer = new FLAC__int8[frame_size];
+ self->mAudioBufferSize = frame_size;
+ }
+
+ FLAC__int8 *s8buffer = self->mAudioBuffer;
+ FLAC__int16 *s16buffer = (FLAC__int16 *)s8buffer;
+
+ // Interleave channel data like PCM
+ if (self->mChannels == 2) {
+ for (sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) {
+ s16buffer[sample++] = (FLAC__int16)(buffer[0][wide_sample]);
+ s16buffer[sample++] = (FLAC__int16)(buffer[1][wide_sample]);
+ }
+ } else if (self->mChannels == 1) {
+ for (sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) {
+ s16buffer[sample++] = (FLAC__int16)(buffer[0][wide_sample]);
+ }
+ } else {
+ for (sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) {
+ for (channel = 0; channel < self->mChannels; channel++, sample++) {
+ s16buffer[sample] = (FLAC__int16)(buffer[channel][wide_sample]);
+ }
+ }
+ }
+ self->mAudioBufferFilled = frame_size;
+
+ return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+}
+
+int FLACPlayer::renderThread(void* p) {
+ return ((FLACPlayer*)p)->render();
+}
+
+int FLACPlayer::render() {
+ int result = -1;
+ int temp;
+ int current_section = 0;
+ bool audioStarted = false;
+
+ LOGV("render\n");
+
+ // let main thread know we're ready
+ {
+ Mutex::Autolock l(mMutex);
+ mRenderTid = myTid();
+ mCondition.signal();
+ }
+
+ while (1) {
+ FLAC__bool status = true;
+ {
+ Mutex::Autolock l(mMutex);
+
+ // pausing?
+ if (mPaused) {
+ if (mAudioSink->ready()) mAudioSink->pause();
+ mRender = false;
+ audioStarted = false;
+ }
+
+ // nothing to render, wait for client thread to wake us up
+ if (!mExit && !mRender) {
+ LOGV("render - signal wait\n");
+ mCondition.wait(mMutex);
+ LOGV("render - signal rx'd\n");
+ }
+ if (mExit) break;
+
+ // We could end up here if start() is called, and before we get a
+ // chance to run, the app calls stop() or reset(). Re-check render
+ // flag so we don't try to render in stop or reset state.
+ if (!mRender) continue;
+
+ // create audio output track if necessary
+ if (!mAudioSink->ready()) {
+ LOGV("render - create output track\n");
+ if (createOutputTrack() != NO_ERROR)
+ break;
+ }
+
+
+ // start audio output if necessary
+ if (!audioStarted && !mPaused && !mExit) {
+ LOGV("render - starting audio\n");
+ mAudioSink->start();
+ audioStarted = true;
+ }
+
+ if (FLAC__stream_decoder_get_state(mDecoder) != FLAC__STREAM_DECODER_END_OF_STREAM) {
+ status = FLAC__stream_decoder_process_single(mDecoder);
+ } else {
+ // end of file, do we need to loop?
+ // ...
+ if (mLoop || mAndroidLoop) {
+ FLAC__stream_decoder_seek_absolute(mDecoder, 0);
+ mCurrentSample = 0;
+ status = FLAC__stream_decoder_process_single(mDecoder);
+ } else {
+ mAudioSink->stop();
+ audioStarted = false;
+ mRender = false;
+ mPaused = true;
+
+ FLAC__uint64 endpos;
+ if (!FLAC__stream_decoder_get_decode_position(mDecoder, &endpos)) {
+ endpos = 0;
+ }
+
+ LOGV("send MEDIA_PLAYBACK_COMPLETE\n");
+ sendEvent(MEDIA_PLAYBACK_COMPLETE);
+
+ // wait until we're started again
+ LOGV("playback complete - wait for signal\n");
+ mCondition.wait(mMutex);
+ LOGV("playback complete - signal rx'd\n");
+ if (mExit) break;
+
+ // if we're still at the end, restart from the beginning
+ if (mState == STATE_OPEN) {
+ FLAC__uint64 curpos;
+ if (FLAC__stream_decoder_get_decode_position(mDecoder, &curpos)) {
+ curpos = 0;
+ }
+ if (curpos == endpos) {
+ FLAC__stream_decoder_seek_absolute(mDecoder, 0);
+ mCurrentSample = 0;
+ }
+ status = FLAC__stream_decoder_process_single(mDecoder);
+ }
+ }
+ }
+ }
+
+ if (!status) {
+ LOGE("Error in FLAC decoder: %s\n", FLAC__stream_decoder_get_resolved_state_string(mDecoder));
+ sendEvent(MEDIA_ERROR);
+ break;
+ }
+
+ if (mAudioBufferFilled > 0) {
+ /* Be sure to clear mAudioBufferFilled even if there's an error. */
+ uint32_t toPlay = mAudioBufferFilled;
+ mAudioBufferFilled = 0;
+
+ if (!mAudioSink->write(mAudioBuffer, toPlay)) {
+ LOGE("Error in FLAC decoder: %s\n", FLAC__stream_decoder_get_resolved_state_string(mDecoder));
+ sendEvent(MEDIA_ERROR);
+ break;
+ }
+ }
+ }
+
+threadExit:
+ mAudioSink.clear();
+ if (mAudioBuffer != NULL) {
+ delete [] mAudioBuffer;
+ mAudioBuffer = NULL;
+ mAudioBufferSize = 0;
+ mAudioBufferFilled = 0;
+ }
+
+ // tell main thread goodbye
+ Mutex::Autolock l(mMutex);
+ mRenderTid = -1;
+ mCondition.signal();
+ return result;
+}
+
+} // end namespace android
diff --git a/media/libmediaplayerservice/FLACPlayer.h b/media/libmediaplayerservice/FLACPlayer.h
new file mode 100644
index 0000000..b7068c3
--- /dev/null
+++ b/media/libmediaplayerservice/FLACPlayer.h
@@ -0,0 +1,100 @@
+/*
+**
+** Copyright 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.
+*/
+
+#ifndef ANDROID_FLACPLAYER_H
+#define ANDROID_FLACPLAYER_H
+
+#include <utils/threads.h>
+
+#include <media/MediaPlayerInterface.h>
+#include <media/AudioTrack.h>
+
+#include "FLAC/all.h"
+
+#define ANDROID_LOOP_TAG "ANDROID_LOOP"
+
+namespace android {
+
+class FLACPlayer : public MediaPlayerInterface {
+public:
+ FLACPlayer();
+ ~FLACPlayer();
+
+ virtual void onFirstRef();
+ virtual status_t initCheck();
+
+ virtual status_t setDataSource(
+ const char *uri, const KeyedVector<String8, String8> *headers);
+
+ virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
+ virtual status_t setVideoSurface(const sp<ISurface>& surface) { return UNKNOWN_ERROR; }
+ virtual status_t prepare();
+ virtual status_t prepareAsync();
+ virtual status_t start();
+ virtual status_t stop();
+ virtual status_t seekTo(int msec);
+ virtual status_t pause();
+ virtual bool isPlaying();
+ virtual status_t getCurrentPosition(int* msec);
+ virtual status_t getDuration(int* msec);
+ virtual status_t release();
+ virtual status_t reset();
+ virtual status_t setLooping(int loop);
+ virtual player_type playerType() { return FLAC_PLAYER; }
+ virtual status_t invoke(const Parcel& request, Parcel *reply) {return INVALID_OPERATION;}
+
+private:
+ status_t setdatasource(const char *path, int fd, int64_t offset, int64_t length);
+ status_t reset_nosync();
+ status_t createOutputTrack();
+ static int renderThread(void*);
+ int render();
+
+ static void vp_metadata(const FLAC__StreamDecoder *, const FLAC__StreamMetadata *, void *);
+ static void vp_error(const FLAC__StreamDecoder *, const FLAC__StreamDecoderErrorStatus, void *);
+ static FLAC__StreamDecoderWriteStatus
+ vp_write(const FLAC__StreamDecoder *, const FLAC__Frame *, const FLAC__int32 * const[], void *);
+
+ FLAC__uint64 mTotalSamples;
+ FLAC__uint64 mCurrentSample;
+ uint32_t mBytesPerSample;
+ uint32_t mChannels;
+ uint32_t mSampleRate;
+ uint32_t mLengthInMsec;
+
+ FLAC__int8 * mAudioBuffer;
+ uint32_t mAudioBufferSize;
+ uint32_t mAudioBufferFilled;
+
+ Mutex mMutex;
+ Condition mCondition;
+ FILE* mFile;
+ FLAC__StreamDecoder* mDecoder;
+ status_t mState;
+ int mStreamType;
+ bool mLoop;
+ bool mAndroidLoop;
+ volatile bool mExit;
+ bool mPaused;
+ volatile bool mRender;
+ pid_t mRenderTid;
+};
+
+}; // namespace android
+
+#endif // ANDROID_FLACPLAYER_H
+
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 3e1f4a5..911d89f 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -57,6 +57,7 @@
#include "MidiFile.h"
#include "VorbisPlayer.h"
+#include "FLACPlayer.h"
#include <media/PVPlayer.h>
#include "TestPlayerStub.h"
#include "StagefrightPlayer.h"
@@ -204,6 +205,7 @@ extmap FILE_EXTS [] = {
{".wmv", PV_PLAYER},
{".asf", PV_PLAYER},
#endif
+ {".flac", FLAC_PLAYER},
};
// TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
@@ -719,6 +721,9 @@ player_type getPlayerType(int fd, int64_t offset, int64_t length)
}
#endif
+ if (ident == 0x43614c66) // 'fLaC'
+ return FLAC_PLAYER;
+
// Some kind of MIDI?
EAS_DATA_HANDLE easdata;
if (EAS_Init(&easdata) == EAS_SUCCESS) {
@@ -812,6 +817,10 @@ static sp<MediaPlayerBase> createPlayer(player_type playerType, void* cookie,
LOGV("Create Test Player stub");
p = new TestPlayerStub();
break;
+ case FLAC_PLAYER:
+ LOGV(" create FLACPlayer");
+ p = new FLACPlayer();
+ break;
}
if (p != NULL) {
if (p->initCheck() == NO_ERROR) {
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 81f995b..c4b88cc 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -47,10 +47,11 @@ LOCAL_CFLAGS += -DBUILD_WITH_FULL_STAGEFRIGHT
endif
LOCAL_C_INCLUDES:= \
- $(JNI_H_INCLUDE) \
+ $(JNI_H_INCLUDE) \
$(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
$(TOP)/external/opencore/android \
- $(TOP)/external/tremolo
+ $(TOP)/external/tremolo \
+ $(TOP)/external/flac/include
LOCAL_SHARED_LIBRARIES := \
libbinder \
@@ -60,8 +61,13 @@ LOCAL_SHARED_LIBRARIES := \
libui \
libsonivox \
libvorbisidec \
- libsurfaceflinger_client \
- libcamera_client
+ libFLAC
+
+ifneq ($(BOARD_USES_ECLAIR_LIBCAMERA),true)
+ LOCAL_SHARED_LIBRARIES += \
+ libsurfaceflinger_client \
+ libcamera_client
+endif
LOCAL_STATIC_LIBRARIES := \
libstagefright_aacdec \
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp
index 03287dd1..25236cf 100644
--- a/media/libstagefright/StagefrightMediaScanner.cpp
+++ b/media/libstagefright/StagefrightMediaScanner.cpp
@@ -30,6 +30,9 @@
#include <Tremolo/ivorbiscodec.h>
#include <Tremolo/ivorbisfile.h>
+// FLAC includes
+#include <FLAC/all.h>
+
namespace android {
StagefrightMediaScanner::StagefrightMediaScanner()
@@ -42,7 +45,8 @@ static bool FileHasAcceptableExtension(const char *extension) {
static const char *kValidExtensions[] = {
".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2",
".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac",
- ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota"
+ ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota",
+ ".flac"
};
static const size_t kNumValidExtensions =
sizeof(kValidExtensions) / sizeof(kValidExtensions[0]);
@@ -144,10 +148,78 @@ failure:
return UNKNOWN_ERROR;
}
+static FLAC__StreamDecoderWriteStatus flac_write(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data) {
+ (void)decoder, (void)frame, (void)buffer, (void)client_data;
+ return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
+}
+
+static void flac_error(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) {
+ (void)decoder, (void)status, (void)client_data;
+}
+
+static void flac_metadata(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) {
+ MediaScannerClient *client = (MediaScannerClient *)client_data;
+
+ if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
+ FLAC__uint64 duration = 1000 * metadata->data.stream_info.total_samples / metadata->data.stream_info.sample_rate;
+ if (duration > 0) {
+ char buffer[20];
+ sprintf(buffer, "%lld", duration);
+ if (!client->addStringTag("duration", buffer))
+ return;
+ }
+ } else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
+ for (uint32_t i = 0; i < metadata->data.vorbis_comment.num_comments; i++) {
+ char *ptr = (char *)metadata->data.vorbis_comment.comments[i].entry;
+
+ char *val = strchr(ptr, '=');
+ if (val) {
+ int keylen = val++ - ptr;
+ char key[keylen + 1];
+ strncpy(key, ptr, keylen);
+ key[keylen] = 0;
+ LOGD("flac_metadata: key: %s value: %s", key, val);
+ if (!client->addStringTag(key, val)) return;
+ }
+ }
+ }
+}
+
+static status_t HandleFLAC(const char *filename, MediaScannerClient *client)
+{
+ status_t status = UNKNOWN_ERROR;
+
+ FLAC__StreamDecoder *decoder;
+
+ decoder = FLAC__stream_decoder_new();
+ if (!decoder)
+ return status;
+
+ FLAC__stream_decoder_set_md5_checking(decoder, false);
+ FLAC__stream_decoder_set_metadata_ignore_all(decoder);
+ FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_STREAMINFO);
+ FLAC__stream_decoder_set_metadata_respond(decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
+
+ FLAC__StreamDecoderInitStatus init_status;
+ init_status = FLAC__stream_decoder_init_file(decoder, filename, flac_write, flac_metadata, flac_error, client);
+ if (init_status != FLAC__STREAM_DECODER_INIT_STATUS_OK)
+ goto exit;
+
+ if (!FLAC__stream_decoder_process_until_end_of_metadata(decoder))
+ goto exit;
+
+ status = OK;
+
+exit:
+ FLAC__stream_decoder_finish(decoder);
+ FLAC__stream_decoder_delete(decoder);
+
+ return OK;
+}
+
status_t StagefrightMediaScanner::processFile(
const char *path, const char *mimeType,
MediaScannerClient &client) {
- LOGV("processFile '%s'.", path);
client.setLocale(locale());
client.beginFile();
@@ -179,6 +251,10 @@ status_t StagefrightMediaScanner::processFile(
return HandleOGG(path, &client);
}
+ if (!strcasecmp(extension, ".flac")) {
+ return HandleFLAC(path, &client);
+ }
+
if (mRetriever->setDataSource(path) == OK
&& mRetriever->setMode(
METADATA_MODE_METADATA_RETRIEVAL_ONLY) == OK) {
diff --git a/media/libstagefright/colorconversion/Android.mk b/media/libstagefright/colorconversion/Android.mk
index b9ba1be..7e8a14a 100644
--- a/media/libstagefright/colorconversion/Android.mk
+++ b/media/libstagefright/colorconversion/Android.mk
@@ -13,9 +13,13 @@ LOCAL_SHARED_LIBRARIES := \
libmedia \
libutils \
libui \
- libcutils \
- libsurfaceflinger_client\
- libcamera_client
+ libcutils
+
+ifneq ($(BOARD_USES_ECLAIR_LIBCAMERA),true)
+ LOCAL_SHARED_LIBRARIES += \
+ libsurfaceflinger_client \
+ libcamera_client
+endif
LOCAL_MODULE:= libstagefright_color_conversion
diff --git a/packages/VpnServices/src/com/android/server/vpn/OpenvpnService.java b/packages/VpnServices/src/com/android/server/vpn/OpenvpnService.java
new file mode 100644
index 0000000..6bb6496
--- /dev/null
+++ b/packages/VpnServices/src/com/android/server/vpn/OpenvpnService.java
@@ -0,0 +1,423 @@
+/*
+ * Copyright (C) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.vpn;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Scanner;
+
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
+import android.net.vpn.OpenvpnProfile;
+import android.net.vpn.VpnManager;
+import android.security.Credentials;
+import android.util.Log;
+
+/**
+ * The service that manages the openvpn VPN connection.
+ */
+class OpenvpnService extends VpnService<OpenvpnProfile> {
+ private static final String OPENVPN_DAEMON = "openvpn";
+ private static final String MTPD = "mtpd";
+ private static final String USE_INLINE = "[[INLINE]]";
+ private static final String USE_KEYSTORE = "[[ANDROID]]";
+ private static final String TAG = OpenvpnService.class.getSimpleName();
+ private static int count = 0;
+
+ private final String socketName = OPENVPN_DAEMON + getCount();
+
+ private transient OpenvpnThread thread = null;
+
+ private transient String mPassword;
+ private transient String mUsername;
+
+ private synchronized static String getCount() {
+ return Integer.toString(count++);
+ }
+
+ @Override
+ protected void connect(String serverIp, String username, String password)
+ throws IOException {
+ OpenvpnProfile p = getProfile();
+ ArrayList<String> args = new ArrayList<String>();
+
+ mUsername = username;
+ mPassword = password;
+
+ args.add(OPENVPN_DAEMON);
+ args.add("--dev");
+ if (p.getDevice() != null) {
+ args.add(p.getDevice());
+ } else {
+ args.add("tun");
+ }
+ args.add("--remote");
+ args.add(serverIp);
+ args.add("--nobind");
+ args.add("--proto");
+ args.add(p.getProto());
+ args.add("--client");
+ args.add("--rport");
+ args.add(p.getPort());
+ if (p.getCAName() != null) {
+ args.add("--ca");
+ args.add(USE_INLINE);
+ args.add(USE_KEYSTORE + Credentials.CA_CERTIFICATE + p.getCAName());
+ }
+ if (p.getCertName() != null) {
+ args.add("--cert");
+ args.add(USE_INLINE);
+ args.add(USE_KEYSTORE + Credentials.USER_CERTIFICATE + p.getCertName());
+ args.add("--key");
+ args.add(USE_INLINE);
+ args.add(USE_KEYSTORE + Credentials.USER_PRIVATE_KEY + p.getCertName());
+ }
+ args.add("--persist-tun");
+ args.add("--persist-key");
+ args.add("--management");
+ args.add("/dev/socket/" + socketName);
+ args.add("unix");
+ args.add("--management-hold");
+ if (p.getUseCompLzo()) {
+ args.add("--comp-lzo");
+ }
+ if (p.getRedirectGateway()) {
+ args.add("--redirect-gateway def1");
+ }
+ if (p.getUserAuth()) {
+ args.add("--auth-user-pass");
+ args.add("--management-query-passwords");
+ }
+ if (p.getSupplyAddr()) {
+ args.add("--ifconfig");
+ args.add(p.getLocalAddr());
+ args.add(p.getRemoteAddr());
+ }
+ if (p.getCipher() != null) {
+ args.add("--cipher");
+ args.add(p.getCipher());
+ }
+ if (p.getKeySize() != null && !p.getKeySize().equals("")) {
+ args.add("--keysize");
+ args.add(p.getKeySize());
+ }
+ args.add("--up");
+ args.add("/system/xbin/openvpn-up.sh");
+ args.add("--script-security");
+ args.add("2");
+
+ if (p.getExtra() != null && !p.getExtra().equals("")) {
+ Scanner s = new Scanner(p.getExtra());
+ while(s.hasNext()) args.add(s.next());
+ }
+ DaemonProxy mtpd = getDaemons().startDaemon(MTPD);
+ mtpd.sendCommand(args.toArray(new String[args.size()]));
+ }
+
+ @Override
+ protected void disconnect() {
+ if (thread != null)
+ thread.disconnectAndWait();
+ }
+
+ @Override
+ void waitUntilConnectedOrTimedout() throws IOException {
+ thread = new OpenvpnThread();
+ thread.openvpnStart();
+ thread.waitConnect(60);
+ setVpnStateUp(true);
+ }
+
+ @Override
+ protected void recover() {
+ try {
+ thread = new OpenvpnThread();
+ thread.openvpnStart();
+ } catch (IOException e) {
+ onError(e);
+ }
+ }
+
+ void startConnectivityMonitor() {
+ /* Openvpn is completely event driven, so we don't need
+ * a polling monitor at all, so do nothing here */
+ }
+
+ private class OpenvpnThread extends Thread {
+ InputStream in;
+ OutputStream out;
+ LocalSocket mSocket;
+
+ boolean finalDisconnect = false;
+ boolean firstConnect = false;
+ boolean disconnecting = false;
+ boolean passwordError = false;
+
+ boolean SFbool;
+ volatile String SFreason;
+ String vpnState = "WAIT"; // initial state
+
+ OpenvpnThread() throws IOException {
+ openSocket();
+ in = mSocket.getInputStream();
+ out = mSocket.getOutputStream();
+ }
+
+ public void openvpnStart() throws IOException {
+ super.start();
+ send("state on"); // make state dynamic
+ send("log on"); // dynamically log over the socket
+ send("hold off"); // don't hold for subsequent reconnects
+ send("hold release"); // release from hold
+ send("bytecount 2"); // need this to update the monitor
+ }
+
+ public synchronized void disconnectAndWait() {
+ try {
+ disconnecting = true;
+ send("signal SIGTERM");
+ while (!finalDisconnect)
+ this.wait();
+ } catch(Exception e) {
+ // we're done
+ }
+ }
+
+ public synchronized void waitConnect(long seconds) throws IOException {
+ long endTime = System.currentTimeMillis() + seconds * 1000;
+ long wait;
+ while (!isConnected() && (wait = (endTime - System.currentTimeMillis())) > 0) {
+ try {
+ this.wait(wait);
+ } catch(InterruptedException e) {
+ // do nothing
+ }
+ if (passwordError)
+ throw new VpnConnectingError(VpnManager.VPN_ERROR_AUTH);
+ }
+ if (!isConnected())
+ throw new VpnConnectingError(VpnManager.VPN_ERROR_CONNECTION_FAILED);
+ firstConnect = true;
+ }
+
+ private boolean isConnected() {
+ return vpnState.equals("CONNECTED");
+ }
+
+ private void openSocket() throws IOException {
+ LocalSocket s = new LocalSocket();
+ LocalSocketAddress a = new LocalSocketAddress(socketName,
+ LocalSocketAddress.Namespace.RESERVED);
+ IOException excp = null;
+ for (int i = 0; i < 10; i++) {
+ try {
+ s.connect(a);
+ mSocket = s;
+ return;
+ } catch (IOException e) {
+ excp = e;
+ try {
+ Thread.currentThread().sleep(500);
+ } catch (InterruptedException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ }
+ throw excp;
+ }
+
+ private synchronized boolean waitForSuccessOrFail() {
+ SFreason = null;
+ try {
+ while (SFreason == null) {
+ this.wait();
+ }
+ return SFbool;
+ } catch(InterruptedException e) {
+ return false;
+ }
+ }
+
+ private synchronized void signalSuccessOrFail(boolean success, String reason) {
+ SFbool = success;
+ SFreason = reason;
+ this.notifyAll();
+ }
+
+
+ private synchronized void sendAsync(String str) throws IOException {
+ str += "\n";
+ out.write(str.getBytes());
+ out.flush();
+ }
+
+ private boolean send(String str) throws IOException {
+ sendAsync(str);
+ return waitForSuccessOrFail();
+ }
+
+ private synchronized void signalState(String s) {
+ // state strings come as <date in secs>, <state>, <other stuff>
+ int first = s.indexOf(',');
+ if (first == -1)
+ return;
+ int second = s.indexOf(',', first + 1);
+ if (second == -1)
+ return;
+ String state = s.substring(first + 1, second);
+
+ /*
+ * state can be:
+ *
+ *
+ * CONNECTING -- OpenVPN's initial state.
+ * WAIT -- (Client only) Waiting for initial response
+ * from server.
+ * AUTH -- (Client only) Authenticating with server.
+ * GET_CONFIG -- (Client only) Downloading configuration options
+ * from server.
+ * ASSIGN_IP -- Assigning IP address to virtual network
+ * interface.
+ * ADD_ROUTES -- Adding routes to system.
+ * CONNECTED -- Initialization Sequence Completed.
+ * RECONNECTING -- A restart has occurred.
+ * EXITING -- A graceful exit is in progress.
+ *
+ * Really all we care about is connected or not
+ */
+ vpnState = state;
+ this.notifyAll();
+ if (state.equals("EXITING") && firstConnect && !disconnecting)
+ onError(new IOException("Connection Closed"));
+ }
+
+ private synchronized void signalPassword(String s) throws IOException {
+ /* message should be Need '<auth type>' password
+ * but coult be Verification Failed: '<auth type'
+ */
+
+ int first = s.indexOf('\'');
+ int second = s.indexOf('\'', first + 1);
+ final String authType = s.substring(first + 1, second);
+
+ /* AuthType can be one of
+ *
+ * "Auth" - regular client server authentication
+ * "Private Key" - password for private key (unimplemented)
+ */
+
+ if (s.startsWith("Need")) {
+ /* we're in the processor thread, so we have to send
+ * these asynchronously to avoid a deadlock */
+ sendAsync("username '" + authType +"' '" + mUsername + "'");
+ sendAsync("password '" + authType +"' '" + mPassword + "'");
+ } else {
+ // must be signalling authentication failure
+ passwordError = true;
+ this.notifyAll();
+ }
+ }
+
+ private void signalBytecount(String s) {
+ int index = s.indexOf(',');
+ if (index == -1)
+ // no , in message, ignore it
+ return;
+
+ String in = s.substring(0, index);
+ String out = s.substring(index+1);
+ vpnStateUpdate(Long.parseLong(in), Long.parseLong(out));
+ }
+
+ private void signalLog(String s) {
+ //log format is <date in secs>,<severity>,<message>
+ int first = s.indexOf(',');
+ if (first == -1)
+ return;
+ int second = s.indexOf(',', first + 1);
+ if (second == -1)
+ return;
+ String message = s.substring(second + 1);
+ Log.i("openvpn", message);
+ }
+
+ private void parseLine(String s) throws IOException {
+ int index = s.indexOf(':');
+ if (index == -1)
+ // no : in message, ignore it
+ return;
+
+ String token = s.substring(0, index);
+ String body = s.substring(index +1);
+
+ if (token.equals(">INFO")) {
+ // This is the starting string, just skip it
+ } else if (token.equals("SUCCESS")) {
+ signalSuccessOrFail(true, body);
+ } else if (token.equals("ERROR")) {
+ signalSuccessOrFail(false, body);
+ } else if (token.equals(">STATE")) {
+ signalState(body);
+ } else if (token.equals(">FATAL")) {
+ signalState("EXITING," + body);
+ } else if (token.equals(">PASSWORD")) {
+ signalPassword(body);
+ } else if (token.equals(">LOG")) {
+ signalLog(body);
+ }else if (token.equals(">HOLD")) {
+ // just warning us we're in a hold state, ignore
+ } else if (token.equals(">BYTECOUNT")) {
+ signalBytecount(body);
+ } else {
+ Log.w(TAG, "Unknown control token:\"" + token + "\"");
+ }
+ }
+
+ public void run() {
+
+ System.out.println("THREAD " + this + " RUNNING");
+
+ try {
+ int c;
+ StringBuffer s = new StringBuffer();
+ while (true) {
+ c = in.read();
+ if (c == -1)
+ throw new IOException("End of Stream");
+ if (c == '\n') {
+ parseLine(s.toString());
+ s = new StringBuffer();
+ continue;
+ }
+ if (c == '\r')
+ continue;
+ s.append((char)c);
+ }
+ } catch(IOException e) {
+ // terminate
+ } finally {
+ synchronized(this) {
+ finalDisconnect = true;
+ this.notifyAll();
+ }
+ System.out.println("THREAD " + this + " TERMINATED");
+ }
+ }
+ }
+}
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnDaemons.java b/packages/VpnServices/src/com/android/server/vpn/VpnDaemons.java
index 499195f..2346299 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnDaemons.java
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnDaemons.java
@@ -99,7 +99,7 @@ class VpnDaemons implements Serializable {
return 0;
}
- private synchronized DaemonProxy startDaemon(String daemonName)
+ synchronized DaemonProxy startDaemon(String daemonName)
throws IOException {
DaemonProxy daemon = new DaemonProxy(daemonName);
mDaemonList.add(daemon);
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnService.java b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
index 63b87b1..7c64f95 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnService.java
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnService.java
@@ -85,6 +85,13 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
String password) throws IOException;
/**
+ * Disconnects the vpn
+ */
+ protected void disconnect() {
+ mDaemons.stopAll();
+ }
+
+ /**
* Returns the daemons management class for this service object.
*/
protected VpnDaemons getDaemons() {
@@ -110,14 +117,19 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
recover(context);
}
+ // intended for override by subclasses
+ protected void recover() {
+ startConnectivityMonitor();
+ }
+
void recover(VpnServiceBinder context) {
mContext = context;
mNotification = new NotificationHelper();
if (VpnState.CONNECTED.equals(mState)) {
Log.i("VpnService", " recovered: " + mProfile.getName());
- startConnectivityMonitor();
- }
+ recover();
+ }
}
VpnState getState() {
@@ -147,7 +159,7 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
setState(VpnState.DISCONNECTING);
mNotification.showDisconnect();
- mDaemons.stopAll();
+ disconnect();
} catch (Throwable e) {
Log.e(TAG, "onDisconnect()", e);
} finally {
@@ -155,7 +167,7 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
}
}
- private void onError(Throwable error) {
+ void onError(Throwable error) {
// error may occur during or after connection setup
// and it may be due to one or all services gone
if (mError != null) {
@@ -167,7 +179,7 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
onDisconnect();
}
- private void onError(int errorCode) {
+ void onError(int errorCode) {
onError(new VpnConnectingError(errorCode));
}
@@ -183,7 +195,7 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
}
}
- private void waitUntilConnectedOrTimedout() throws IOException {
+ void waitUntilConnectedOrTimedout() throws IOException {
sleep(2000); // 2 seconds
for (int i = 0; i < 80; i++) {
if (mState != VpnState.CONNECTING) {
@@ -207,6 +219,21 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
}
}
+ void setVpnStateUp(boolean state) throws IOException {
+ if (state) {
+ SystemProperties.set(VPN_STATUS, VPN_IS_UP);
+ onConnected();
+ mNotification.update(System.currentTimeMillis());
+ } else {
+ SystemProperties.set(VPN_STATUS, VPN_IS_DOWN);
+ }
+ }
+
+ void vpnStateUpdate(long in, long out) {
+ // currently don't show in and out bytes in status
+ mNotification.update(System.currentTimeMillis());
+ }
+
private synchronized void onConnected() throws IOException {
if (DBG) Log.d(TAG, "onConnected()");
@@ -276,6 +303,11 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
private void setVpnDns() {
String vpnDns1 = SystemProperties.get(VPN_DNS1);
String vpnDns2 = SystemProperties.get(VPN_DNS2);
+ if (vpnDns1.length() == 0) {
+ Log.i(TAG, "No vpn dns supplied, not updating");
+ return;
+ }
+
SystemProperties.set(DNS1, vpnDns1);
SystemProperties.set(DNS2, vpnDns2);
Log.i(TAG, String.format("set vpn dns prop: %s, %s",
@@ -323,7 +355,7 @@ abstract class VpnService<E extends VpnProfile> implements Serializable {
}
}
- private void startConnectivityMonitor() {
+ void startConnectivityMonitor() {
new Thread(new Runnable() {
public void run() {
Log.i(TAG, "VPN connectivity monitor running");
diff --git a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
index 5672a01..162aea7 100644
--- a/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
+++ b/packages/VpnServices/src/com/android/server/vpn/VpnServiceBinder.java
@@ -22,6 +22,7 @@ import android.net.vpn.IVpnService;
import android.net.vpn.L2tpIpsecProfile;
import android.net.vpn.L2tpIpsecPskProfile;
import android.net.vpn.L2tpProfile;
+import android.net.vpn.OpenvpnProfile;
import android.net.vpn.PptpProfile;
import android.net.vpn.VpnManager;
import android.net.vpn.VpnProfile;
@@ -47,7 +48,7 @@ public class VpnServiceBinder extends Service {
private static final String TAG = VpnServiceBinder.class.getSimpleName();
private static final boolean DBG = true;
- private static final String STATES_FILE_RELATIVE_PATH = "/misc/vpn/.states";
+ private static final String STATES_FILE_RELATIVE_PATH = "/data/misc/vpn/.states";
// The actual implementation is delegated to the VpnService class.
private VpnService<? extends VpnProfile> mService;
@@ -159,6 +160,11 @@ public class VpnServiceBinder extends Service {
l2tp.setContext(this, (L2tpProfile) p);
return l2tp;
+ case OPENVPN:
+ OpenvpnService ovpn = new OpenvpnService();
+ ovpn.setContext(this, (OpenvpnProfile)p );
+ return ovpn;
+
case PPTP:
PptpService pptp = new PptpService();
pptp.setContext(this, (PptpProfile) p);
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 81b8d40..5c8ee53 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -430,6 +430,12 @@ public class ConnectivityService extends IConnectivityManager.Stub {
public NetworkInfo getNetworkInfo(int networkType) {
enforceAccessPermission();
+
+ // HACK! - return a stub NetworkInfo object to make bad apps happy.
+ if (ConnectivityManager.TYPE_WIMAX == networkType) {
+ return NetworkInfo.getEmptyWimaxNetworkInfo();
+ }
+
if (ConnectivityManager.isNetworkTypeValid(networkType)) {
NetworkStateTracker t = mNetTrackers[networkType];
if (t != null)
diff --git a/services/java/com/android/server/InputDevice.java b/services/java/com/android/server/InputDevice.java
index 414b69f..e198118 100644
--- a/services/java/com/android/server/InputDevice.java
+++ b/services/java/com/android/server/InputDevice.java
@@ -23,27 +23,32 @@ import android.view.Surface;
import android.view.WindowManagerPolicy;
import java.io.PrintWriter;
+import java.io.FileInputStream;
+import java.util.StringTokenizer;
+import android.view.RawInputEvent;
public class InputDevice {
static final boolean DEBUG_POINTERS = false;
static final boolean DEBUG_HACKS = false;
-
+ static final boolean DEBUG_MOUSE = false;
+ static final String TAG = "InputDevice";
+
/** Amount that trackball needs to move in order to generate a key event. */
static final int TRACKBALL_MOVEMENT_THRESHOLD = 6;
/** Maximum number of pointers we will track and report. */
static final int MAX_POINTERS = 10;
-
+
/**
* Slop distance for jumpy pointer detection.
* The vertical range of the screen divided by this is our epsilon value.
*/
private static final int JUMPY_EPSILON_DIVISOR = 212;
-
+
/** Number of jumpy points to drop for touchscreens that need it. */
private static final int JUMPY_TRANSITION_DROPS = 3;
private static final int JUMPY_DROP_LIMIT = 3;
-
+
final int id;
final int classes;
final String name;
@@ -51,18 +56,18 @@ public class InputDevice {
final AbsoluteInfo absY;
final AbsoluteInfo absPressure;
final AbsoluteInfo absSize;
-
+
long mKeyDownTime = 0;
int mMetaKeysState = 0;
-
+
// For use by KeyInputQueue for keeping track of the current touch
// data in the old non-multi-touch protocol.
final int[] curTouchVals = new int[MotionEvent.NUM_SAMPLE_DATA * 2];
-
+
final MotionState mAbs = new MotionState(0, 0);
final MotionState mRel = new MotionState(TRACKBALL_MOVEMENT_THRESHOLD,
TRACKBALL_MOVEMENT_THRESHOLD);
-
+
static class MotionState {
int xPrecision;
int yPrecision;
@@ -72,16 +77,16 @@ public class InputDevice {
boolean changed = false;
boolean everChanged = false;
long mDownTime = 0;
-
+
// The currently assigned pointer IDs, corresponding to the last data.
int[] mPointerIds = new int[MAX_POINTERS];
-
+
// This is the last generated pointer data, ordered to match
// mPointerIds.
boolean mSkipLastPointers;
int mLastNumPointers = 0;
final int[] mLastData = new int[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS];
-
+
// This is the next set of pointer data being generated. It is not
// in any known order, and will be propagated in to mLastData
// as part of mapping it to the appropriate pointer IDs.
@@ -90,14 +95,14 @@ public class InputDevice {
int mNextNumPointers = 0;
final int[] mNextData = new int[(MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS)
+ MotionEvent.NUM_SAMPLE_DATA];
-
+
// Used to determine whether we dropped bad data, to avoid doing
// it repeatedly.
final boolean[] mDroppedBadPoint = new boolean[MAX_POINTERS];
// Used to count the number of jumpy points dropped.
private int mJumpyPointsDropped = 0;
-
+
// Used to perform averaging of reported coordinates, to smooth
// the data and filter out transients during a release.
static final int HISTORY_SIZE = 5;
@@ -106,19 +111,19 @@ public class InputDevice {
final int[] mHistoryData = new int[(MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS)
* HISTORY_SIZE];
final int[] mAveragedData = new int[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS];
-
+
// Temporary data structures for doing the pointer ID mapping.
final int[] mLast2Next = new int[MAX_POINTERS];
final int[] mNext2Last = new int[MAX_POINTERS];
final long[] mNext2LastDistance = new long[MAX_POINTERS];
-
+
// Temporary data structure for generating the final motion data.
final float[] mReportData = new float[MotionEvent.NUM_SAMPLE_DATA * MAX_POINTERS];
-
+
// This is not used here, but can be used by callers for state tracking.
int mAddingPointerOffset = 0;
final boolean[] mDown = new boolean[MAX_POINTERS];
-
+
void dumpIntArray(PrintWriter pw, int[] array) {
pw.print("[");
for (int i=0; i<array.length; i++) {
@@ -127,7 +132,7 @@ public class InputDevice {
}
pw.print("]");
}
-
+
void dumpBooleanArray(PrintWriter pw, boolean[] array) {
pw.print("[");
for (int i=0; i<array.length; i++) {
@@ -136,7 +141,7 @@ public class InputDevice {
}
pw.print("]");
}
-
+
void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("xPrecision="); pw.print(xPrecision);
pw.print(" yPrecision="); pw.println(yPrecision);
@@ -168,7 +173,7 @@ public class InputDevice {
pw.print(prefix); pw.print("mDown=");
dumpBooleanArray(pw, mDown); pw.println("");
}
-
+
MotionState(int mx, int my) {
xPrecision = mx;
yPrecision = my;
@@ -178,7 +183,7 @@ public class InputDevice {
mPointerIds[i] = i;
}
}
-
+
/**
* Special hack for devices that have bad screen data: if one of the
* points has moved more than a screen height from the last position,
@@ -195,13 +200,13 @@ public class InputDevice {
if (mNextNumPointers != mLastNumPointers) {
return;
}
-
+
// We consider a single movement across more than a 7/16 of
// the long size of the screen to be bad. This was a magic value
// determined by looking at the maximum distance it is feasible
// to actually move in one sample.
final int maxDy = ((dev.absY.maxValue-dev.absY.minValue)*7)/16;
-
+
// Look through all new points and see if any are farther than
// acceptable from all previous points.
for (int i=mNextNumPointers-1; i>=0; i--) {
@@ -244,31 +249,31 @@ public class InputDevice {
mDroppedBadPoint[i] = dropped;
}
}
-
+
void dropJumpyPoint(InputDevice dev) {
// We should always have absY, but let's be paranoid.
if (dev.absY == null) {
return;
}
final int jumpyEpsilon = dev.absY.range / JUMPY_EPSILON_DIVISOR;
-
+
final int nextNumPointers = mNextNumPointers;
final int lastNumPointers = mLastNumPointers;
final int[] nextData = mNextData;
final int[] lastData = mLastData;
-
+
if (nextNumPointers != mLastNumPointers) {
if (DEBUG_HACKS) {
- Slog.d("InputDevice", "Different pointer count " + lastNumPointers +
+ Slog.d("InputDevice", "Different pointer count " + lastNumPointers +
" -> " + nextNumPointers);
for (int i = 0; i < nextNumPointers; i++) {
int ioff = i * MotionEvent.NUM_SAMPLE_DATA;
- Slog.d("InputDevice", "Pointer " + i + " (" +
+ Slog.d("InputDevice", "Pointer " + i + " (" +
mNextData[ioff + MotionEvent.SAMPLE_X] + ", " +
mNextData[ioff + MotionEvent.SAMPLE_Y] + ")");
}
}
-
+
// Just drop the first few events going from 1 to 2 pointers.
// They're bad often enough that they're not worth considering.
if (lastNumPointers == 1 && nextNumPointers == 2
@@ -278,36 +283,36 @@ public class InputDevice {
} else if (lastNumPointers == 2 && nextNumPointers == 1
&& mJumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
// The event when we go from 2 -> 1 tends to be messed up too
- System.arraycopy(lastData, 0, nextData, 0,
+ System.arraycopy(lastData, 0, nextData, 0,
lastNumPointers * MotionEvent.NUM_SAMPLE_DATA);
mNextNumPointers = lastNumPointers;
mJumpyPointsDropped++;
-
+
if (DEBUG_HACKS) {
for (int i = 0; i < mNextNumPointers; i++) {
int ioff = i * MotionEvent.NUM_SAMPLE_DATA;
- Slog.d("InputDevice", "Pointer " + i + " replaced (" +
+ Slog.d("InputDevice", "Pointer " + i + " replaced (" +
mNextData[ioff + MotionEvent.SAMPLE_X] + ", " +
mNextData[ioff + MotionEvent.SAMPLE_Y] + ")");
}
}
} else {
mJumpyPointsDropped = 0;
-
+
if (DEBUG_HACKS) {
Slog.d("InputDevice", "Transition - drop limit reset");
}
}
return;
}
-
+
// A 'jumpy' point is one where the coordinate value for one axis
// has jumped to the other pointer's location. No need to do anything
// else if we only have one pointer.
if (nextNumPointers < 2) {
return;
}
-
+
int badPointerIndex = -1;
int badPointerReplaceXWith = 0;
int badPointerReplaceYWith = 0;
@@ -315,13 +320,13 @@ public class InputDevice {
for (int i = nextNumPointers - 1; i >= 0; i--) {
boolean dropx = false;
boolean dropy = false;
-
+
// Limit how many times a jumpy point can get dropped.
if (mJumpyPointsDropped < JUMPY_DROP_LIMIT) {
final int ioff = i * MotionEvent.NUM_SAMPLE_DATA;
final int x = nextData[ioff + MotionEvent.SAMPLE_X];
final int y = nextData[ioff + MotionEvent.SAMPLE_Y];
-
+
if (DEBUG_HACKS) {
Slog.d("InputDevice", "Point " + i + " (" + x + ", " + y + ")");
}
@@ -339,14 +344,14 @@ public class InputDevice {
dropx = Math.abs(x - xOther) <= jumpyEpsilon;
dropy = Math.abs(y - yOther) <= jumpyEpsilon;
}
-
+
if (dropx) {
int xreplace = lastData[MotionEvent.SAMPLE_X];
int yreplace = lastData[MotionEvent.SAMPLE_Y];
int distance = Math.abs(yreplace - y);
for (int j = 1; j < lastNumPointers; j++) {
final int joff = j * MotionEvent.NUM_SAMPLE_DATA;
- int lasty = lastData[joff + MotionEvent.SAMPLE_Y];
+ int lasty = lastData[joff + MotionEvent.SAMPLE_Y];
int currDist = Math.abs(lasty - y);
if (currDist < distance) {
xreplace = lastData[joff + MotionEvent.SAMPLE_X];
@@ -354,7 +359,7 @@ public class InputDevice {
distance = currDist;
}
}
-
+
int badXDelta = Math.abs(xreplace - x);
if (badXDelta > badPointerDistance) {
badPointerDistance = badXDelta;
@@ -368,7 +373,7 @@ public class InputDevice {
int distance = Math.abs(xreplace - x);
for (int j = 1; j < lastNumPointers; j++) {
final int joff = j * MotionEvent.NUM_SAMPLE_DATA;
- int lastx = lastData[joff + MotionEvent.SAMPLE_X];
+ int lastx = lastData[joff + MotionEvent.SAMPLE_X];
int currDist = Math.abs(lastx - x);
if (currDist < distance) {
xreplace = lastx;
@@ -376,7 +381,7 @@ public class InputDevice {
distance = currDist;
}
}
-
+
int badYDelta = Math.abs(yreplace - y);
if (badYDelta > badPointerDistance) {
badPointerDistance = badYDelta;
@@ -402,7 +407,7 @@ public class InputDevice {
mJumpyPointsDropped = 0;
}
}
-
+
/**
* Special hack for devices that have bad screen data: aggregate and
* compute averages of the coordinate data, to reduce the amount of
@@ -484,7 +489,7 @@ public class InputDevice {
}
}
}
-
+
// Now compute the average.
int start = mHistoryDataStart[i];
int end = mHistoryDataEnd[i];
@@ -519,7 +524,7 @@ public class InputDevice {
}
return mAveragedData;
}
-
+
private boolean assignPointer(int nextIndex, boolean allowOverlap) {
final int lastNumPointers = mLastNumPointers;
final int[] next2Last = mNext2Last;
@@ -528,12 +533,12 @@ public class InputDevice {
final int[] lastData = mLastData;
final int[] nextData = mNextData;
final int id = nextIndex * MotionEvent.NUM_SAMPLE_DATA;
-
+
if (DEBUG_POINTERS) Slog.v("InputDevice", "assignPointer: nextIndex="
+ nextIndex + " dataOff=" + id);
final int x1 = nextData[id + MotionEvent.SAMPLE_X];
final int y1 = nextData[id + MotionEvent.SAMPLE_Y];
-
+
long bestDistance = -1;
int bestIndex = -1;
for (int j=0; j<lastNumPointers; j++) {
@@ -552,51 +557,51 @@ public class InputDevice {
bestIndex = j;
}
}
-
+
if (DEBUG_POINTERS) Slog.v("InputDevice", "New index " + nextIndex
+ " best old index=" + bestIndex + " (distance="
+ bestDistance + ")");
next2Last[nextIndex] = bestIndex;
next2LastDistance[nextIndex] = bestDistance;
-
+
if (bestIndex < 0) {
return true;
}
-
+
if (last2Next[bestIndex] == -1) {
last2Next[bestIndex] = nextIndex;
return false;
}
-
+
if (DEBUG_POINTERS) Slog.v("InputDevice", "Old index " + bestIndex
+ " has multiple best new pointers!");
-
+
last2Next[bestIndex] = -2;
return true;
}
-
+
private int updatePointerIdentifiers() {
final int[] lastData = mLastData;
final int[] nextData = mNextData;
final int nextNumPointers = mNextNumPointers;
final int lastNumPointers = mLastNumPointers;
-
+
if (nextNumPointers == 1 && lastNumPointers == 1) {
System.arraycopy(nextData, 0, lastData, 0,
MotionEvent.NUM_SAMPLE_DATA);
return -1;
}
-
+
// Clear our old state.
final int[] last2Next = mLast2Next;
for (int i=0; i<lastNumPointers; i++) {
last2Next[i] = -1;
}
-
+
if (DEBUG_POINTERS) Slog.v("InputDevice",
"Update pointers: lastNumPointers=" + lastNumPointers
+ " nextNumPointers=" + nextNumPointers);
-
+
// Figure out the closes new points to the previous points.
final int[] next2Last = mNext2Last;
final long[] next2LastDistance = mNext2LastDistance;
@@ -604,25 +609,25 @@ public class InputDevice {
for (int i=0; i<nextNumPointers; i++) {
conflicts |= assignPointer(i, true);
}
-
+
// Resolve ambiguities in pointer mappings, when two or more
// new pointer locations find their best previous location is
// the same.
if (conflicts) {
if (DEBUG_POINTERS) Slog.v("InputDevice", "Resolving conflicts");
-
+
for (int i=0; i<lastNumPointers; i++) {
if (last2Next[i] != -2) {
continue;
}
-
+
// Note that this algorithm is far from perfect. Ideally
// we should do something like the one described at
// http://portal.acm.org/citation.cfm?id=997856
-
+
if (DEBUG_POINTERS) Slog.v("InputDevice",
"Resolving last index #" + i);
-
+
int numFound;
do {
numFound = 0;
@@ -638,7 +643,7 @@ public class InputDevice {
worstJ = j;
}
}
-
+
if (worstJ >= 0) {
if (DEBUG_POINTERS) Slog.v("InputDevice",
"Worst new pointer: " + worstJ
@@ -652,9 +657,9 @@ public class InputDevice {
} while (numFound > 2);
}
}
-
+
int retIndex = -1;
-
+
if (lastNumPointers < nextNumPointers) {
// We have one or more new pointers that are down. Create a
// new pointer identifier for one of them.
@@ -678,14 +683,14 @@ public class InputDevice {
i++;
nextId++;
}
-
+
if (DEBUG_POINTERS) Slog.v("InputDevice",
"New pointer id " + nextId + " at index " + i);
-
+
mLastNumPointers++;
retIndex = i;
mPointerIds[i] = nextId;
-
+
// And assign this identifier to the first new pointer.
for (int j=0; j<nextNumPointers; j++) {
if (next2Last[j] < 0) {
@@ -696,7 +701,7 @@ public class InputDevice {
}
}
}
-
+
// Propagate all of the current data into the appropriate
// location in the old data to match the pointer ID that was
// assigned to it.
@@ -711,7 +716,7 @@ public class InputDevice {
MotionEvent.NUM_SAMPLE_DATA);
}
}
-
+
if (lastNumPointers > nextNumPointers) {
// One or more pointers has gone up. Find the first one,
// and adjust accordingly.
@@ -725,10 +730,10 @@ public class InputDevice {
}
}
}
-
+
return retIndex;
}
-
+
void removeOldPointer(int index) {
final int lastNumPointers = mLastNumPointers;
if (index >= 0 && index < lastNumPointers) {
@@ -740,20 +745,20 @@ public class InputDevice {
mLastNumPointers--;
}
}
-
+
MotionEvent generateAbsMotion(InputDevice device, long curTime,
long curTimeNano, Display display, int orientation,
int metaState) {
-
+ boolean isMouse = (device.classes & RawInputEvent.CLASS_MOUSE) != 0;
if (mSkipLastPointers) {
mSkipLastPointers = false;
mLastNumPointers = 0;
}
-
- if (mNextNumPointers <= 0 && mLastNumPointers <= 0) {
+
+ if (!isMouse && (mNextNumPointers <= 0 && mLastNumPointers <= 0)) {
return null;
}
-
+
final int lastNumPointers = mLastNumPointers;
final int nextNumPointers = mNextNumPointers;
if (mNextNumPointers > MAX_POINTERS) {
@@ -761,24 +766,28 @@ public class InputDevice {
+ " exceeded maximum of " + MAX_POINTERS);
mNextNumPointers = MAX_POINTERS;
}
-
- int upOrDownPointer = updatePointerIdentifiers();
-
+
+ /*
+ * This is not used for mouse
+ */
+ int upOrDownPointer = isMouse ? 0 : updatePointerIdentifiers();
+
final float[] reportData = mReportData;
final int[] rawData;
- if (KeyInputQueue.BAD_TOUCH_HACK) {
+ if (!isMouse && KeyInputQueue.BAD_TOUCH_HACK) {
rawData = generateAveragedData(upOrDownPointer, lastNumPointers,
nextNumPointers);
} else {
- rawData = mLastData;
+ rawData = isMouse ? mNextData : mLastData;
}
-
- final int numPointers = mLastNumPointers;
-
- if (DEBUG_POINTERS) Slog.v("InputDevice", "Processing "
+
+ final int numPointers = isMouse ? 1 : mLastNumPointers;
+
+ if (DEBUG_POINTERS || DEBUG_MOUSE)
+ Slog.v("InputDevice", "Processing "
+ numPointers + " pointers (going from " + lastNumPointers
- + " to " + nextNumPointers + ")");
-
+ + " to " + nextNumPointers + ")" + " touch hack "
+ + KeyInputQueue.BAD_TOUCH_HACK);
for (int i=0; i<numPointers; i++) {
final int pos = i * MotionEvent.NUM_SAMPLE_DATA;
reportData[pos + MotionEvent.SAMPLE_X] = rawData[pos + MotionEvent.SAMPLE_X];
@@ -786,31 +795,50 @@ public class InputDevice {
reportData[pos + MotionEvent.SAMPLE_PRESSURE] = rawData[pos + MotionEvent.SAMPLE_PRESSURE];
reportData[pos + MotionEvent.SAMPLE_SIZE] = rawData[pos + MotionEvent.SAMPLE_SIZE];
}
-
+
int action;
int edgeFlags = 0;
- if (nextNumPointers != lastNumPointers) {
- if (nextNumPointers > lastNumPointers) {
- if (lastNumPointers == 0) {
- action = MotionEvent.ACTION_DOWN;
- mDownTime = curTime;
+ if (!isMouse) {
+ if (nextNumPointers != lastNumPointers) {
+ if (nextNumPointers > lastNumPointers) {
+ if (lastNumPointers == 0) {
+ action = MotionEvent.ACTION_DOWN;
+ mDownTime = curTime;
+ } else {
+ action = MotionEvent.ACTION_POINTER_DOWN
+ | (upOrDownPointer << MotionEvent.ACTION_POINTER_ID_SHIFT);
+ }
} else {
- action = MotionEvent.ACTION_POINTER_DOWN
+ if (numPointers == 1) {
+ action = MotionEvent.ACTION_UP;
+ } else {
+ action = MotionEvent.ACTION_POINTER_UP
| (upOrDownPointer << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
+ }
}
+ currentMove = null;
} else {
- if (numPointers == 1) {
+ action = MotionEvent.ACTION_MOVE;
+ }
+ } else {
+ if (mNextNumPointers != mLastNumPointers) {
+ if (mNextNumPointers == 1) {
+ action = MotionEvent.ACTION_DOWN;
+ mDownTime = curTime;
+ } else if (mNextNumPointers == 2) {
action = MotionEvent.ACTION_UP;
} else {
- action = MotionEvent.ACTION_POINTER_UP
- | (upOrDownPointer << MotionEvent.ACTION_POINTER_INDEX_SHIFT);
+ action = MotionEvent.ACTION_MOVE;
}
+ mLastNumPointers = mNextNumPointers;
+ currentMove = null;
+ } else {
+ action = MotionEvent.ACTION_MOVE;
}
- currentMove = null;
- } else {
- action = MotionEvent.ACTION_MOVE;
+ if (DEBUG_MOUSE)
+ Slog.i(TAG, "mouse action " + action);
}
-
+
final int dispW = display.getWidth()-1;
final int dispH = display.getHeight()-1;
int w = dispW;
@@ -821,14 +849,14 @@ public class InputDevice {
w = h;
h = tmp;
}
-
+
final AbsoluteInfo absX = device.absX;
final AbsoluteInfo absY = device.absY;
final AbsoluteInfo absPressure = device.absPressure;
final AbsoluteInfo absSize = device.absSize;
for (int i=0; i<numPointers; i++) {
final int j = i * MotionEvent.NUM_SAMPLE_DATA;
-
+
if (absX != null) {
reportData[j + MotionEvent.SAMPLE_X] =
((reportData[j + MotionEvent.SAMPLE_X]-absX.minValue)
@@ -840,16 +868,16 @@ public class InputDevice {
/ absY.range) * h;
}
if (absPressure != null) {
- reportData[j + MotionEvent.SAMPLE_PRESSURE] =
+ reportData[j + MotionEvent.SAMPLE_PRESSURE] =
((reportData[j + MotionEvent.SAMPLE_PRESSURE]-absPressure.minValue)
/ (float)absPressure.range);
}
if (absSize != null) {
- reportData[j + MotionEvent.SAMPLE_SIZE] =
+ reportData[j + MotionEvent.SAMPLE_SIZE] =
((reportData[j + MotionEvent.SAMPLE_SIZE]-absSize.minValue)
/ (float)absSize.range);
}
-
+
switch (orientation) {
case Surface.ROTATION_90: {
final float temp = reportData[j + MotionEvent.SAMPLE_X];
@@ -870,7 +898,7 @@ public class InputDevice {
}
}
}
-
+
// We only consider the first pointer when computing the edge
// flags, since they are global to the event.
if (action == MotionEvent.ACTION_DOWN) {
@@ -885,9 +913,9 @@ public class InputDevice {
edgeFlags |= MotionEvent.EDGE_BOTTOM;
}
}
-
+
if (currentMove != null) {
- if (false) Slog.i("InputDevice", "Adding batch x="
+ if (DEBUG_MOUSE) Slog.i("InputDevice", "Adding batch x="
+ reportData[MotionEvent.SAMPLE_X]
+ " y=" + reportData[MotionEvent.SAMPLE_Y]
+ " to " + currentMove);
@@ -897,42 +925,42 @@ public class InputDevice {
}
return null;
}
-
+
MotionEvent me = MotionEvent.obtainNano(mDownTime, curTime,
curTimeNano, action, numPointers, mPointerIds, reportData,
metaState, xPrecision, yPrecision, device.id, edgeFlags);
if (action == MotionEvent.ACTION_MOVE) {
currentMove = me;
}
-
- if (nextNumPointers < lastNumPointers) {
+
+ if ((!isMouse) && (nextNumPointers < lastNumPointers)) {
removeOldPointer(upOrDownPointer);
}
-
+
return me;
}
-
+
boolean hasMore() {
return mLastNumPointers != mNextNumPointers;
}
-
+
void finish() {
mNextNumPointers = mAddingPointerOffset = 0;
mNextData[MotionEvent.SAMPLE_PRESSURE] = 0;
}
-
+
MotionEvent generateRelMotion(InputDevice device, long curTime,
long curTimeNano, int orientation, int metaState) {
-
+
final float[] scaled = mReportData;
-
+
// For now we only support 1 pointer with relative motions.
scaled[MotionEvent.SAMPLE_X] = mNextData[MotionEvent.SAMPLE_X];
scaled[MotionEvent.SAMPLE_Y] = mNextData[MotionEvent.SAMPLE_Y];
scaled[MotionEvent.SAMPLE_PRESSURE] = 1.0f;
scaled[MotionEvent.SAMPLE_SIZE] = 0;
int edgeFlags = 0;
-
+
int action;
if (mNextNumPointers != mLastNumPointers) {
mNextData[MotionEvent.SAMPLE_X] =
@@ -950,7 +978,7 @@ public class InputDevice {
} else {
action = MotionEvent.ACTION_MOVE;
}
-
+
scaled[MotionEvent.SAMPLE_X] *= xMoveScale;
scaled[MotionEvent.SAMPLE_Y] *= yMoveScale;
switch (orientation) {
@@ -972,7 +1000,7 @@ public class InputDevice {
break;
}
}
-
+
if (currentMove != null) {
if (false) Slog.i("InputDevice", "Adding batch x="
+ scaled[MotionEvent.SAMPLE_X]
@@ -984,7 +1012,7 @@ public class InputDevice {
}
return null;
}
-
+
MotionEvent me = MotionEvent.obtainNano(mDownTime, curTime,
curTimeNano, action, 1, mPointerIds, scaled, metaState,
xPrecision, yPrecision, device.id, edgeFlags);
@@ -994,14 +1022,14 @@ public class InputDevice {
return me;
}
}
-
+
static class AbsoluteInfo {
int minValue;
int maxValue;
int range;
int flat;
int fuzz;
-
+
final void dump(PrintWriter pw) {
pw.print("minValue="); pw.print(minValue);
pw.print(" maxValue="); pw.print(maxValue);
@@ -1010,7 +1038,7 @@ public class InputDevice {
pw.print(" fuzz="); pw.print(fuzz);
}
};
-
+
InputDevice(int _id, int _classes, String _name,
AbsoluteInfo _absX, AbsoluteInfo _absY,
AbsoluteInfo _absPressure, AbsoluteInfo _absSize) {
diff --git a/services/java/com/android/server/KeyInputQueue.java b/services/java/com/android/server/KeyInputQueue.java
index f30346b..5d0d127 100644
--- a/services/java/com/android/server/KeyInputQueue.java
+++ b/services/java/com/android/server/KeyInputQueue.java
@@ -50,10 +50,13 @@ import java.util.ArrayList;
public abstract class KeyInputQueue {
static final String TAG = "KeyInputQueue";
+ static final int UPKEY_KEYWORD = 19;
+ static final int DOWNKEY_KEYWORD = 20;
static final boolean DEBUG = false;
static final boolean DEBUG_VIRTUAL_KEYS = false;
static final boolean DEBUG_POINTERS = false;
+ static final boolean DEBUG_MOUSE = false;
/**
* Turn on some hacks we have to improve the touch interaction with a
@@ -85,6 +88,8 @@ public abstract class KeyInputQueue {
Display mDisplay = null;
int mDisplayWidth;
int mDisplayHeight;
+ int mCx;
+ int mCy;
int mOrientation = Surface.ROTATION_0;
int[] mKeyRotationMap = null;
@@ -322,6 +327,8 @@ public abstract class KeyInputQueue {
// buttons based on that display.
mDisplayWidth = display.getWidth();
mDisplayHeight = display.getHeight();
+ mCx = mDisplayWidth / 2;
+ mCy = mDisplayHeight / 2;
}
public void getInputConfiguration(Configuration config) {
@@ -639,11 +646,35 @@ public abstract class KeyInputQueue {
di.mAbs.mDown[0] = ev.value != 0;
// Trackball (mouse) protocol: press down or up.
- } else if (ev.scancode == RawInputEvent.BTN_MOUSE &&
- (classes&RawInputEvent.CLASS_TRACKBALL) != 0) {
- di.mRel.changed = true;
- di.mRel.mNextNumPointers = ev.value != 0 ? 1 : 0;
- send = true;
+ } else if (ev.scancode == RawInputEvent.BTN_MOUSE) {
+ if ((classes&RawInputEvent.CLASS_TRACKBALL) != 0) {
+ di.mRel.changed = true;
+ di.mRel.mNextNumPointers = ev.value != 0 ? 1 : 0;
+ send = true;
+ } else if ((classes&RawInputEvent.CLASS_MOUSE) != 0) {
+ if (DEBUG_MOUSE)
+ Slog.i(TAG, "Mouse key event found, down:"
+ + ev.value + " was :" +
+ di.mAbs.mDown[0] + " Send " + send);
+ di.mAbs.changed = true;
+ di.mAbs.mNextNumPointers = (ev.value != 0) ? 1 : 2;
+ send = true;
+ }
+ } else if ((ev.scancode == RawInputEvent.BTN_RIGHT ||
+ ev.scancode == RawInputEvent.BTN_MIDDLE) &&
+ (classes&RawInputEvent.CLASS_MOUSE) != 0) {
+ boolean down = (ev.value != 0);
+ if (down)
+ di.mKeyDownTime = curTime;
+
+ addLocked(di, curTime, ev.flags,
+ RawInputEvent.CLASS_KEYBOARD,
+ newKeyEvent(di, di.mKeyDownTime, curTime, down,
+ (ev.scancode == RawInputEvent.BTN_RIGHT)
+ ? KeyEvent.KEYCODE_BACK : KeyEvent.KEYCODE_MENU,
+ 0, scancode,
+ ((ev.flags & WindowManagerPolicy.FLAG_WOKE_HERE) != 0)
+ ? KeyEvent.FLAG_WOKE_HERE : 0));
}
// Process position events from multitouch protocol.
@@ -695,15 +726,59 @@ public abstract class KeyInputQueue {
}
// Process movement events from trackball (mouse) protocol.
- } else if (ev.type == RawInputEvent.EV_REL &&
- (classes&RawInputEvent.CLASS_TRACKBALL) != 0) {
- // Add this relative movement into our totals.
- if (ev.scancode == RawInputEvent.REL_X) {
- di.mRel.changed = true;
- di.mRel.mNextData[MotionEvent.SAMPLE_X] += ev.value;
- } else if (ev.scancode == RawInputEvent.REL_Y) {
- di.mRel.changed = true;
- di.mRel.mNextData[MotionEvent.SAMPLE_Y] += ev.value;
+ } else if (ev.type == RawInputEvent.EV_REL) {
+ if (DEBUG_MOUSE)
+ Slog.i(TAG, "rel event found, class :" + classes + " mouse value: " + RawInputEvent.CLASS_MOUSE);
+ if ((classes&RawInputEvent.CLASS_TRACKBALL) != 0) {
+ // Add this relative movement into our totals.
+ if (ev.scancode == RawInputEvent.REL_X) {
+ di.mRel.changed = true;
+ di.mRel.mNextData[MotionEvent.SAMPLE_X] += ev.value;
+ } else if (ev.scancode == RawInputEvent.REL_Y) {
+ di.mRel.changed = true;
+ di.mRel.mNextData[MotionEvent.SAMPLE_Y] += ev.value;
+ }
+ } else if ((classes&RawInputEvent.CLASS_MOUSE) != 0) {
+ if (ev.scancode == RawInputEvent.REL_X) {
+ di.mAbs.changed = true;
+ mCx += (int)ev.value;
+ mCx = ((mCx < 0) ? 0 : (mCx >= mDisplayWidth ? mDisplayWidth - 1 : mCx));
+ di.mAbs.mNextData[MotionEvent.SAMPLE_X] = mCx;
+ } else if (ev.scancode == RawInputEvent.REL_Y) {
+ di.mAbs.changed = true;
+ mCy += (int)ev.value;
+ mCy = ((mCy < 0) ? 0 : (mCy >= mDisplayHeight ? mDisplayHeight - 1 : mCy));
+ di.mAbs.mNextData[MotionEvent.SAMPLE_Y] = mCy;
+ } else if (ev.scancode == RawInputEvent.REL_WHEEL &&
+ (classes&RawInputEvent.CLASS_MOUSE) != 0) {
+ boolean down;
+ int keycode;
+ if (ev.value != 0) {
+ down = true;
+ di.mKeyDownTime = curTime;
+ } else {
+ down = false;
+ }
+ if (ev.value < 0){
+ keycode = rotateKeyCodeLocked(DOWNKEY_KEYWORD);
+ } else if(ev.value > 0){
+ keycode = rotateKeyCodeLocked(UPKEY_KEYWORD);
+ } else {
+ keycode = rotateKeyCodeLocked(ev.keycode);
+ }
+ addLocked(di, curTime, ev.flags,
+ RawInputEvent.CLASS_KEYBOARD,
+ newKeyEvent(di, di.mKeyDownTime, curTime, down,
+ keycode, 0, scancode,
+ ((ev.flags & WindowManagerPolicy.FLAG_WOKE_HERE) != 0)
+ ? KeyEvent.FLAG_WOKE_HERE : 0));
+ addLocked(di, curTime, ev.flags,
+ RawInputEvent.CLASS_KEYBOARD,
+ newKeyEvent(di, di.mKeyDownTime, curTime, !down,
+ keycode, 0, scancode,
+ ((ev.flags & WindowManagerPolicy.FLAG_WOKE_HERE) != 0)
+ ? KeyEvent.FLAG_WOKE_HERE : 0));
+ }
}
}
@@ -790,7 +865,8 @@ public abstract class KeyInputQueue {
me = ms.generateAbsMotion(di, curTime,
curTimeNano, mDisplay,
mOrientation, mGlobalMetaState);
- if (DEBUG_POINTERS) Slog.v(TAG, "Absolute: x="
+ if (DEBUG_POINTERS || DEBUG_MOUSE)
+ Slog.v(TAG, "Absolute: x="
+ di.mAbs.mNextData[MotionEvent.SAMPLE_X]
+ " y="
+ di.mAbs.mNextData[MotionEvent.SAMPLE_Y]
@@ -799,8 +875,15 @@ public abstract class KeyInputQueue {
if (WindowManagerPolicy.WATCH_POINTER) {
Slog.i(TAG, "Enqueueing: " + me);
}
- addLocked(di, curTimeNano, ev.flags,
- RawInputEvent.CLASS_TOUCHSCREEN, me);
+ if ((classes & RawInputEvent.CLASS_TOUCHSCREEN) != 0) {
+ addLocked(di, curTime, ev.flags,
+ RawInputEvent.CLASS_TOUCHSCREEN, me);
+ } else if ((classes & RawInputEvent.CLASS_MOUSE) != 0) {
+ addLocked(di, curTime, ev.flags,
+ RawInputEvent.CLASS_MOUSE, me);
+ } else {
+ Slog.w(TAG, "Unknown classes? " + classes);
+ }
}
} while (ms.hasMore());
} else {
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 73d17ea..b284ac9 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -1068,9 +1068,11 @@ class NotificationManagerService extends INotificationManager.Stub
}
}
+ int mPulseScreen = Settings.System.getInt(mContext.getContentResolver(), Settings.System.TRACKBALL_SCREEN_ON, 0);
+
// we only flash if screen is off and persistent pulsing is enabled
// and we are not currently in a call
- if (mLedNotification == null || mScreenOn || mInCall) {
+ if (mLedNotification == null || (mScreenOn && (mPulseScreen == 0)) || mInCall) {
mNotificationLight.turnOff();
} else {
int ledARGB = mLedNotification.notification.ledARGB;
@@ -1120,7 +1122,9 @@ class NotificationManagerService extends INotificationManager.Stub
// to accidentally lose.
private void updateAdbNotification() {
if (mAdbEnabled && mUsbConnected) {
- if ("0".equals(SystemProperties.get("persist.adb.notify"))) {
+ if ("0".equals(SystemProperties.get("persist.adb.notify")) ||
+ Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.ADB_NOTIFY, 1) == 0) {
return;
}
if (!mAdbNotificationShown) {
@@ -1137,7 +1141,6 @@ class NotificationManagerService extends INotificationManager.Stub
mAdbNotification = new Notification();
mAdbNotification.icon = com.android.internal.R.drawable.stat_sys_adb;
mAdbNotification.when = 0;
- mAdbNotification.flags = Notification.FLAG_ONGOING_EVENT;
mAdbNotification.tickerText = title;
mAdbNotification.defaults = 0; // please be quiet
mAdbNotification.sound = null;
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 0b84c8d..136a042 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -962,13 +962,13 @@ class PackageManagerService extends IPackageManager.Stub {
SystemClock.uptimeMillis());
mAppInstallObserver = new AppDirObserver(
mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
- mAppInstallObserver.startWatching();
scanDirLI(mAppInstallDir, 0, scanMode);
+ mAppInstallObserver.startWatching();
mDrmAppInstallObserver = new AppDirObserver(
mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
- mDrmAppInstallObserver.startWatching();
scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK, scanMode);
+ mDrmAppInstallObserver.startWatching();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
SystemClock.uptimeMillis());
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 493a348..986b157 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -2113,8 +2113,11 @@ class PowerManagerService extends IPowerManager.Stub
Slog.d(TAG, "lightSensorChangedLocked " + value);
}
- // do not allow light sensor value to decrease
- if (mHighestLightSensorValue < value) {
+ // do not allow light sensor value to decrease unless the environment it's very dark
+ if (value < 200) {
+ mHighestLightSensorValue = value;
+ }
+ else if (mHighestLightSensorValue < value) {
mHighestLightSensorValue = value;
}
diff --git a/services/java/com/android/server/ProcessStats.java b/services/java/com/android/server/ProcessStats.java
index a02c4e7..a155f59 100644
--- a/services/java/com/android/server/ProcessStats.java
+++ b/services/java/com/android/server/ProcessStats.java
@@ -138,7 +138,7 @@ public class ProcessStats {
private boolean mFirst = true;
- private byte[] mBuffer = new byte[256];
+ private byte[] mBuffer = new byte[1024];
/**
* The time in microseconds that the CPU has been running at each speed.
@@ -502,7 +502,7 @@ public class ProcessStats {
private long[] getCpuSpeedTimes(long[] out) {
long[] tempTimes = out;
long[] tempSpeeds = mCpuSpeeds;
- final int MAX_SPEEDS = 20;
+ final int MAX_SPEEDS = 30;
if (out == null) {
tempTimes = new long[MAX_SPEEDS]; // Hopefully no more than that
tempSpeeds = new long[MAX_SPEEDS];
@@ -514,20 +514,22 @@ public class ProcessStats {
StringTokenizer st = new StringTokenizer(file, "\n ");
while (st.hasMoreElements()) {
String token = st.nextToken();
- try {
- long val = Long.parseLong(token);
- tempSpeeds[speed] = val;
- token = st.nextToken();
- val = Long.parseLong(token);
- tempTimes[speed] = val;
- speed++;
- if (speed == MAX_SPEEDS) break; // No more
- if (localLOGV && out == null) {
- Slog.v(TAG, "First time : Speed/Time = " + tempSpeeds[speed - 1]
- + "\t" + tempTimes[speed - 1]);
+ if (st.hasMoreElements()) {
+ try {
+ long val = Long.parseLong(token);
+ tempSpeeds[speed] = val;
+ token = st.nextToken();
+ val = Long.parseLong(token);
+ tempTimes[speed] = val;
+ speed++;
+ if (speed == MAX_SPEEDS) break; // No more
+ if (localLOGV && out == null) {
+ Slog.v(TAG, "First time : Speed/Time = " + tempSpeeds[speed - 1]
+ + "\t" + tempTimes[speed - 1]);
+ }
+ } catch (NumberFormatException nfe) {
+ Slog.i(TAG, "Unable to parse time_in_state");
}
- } catch (NumberFormatException nfe) {
- Slog.i(TAG, "Unable to parse time_in_state");
}
}
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 9d5d035..b7a7bbf 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -39,6 +39,7 @@ import android.os.*;
import android.provider.Contacts.People;
import android.provider.Settings;
import android.server.BluetoothA2dpService;
+import android.server.BluetoothHidService;
import android.server.BluetoothService;
import android.server.search.SearchManagerService;
import android.util.EventLog;
@@ -95,6 +96,7 @@ class ServerThread extends Thread {
WindowManagerService wm = null;
BluetoothService bluetooth = null;
BluetoothA2dpService bluetoothA2dp = null;
+ BluetoothHidService bluetoothHid = null;
HeadsetObserver headset = null;
DockObserver dock = null;
UiModeManagerService uiMode = null;
@@ -193,6 +195,10 @@ class ServerThread extends Thread {
bluetoothA2dp = new BluetoothA2dpService(context, bluetooth);
ServiceManager.addService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE,
bluetoothA2dp);
+ bluetoothHid = new BluetoothHidService(context, bluetooth);
+ ServiceManager.addService(BluetoothHidService.BLUETOOTH_HID_SERVICE,
+ bluetoothHid);
+ //Log.e(TAG, "Bluetooth HID Service");
int bluetoothOn = Settings.Secure.getInt(mContentResolver,
Settings.Secure.BLUETOOTH_ON, 0);
@@ -442,7 +448,7 @@ class ServerThread extends Thread {
// Enable the JIT for the system_server process
VMRuntime.getRuntime().startJitCompilation();
}
-
+
// It is now time to start up the app processes...
if (devicePolicy != null) {
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index a93a6ee..5b89ee0 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -900,7 +900,12 @@ public class ThrottleService extends IThrottleManager.Stub {
dataFile = new File(throttleDir, imsiHash);
}
// touch the file so it's not LRU
- dataFile.setLastModified(System.currentTimeMillis());
+ if (System.currentTimeMillis() >= 0) {
+ dataFile.setLastModified(System.currentTimeMillis());
+ } else {
+ // system clock is out of whack, but that doesn't mean we can't boot
+ dataFile.setLastModified(Long.MAX_VALUE);
+ }
checkAndDeleteLRUDataFile(throttleDir);
return dataFile;
}
diff --git a/services/java/com/android/server/VibratorService.java b/services/java/com/android/server/VibratorService.java
index 2e7e3e1..379c158 100755
--- a/services/java/com/android/server/VibratorService.java
+++ b/services/java/com/android/server/VibratorService.java
@@ -123,8 +123,17 @@ public class VibratorService extends IVibratorService.Stub {
return;
}
Vibration vib = new Vibration(token, milliseconds);
+ try {
+ token.linkToDeath(vib, 0);
+ } catch (RemoteException e) {
+ return;
+ }
synchronized (mVibrations) {
removeVibrationLocked(token);
+ if ((mCurrentVibration != null) && (mThread == null)) {
+ mCurrentVibration.mToken.unlinkToDeath(mCurrentVibration, 0);
+ mCurrentVibration = null;
+ }
doCancelVibrateLocked();
mCurrentVibration = vib;
startVibrationLocked(vib);
@@ -174,6 +183,10 @@ public class VibratorService extends IVibratorService.Stub {
synchronized (mVibrations) {
removeVibrationLocked(token);
+ if ((mCurrentVibration != null) && (mThread == null)) {
+ mCurrentVibration.mToken.unlinkToDeath(mCurrentVibration, 0);
+ mCurrentVibration = null;
+ }
doCancelVibrateLocked();
if (repeat >= 0) {
mVibrations.addFirst(vib);
@@ -205,6 +218,10 @@ public class VibratorService extends IVibratorService.Stub {
doCancelVibrateLocked();
startNextVibrationLocked();
}
+ if ((mCurrentVibration != null) && (mThread == null)) {
+ mCurrentVibration.mToken.unlinkToDeath(mCurrentVibration, 0);
+ mCurrentVibration = null;
+ }
}
}
finally {
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index a8dad88..0715340 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -64,6 +64,7 @@ import android.content.pm.PackageManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Matrix;
+import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Region;
@@ -133,6 +134,9 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import android.graphics.Canvas;
+import android.graphics.Path;
+
/** {@hide} */
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, KeyInputQueue.HapticFeedbackCallback {
@@ -387,6 +391,13 @@ public class WindowManagerService extends IWindowManager.Stub
Surface mBlurSurface;
boolean mBlurShown;
+ Surface mMouseSurface;
+ boolean mMouseDisplayed = false;
+ int mMlx;
+ int mMly;
+ int mMlw;
+ int mMlh;
+
int mTransactionSequence = 0;
final float[] mTmpFloats = new float[9];
@@ -2148,6 +2159,7 @@ public class WindowManagerService extends IWindowManager.Stub
private void removeWindowInnerLocked(Session session, WindowState win) {
mKeyWaiter.finishedKey(session, win.mClient, true,
KeyWaiter.RETURN_NOTHING);
+ mKeyWaiter.releaseMotionTarget(win);
mKeyWaiter.releasePendingPointerLocked(win.mSession);
mKeyWaiter.releasePendingTrackballLocked(win.mSession);
@@ -5260,7 +5272,7 @@ public class WindowManagerService extends IWindowManager.Stub
// dispatch the event.
try {
if (DEBUG_INPUT || DEBUG_FOCUS || WindowManagerPolicy.WATCH_POINTER) {
- Slog.v(TAG, "Delivering pointer " + qev + " to " + target);
+ Slog.v(TAG, "Delivering pointer " + qev + " Ev " + ev + " to " + target);
}
if (MEASURE_LATENCY) {
@@ -6119,6 +6131,12 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ void releaseMotionTarget(WindowState win) {
+ if (mMotionTarget == win) {
+ mMotionTarget = null;
+ }
+ }
+
MotionEvent finishedKey(Session session, IWindow client, boolean force,
int returnWhat) {
if (DEBUG_INPUT) Slog.v(
@@ -6169,7 +6187,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (qev != null) {
res = (MotionEvent)qev.event;
if (DEBUG_INPUT) Slog.v(TAG,
- "Returning pending motion: " + res);
+ "Returning pending motion: " + res + " q: " + qev);
mQueue.recycleEvent(qev);
if (win != null && returnWhat == RETURN_PENDING_POINTER) {
res.offsetLocation(-win.mFrame.left, -win.mFrame.top);
@@ -6394,7 +6412,8 @@ public class WindowManagerService extends IWindowManager.Stub
if (screenIsOff) {
if (!mPolicy.isWakeRelMovementTq(event.deviceId,
device.classes, event)) {
- //Slog.i(TAG, "dropping because screenIsOff and !isWakeKey");
+ if (DEBUG_INPUT)
+ Slog.i(TAG, "dropping because screenIsOff and !isWakeKey");
return false;
}
event.flags |= WindowManagerPolicy.FLAG_WOKE_HERE;
@@ -6540,7 +6559,8 @@ public class WindowManagerService extends IWindowManager.Stub
if (ev.classType == RawInputEvent.CLASS_TOUCHSCREEN) {
eventType = eventType((MotionEvent)ev.event);
} else if (ev.classType == RawInputEvent.CLASS_KEYBOARD ||
- ev.classType == RawInputEvent.CLASS_TRACKBALL) {
+ ev.classType == RawInputEvent.CLASS_TRACKBALL ||
+ ev.classType == RawInputEvent.CLASS_MOUSE) {
eventType = LocalPowerManager.BUTTON_EVENT;
} else {
eventType = LocalPowerManager.OTHER_EVENT;
@@ -6600,6 +6620,44 @@ public class WindowManagerService extends IWindowManager.Stub
case RawInputEvent.CLASS_TOUCHSCREEN:
//Slog.i(TAG, "Read next event " + ev);
dispatchPointer(ev, (MotionEvent)ev.event, 0, 0);
+ if (mMouseDisplayed) {
+ Surface.openTransaction();
+ mMouseSurface.hide();
+ Surface.closeTransaction();
+ mMouseDisplayed = false;
+ }
+ break;
+ case RawInputEvent.CLASS_MOUSE:
+ MotionEvent mmev = (MotionEvent)ev.event;
+ int mcx = (int)mmev.getX();
+ int mcy = (int)mmev.getY();
+
+ if (mMouseSurface != null && (mMlx != mcx || mMly != mcy)) {
+ Surface.openTransaction();
+ if (DEBUG_INPUT)
+ Slog.i(TAG, "Open transaction for the mouse surface");
+ WindowState top =
+ (WindowState)mWindows.get(mWindows.size() - 1);
+ try {
+ if (DEBUG_INPUT)
+ Slog.i(TAG, "Move surf, x: " +
+ Integer.toString(mcx) + " y:"
+ + Integer.toString(mcy));
+
+ mMouseSurface.setPosition(mcx, mcy);
+ mMouseSurface.setLayer(top.mAnimLayer + 1);
+ if (!mMouseDisplayed) {
+ mMouseSurface.show();
+ mMouseDisplayed = true;
+ }
+ mMlx = mcx;
+ mMly = mcy;
+ } catch ( RuntimeException e) {
+ Slog.e(TAG, "Failure showing mouse surface",e);
+ }
+ Surface.closeTransaction();
+ }
+ dispatchPointer(ev, (MotionEvent)ev.event, 0, 0);
break;
case RawInputEvent.CLASS_TRACKBALL:
dispatchTrackball(ev, (MotionEvent)ev.event, 0, 0);
@@ -9584,6 +9642,61 @@ public class WindowManagerService extends IWindowManager.Stub
mFxSession = new SurfaceSession();
}
+ if (mMouseSurface == null) {
+ int mMx, mMy, mMw, mMh;
+ Canvas mCanvas;
+ Path mPath = new Path();
+
+ if (DEBUG_INPUT)
+ Slog.i(TAG, "Create Mouse Surface");
+
+ mMw = 12;
+ mMh = 20;
+ mMx = (mDisplay.getWidth() - mMw) / 2;
+ mMy = (mDisplay.getHeight() - mMh) / 2;
+
+ try {
+
+ /*
+ *First Mouse event, create Surface
+ */
+
+ mMouseSurface =
+ new Surface(mFxSession,
+ 0, -1, mMw, mMh,
+ PixelFormat.TRANSPARENT,
+ Surface.FX_SURFACE_NORMAL);
+ mCanvas = mMouseSurface.lockCanvas(null);
+ Paint tPaint = new Paint();
+ tPaint.setStyle(Paint.Style.STROKE);
+ tPaint.setStrokeWidth(2);
+ tPaint.setColor(0xffffffff);
+ mPath.moveTo(0.0f, 0.0f);
+ mPath.lineTo(12.0f, 12.0f);
+ mPath.lineTo(7.0f, 12.0f);
+ mPath.lineTo(11.0f, 20.0f);
+ mPath.lineTo(8.0f, 21.0f);
+ mPath.lineTo(4.0f, 13.0f);
+ mPath.lineTo(0.0f, 17.0f);
+ mPath.close();
+ mCanvas.clipPath(mPath);
+ mCanvas.drawColor(0xff000000);
+ mCanvas.drawPath(mPath, tPaint);
+
+ mMouseSurface.unlockCanvasAndPost(mCanvas);
+ mMouseSurface.openTransaction();
+ mMouseSurface.setSize(mMw, mMh);
+ mMouseSurface.closeTransaction();
+
+ } catch (Exception e) {
+ Slog.e(TAG, "Exception creating mouse surface",e);
+ }
+ mMlx = mMx;
+ mMly = mMy;
+ mMlw = mMw;
+ mMlh = mMh;
+ }
+
if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
// Initialize state of exiting tokens.
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 0c11940..039ef31 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -52,6 +52,7 @@ import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IIntentReceiver;
@@ -1176,7 +1177,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
d.setCancelable(false);
d.setTitle("System UIDs Inconsistent");
d.setMessage("UIDs on the system are inconsistent, you need to wipe your data partition or your device will be unstable.");
- d.setButton("I'm Feeling Lucky",
+ d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
mUidAlert = d;
d.show();
@@ -5879,10 +5880,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
if (pkgs != null) {
for (String pkg : pkgs) {
- if (forceStopPackageLocked(pkg, -1, false, false, false)) {
- setResultCode(Activity.RESULT_OK);
- return;
- }
+ synchronized (ActivityManagerService.this) {
+ if (forceStopPackageLocked(pkg, -1, false, false, false)) {
+ setResultCode(Activity.RESULT_OK);
+ return;
+ }
+ }
}
}
}
@@ -13814,7 +13817,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
int adj;
int schedGroup;
int N;
- if (app == TOP_APP) {
+ if ("com.android.mms".equals(app.processName)) {
+ // MMS can die in situations of heavy memory pressure.
+ // Always push it to the top.
+ adj = FOREGROUND_APP_ADJ;
+ schedGroup = Process.THREAD_GROUP_DEFAULT;
+ app.adjType = "mms";
+ } else if (app == TOP_APP) {
// The last app on the list is the foreground app.
adj = FOREGROUND_APP_ADJ;
schedGroup = Process.THREAD_GROUP_DEFAULT;
diff --git a/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java b/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java
index 8e9818d..9fb48b3 100644
--- a/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java
+++ b/services/java/com/android/server/am/AppWaitingForDebuggerDialog.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import android.content.Context;
+import android.content.DialogInterface;
import android.os.Handler;
import android.os.Message;
@@ -49,7 +50,7 @@ class AppWaitingForDebuggerDialog extends BaseErrorDialog {
text.append(" is waiting for the debugger to attach.");
setMessage(text.toString());
- setButton("Force Close", mHandler.obtainMessage(1, app));
+ setButton(DialogInterface.BUTTON_POSITIVE, "Force Close", mHandler.obtainMessage(1, app));
setTitle("Waiting For Debugger");
getWindow().setTitle("Waiting For Debugger: " + app.info.processName);
}
diff --git a/services/java/com/android/server/am/FactoryErrorDialog.java b/services/java/com/android/server/am/FactoryErrorDialog.java
index 2e25474..b19bb5c 100644
--- a/services/java/com/android/server/am/FactoryErrorDialog.java
+++ b/services/java/com/android/server/am/FactoryErrorDialog.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import android.content.Context;
+import android.content.DialogInterface;
import android.os.Handler;
import android.os.Message;
@@ -26,7 +27,8 @@ class FactoryErrorDialog extends BaseErrorDialog {
setCancelable(false);
setTitle(context.getText(com.android.internal.R.string.factorytest_failed));
setMessage(msg);
- setButton(context.getText(com.android.internal.R.string.factorytest_reboot),
+ setButton(DialogInterface.BUTTON_POSITIVE,
+ context.getText(com.android.internal.R.string.factorytest_reboot),
mHandler.obtainMessage(0));
getWindow().setTitle("Factory Error");
}
diff --git a/services/java/com/android/server/status/IconData.java b/services/java/com/android/server/status/IconData.java
index fd226f9..9aaaba1 100644
--- a/services/java/com/android/server/status/IconData.java
+++ b/services/java/com/android/server/status/IconData.java
@@ -16,6 +16,7 @@
package com.android.server.status;
+import android.provider.Settings;
import android.util.Slog;
public class IconData {
@@ -30,8 +31,20 @@ public class IconData {
public static final int ICON = 2;
/**
- * The type of this item. One of TEXT, ICON, or LEVEL_ICON.
+ * Indicates ths item represents an integer displayed on top of an icon.
+ */
+ public static final int ICON_NUMBER = 3;
+
+ /**
+ * Default colors to use for any text appearing on each type of icon.
*/
+ private static final int DEFAULT_TEXT_COLOR = 0xff000000;
+ private static final int DEFAULT_ICON_COLOR = 0xffffffff;
+ private static final int DEFAULT_ICON_NUMBER_COLOR = 0xffffffff;
+
+ /**
+ * The type of this item. One of TEXT, ICON, or LEVEL_ICON.
+ */
public int type;
/**
@@ -65,6 +78,23 @@ public class IconData {
*/
public CharSequence text;
+ /**
+ * The default color of any text associated with this icon.
+ */
+ public int textColor;
+
+ /**
+ * The system setting that holds the text color for this icon.
+ */
+ public String colorSetting;
+
+ /**
+ * The system setting that determines whether the icon is visible or not.
+ * Currently this only applies to the TEXT type.
+ */
+ public String visibleSetting;
+ public boolean defVisibility;
+
private IconData() {
}
@@ -77,14 +107,35 @@ public class IconData {
data.iconId = iconId;
data.iconLevel = iconLevel;
data.number = number;
+ data.textColor = DEFAULT_ICON_COLOR;
+ data.colorSetting = Settings.System.NOTIF_COUNT_COLOR;
return data;
}
- public static IconData makeText(String slot, CharSequence text) {
+ public static IconData makeText(String slot, CharSequence text, String colorSetting,
+ String visibleSetting, boolean defVisibility) {
IconData data = new IconData();
data.type = TEXT;
data.slot = slot;
data.text = text;
+ data.textColor = DEFAULT_TEXT_COLOR;
+ data.colorSetting = colorSetting;
+ data.visibleSetting = visibleSetting;
+ data.defVisibility = defVisibility;
+ return data;
+ }
+
+ public static IconData makeIconNumber(String slot,
+ String iconPackage, int iconId, int iconLevel, int number, String colorSetting) {
+ IconData data = new IconData();
+ data.type = ICON_NUMBER;
+ data.slot = slot;
+ data.iconPackage = iconPackage;
+ data.iconId = iconId;
+ data.iconLevel = iconLevel;
+ data.number = number;
+ data.textColor = DEFAULT_ICON_NUMBER_COLOR;
+ data.colorSetting = colorSetting;
return data;
}
@@ -96,6 +147,10 @@ public class IconData {
this.iconLevel = that.iconLevel;
this.number = that.number;
this.text = that.text; // should we clone this?
+ this.textColor = that.textColor;
+ this.colorSetting = that.colorSetting;
+ this.visibleSetting = that.visibleSetting;
+ this.defVisibility = that.defVisibility;
}
public IconData clone() {
@@ -115,6 +170,14 @@ public class IconData {
+ " iconId=" + Integer.toHexString(this.iconId)
+ " iconLevel=" + this.iconLevel + ")";
}
+
+ else if (this.type == ICON_NUMBER) {
+ return "IconData(slot=" + (this.slot != null ? "'" + this.slot + "'" : "null")
+ + " package=" + this.iconPackage
+ + " iconId=" + Integer.toHexString(this.iconId)
+ + " iconLevel=" + this.iconLevel
+ + " number='" + this.number + "')";
+ }
else {
return "IconData(type=" + type + ")";
}
diff --git a/services/java/com/android/server/status/StatusBarIcon.java b/services/java/com/android/server/status/StatusBarIcon.java
index 6f8b8a8..9f49747 100644
--- a/services/java/com/android/server/status/StatusBarIcon.java
+++ b/services/java/com/android/server/status/StatusBarIcon.java
@@ -30,6 +30,11 @@ import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
+import android.graphics.drawable.AnimationDrawable;
+import android.provider.Settings;
+import android.view.WindowManager;
+import android.widget.FrameLayout;
+import android.util.DisplayMetrics;
class StatusBarIcon {
// TODO: get this from a resource
@@ -44,8 +49,13 @@ class StatusBarIcon {
private TextView mTextView;
private AnimatedImageView mImageView;
private TextView mNumberView;
+ private int clockColor = 0xff000000;
+ private int batteryPercentColor = 0xffffffff;
+ private int notifCountColor = 0xffffffff;
+ private Context mContext;
public StatusBarIcon(Context context, IconData data, ViewGroup parent) {
+ mContext = context;
mData = data.clone();
switch (data.type) {
@@ -55,15 +65,25 @@ class StatusBarIcon {
mTextView = t;
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
- LinearLayout.LayoutParams.MATCH_PARENT);
+ LinearLayout.LayoutParams.FILL_PARENT);
t.setTextSize(16);
- t.setTextColor(0xff000000);
t.setTypeface(Typeface.DEFAULT_BOLD);
t.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
t.setPadding(6, 0, 0, 0);
t.setLayoutParams(layoutParams);
t.setText(data.text);
this.view = t;
+
+ data.textColor = Settings.System.getInt(mContext.getContentResolver(), data.colorSetting, data.textColor);
+ t.setTextColor(data.textColor);
+
+ if (getBoolean(context, data.visibleSetting, data.defVisibility)) {
+ t.setVisibility(View.VISIBLE);
+ }
+ else {
+ t.setVisibility(View.GONE);
+ }
+
break;
}
@@ -85,12 +105,71 @@ class StatusBarIcon {
mNumberView = nv;
if (data.number > 0) {
nv.setText("" + data.number);
+ data.textColor = Settings.System.getInt(mContext.getContentResolver(),
+ data.colorSetting, data.textColor);
+ nv.setTextColor(data.textColor);
nv.setVisibility(View.VISIBLE);
} else {
nv.setVisibility(View.GONE);
}
break;
}
+ case IconData.ICON_NUMBER: {
+ // container
+ LayoutInflater inflater = (LayoutInflater)context.getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ View v = inflater.inflate(com.android.internal.R.layout.status_bar_icon, parent, false);
+ this.view = v;
+
+ // icon
+ AnimatedImageView im = (AnimatedImageView)v.findViewById(com.android.internal.R.id.image);
+ im.setImageDrawable(getIcon(context, data));
+ im.setImageLevel(data.iconLevel);
+ mImageView = im;
+
+ // number
+ TextView nv = (TextView)v.findViewById(com.android.internal.R.id.number);
+ mNumberView = nv;
+
+ //remove background, center, and change gravity of text
+ // attempt to correct position on both hdpi and mdpi
+ DisplayMetrics dm = new DisplayMetrics();
+ ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(dm);
+
+ if (DisplayMetrics.DENSITY_HIGH == dm.densityDpi) {
+ mNumberView.setLayoutParams(
+ new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.WRAP_CONTENT,
+ FrameLayout.LayoutParams.WRAP_CONTENT,
+ Gravity.RIGHT | Gravity.CENTER_VERTICAL));
+
+ mNumberView.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
+ }
+ else {
+ mNumberView.setLayoutParams(
+ new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.WRAP_CONTENT,
+ FrameLayout.LayoutParams.WRAP_CONTENT,
+ Gravity.CENTER | Gravity.CENTER_VERTICAL));
+
+ mNumberView.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL);
+ }
+
+ mNumberView.setBackgroundDrawable(null);
+ data.textColor = Settings.System.getInt(context.getContentResolver(),
+ data.colorSetting, data.textColor);
+ mNumberView.setTextColor(data.textColor);
+ mNumberView.setTextSize(12);
+
+ if (data.number == 100) {
+ nv.setText("" + 99);
+ } else if ((data.number > 0)&&(data.number < 100)) {
+ nv.setText("" + data.number);
+ } else {
+ nv.setText("");
+ }
+ break;
+ }
}
}
@@ -100,12 +179,16 @@ class StatusBarIcon {
}
switch (data.type) {
case IconData.TEXT:
+ data.textColor = Settings.System.getInt(mContext.getContentResolver(),
+ data.colorSetting, data.textColor);
+ mTextView.setTextColor(data.textColor);
if (!TextUtils.equals(mData.text, data.text)) {
TextView tv = mTextView;
tv.setText(data.text);
}
break;
case IconData.ICON:
+ case IconData.ICON_NUMBER:
if (((mData.iconPackage != null && data.iconPackage != null)
&& !mData.iconPackage.equals(data.iconPackage))
|| mData.iconId != data.iconId
@@ -114,6 +197,9 @@ class StatusBarIcon {
im.setImageDrawable(getIcon(context, data));
im.setImageLevel(data.iconLevel);
}
+ data.textColor = Settings.System.getInt(mContext.getContentResolver(),
+ data.colorSetting, data.textColor);
+ mNumberView.setTextColor(data.textColor);
if (mData.number != data.number) {
TextView nv = mNumberView;
if (data.number > 0) {
@@ -182,5 +268,8 @@ class StatusBarIcon {
int getNumber() {
return mData.number;
}
+ private boolean getBoolean(Context context, String systemSettingKey, boolean defaultValue) {
+ return 1 == android.provider.Settings.System.getInt(context.getContentResolver(), systemSettingKey, defaultValue ? 1 : 0);
+ }
}
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index 94d1cb4..1fd72e6 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -20,6 +20,7 @@ import android.app.AlertDialog;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothHid;
import android.bluetooth.BluetoothPbap;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
@@ -121,6 +122,9 @@ public class StatusBarPolicy {
//***** Signal strength icons
private IconData mPhoneData;
+ private IBinder mPhoneDbmIcon;
+ private IconData mPhoneDbmData;
+
//GSM/UMTS
private static final int[] sSignalImages = new int[] {
com.android.internal.R.drawable.stat_sys_signal_0,
@@ -299,6 +303,7 @@ public class StatusBarPolicy {
private IconData mBluetoothData;
private int mBluetoothHeadsetState;
private boolean mBluetoothA2dpConnected;
+ private int mBluetoothHidState;
private int mBluetoothPbapState;
private boolean mBluetoothEnabled;
@@ -381,6 +386,7 @@ public class StatusBarPolicy {
}
else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED) ||
action.equals(BluetoothHeadset.ACTION_STATE_CHANGED) ||
+ action.equals(BluetoothHid.HID_DEVICE_STATE_CHANGED_ACTION) ||
action.equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED) ||
action.equals(BluetoothPbap.PBAP_STATE_CHANGED_ACTION)) {
updateBluetooth(intent);
@@ -415,7 +421,7 @@ public class StatusBarPolicy {
// clock
mCalendar = Calendar.getInstance(TimeZone.getDefault());
- mClockData = IconData.makeText("clock", "");
+ mClockData = IconData.makeText("clock", "", Settings.System.CLOCK_COLOR, Settings.System.SHOW_STATUS_CLOCK, true);
mClockIcon = service.addIcon(mClockData, null);
updateClock();
@@ -425,8 +431,9 @@ public class StatusBarPolicy {
new com.android.server.status.StorageNotification(context));
// battery
- mBatteryData = IconData.makeIcon("battery",
- null, com.android.internal.R.drawable.stat_sys_battery_unknown, 0, 0);
+ mBatteryData = IconData.makeIconNumber("battery",
+ null, com.android.internal.R.drawable.stat_sys_battery_unknown, 0, 0,
+ Settings.System.BATTERY_PERCENTAGE_STATUS_COLOR);
mBatteryIcon = service.addIcon(mBatteryData, null);
// phone_signal
@@ -435,6 +442,10 @@ public class StatusBarPolicy {
null, com.android.internal.R.drawable.stat_sys_signal_null, 0, 0);
mPhoneIcon = service.addIcon(mPhoneData, null);
+ // dbm signal level
+ mPhoneDbmData = IconData.makeText("phone_dbm_signal", "", Settings.System.DBM_COLOR, Settings.System.SHOW_STATUS_DBM, false);
+ mPhoneDbmIcon = service.addIcon(mPhoneDbmData, null);
+
// register for phone state notifications.
((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE))
.listen(mPhoneStateListener,
@@ -488,8 +499,14 @@ public class StatusBarPolicy {
null, com.android.internal.R.drawable.stat_sys_gps_acquiring_anim, 0, 0);
mGpsFixIconData = IconData.makeIcon("gps",
null, com.android.internal.R.drawable.stat_sys_gps_on, 0, 0);
- mGpsIcon = service.addIcon(mGpsEnabledIconData, null);
- service.setIconVisibility(mGpsIcon, false);
+ ContentResolver resolver = mContext.getContentResolver();
+ String allowedProviders = Settings.Secure.getString(resolver,
+ Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
+ if((allowedProviders.equalsIgnoreCase("gps")) || (allowedProviders.equalsIgnoreCase("network")))
+ {
+ mGpsIcon = service.addIcon(mGpsEnabledIconData, null);
+ service.setIconVisibility(mGpsIcon, false);
+ }
// Alarm clock
mAlarmClockIconData = IconData.makeIcon(
@@ -530,6 +547,7 @@ public class StatusBarPolicy {
filter.addAction(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
filter.addAction(BluetoothHeadset.ACTION_STATE_CHANGED);
+ filter.addAction(BluetoothHid.HID_DEVICE_STATE_CHANGED_ACTION);
filter.addAction(BluetoothA2dp.ACTION_SINK_STATE_CHANGED);
filter.addAction(BluetoothPbap.PBAP_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
@@ -562,7 +580,12 @@ public class StatusBarPolicy {
if (b24) {
res = R.string.twenty_four_hour_time_format;
} else {
- res = R.string.twelve_hour_time_format;
+ if (Settings.System.getInt(mContext.getContentResolver(), Settings.System.SHOW_TWELVE_HOUR_CLOCK_PERIOD, 1) == 1) {
+ res = R.string.twelve_hour_time_format;
+ }
+ else {
+ res = R.string.twelve_hour_time_format_no_period;
+ }
}
final char MAGIC1 = '\uEF00';
@@ -648,10 +671,21 @@ public class StatusBarPolicy {
private final void updateBattery(Intent intent) {
mBatteryData.iconId = intent.getIntExtra("icon-small", 0);
mBatteryData.iconLevel = intent.getIntExtra("level", 0);
- mService.updateIcon(mBatteryIcon, mBatteryData, null);
boolean plugged = intent.getIntExtra("plugged", 0) != 0;
int level = intent.getIntExtra("level", -1);
+
+ //show battery percentage if not plugged in and status is enabled
+ if (plugged || level >= 100 ||
+ Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.BATTERY_PERCENTAGE_STATUS_ICON, 0) == 0) {
+ mBatteryData.number = -1;
+ } else {
+ mBatteryData.number = level;
+ }
+
+ mService.updateIcon(mBatteryIcon, mBatteryData, null);
+
if (false) {
Slog.d(TAG, "updateBattery level=" + level
+ " plugged=" + plugged
@@ -973,6 +1007,7 @@ public class StatusBarPolicy {
private final void updateSignalStrength() {
int iconLevel = -1;
+ int dBm = 0;
int[] iconList;
// Display signal strength while in "emergency calls only" mode
@@ -985,6 +1020,7 @@ public class StatusBarPolicy {
mPhoneData.iconId = com.android.internal.R.drawable.stat_sys_signal_null;
}
mService.updateIcon(mPhoneIcon, mPhoneData, null);
+ mService.updateIcon(mPhoneDbmIcon, mPhoneDbmData, null);
return;
}
@@ -1001,6 +1037,10 @@ public class StatusBarPolicy {
else if (asu >= 5) iconLevel = 2;
else iconLevel = 1;
+ if (asu != 99) {
+ dBm = asu * 2 - 113;
+ }
+
// Though mPhone is a Manager, this call is not an IPC
if (mPhone.isNetworkRoaming()) {
iconList = sSignalImages_r;
@@ -1015,15 +1055,19 @@ public class StatusBarPolicy {
// If a voice call is made then RSSI should switch to 1x.
if ((mPhoneState == TelephonyManager.CALL_STATE_IDLE) && isEvdo()){
iconLevel = getEvdoLevel();
+ dBm = mSignalStrength.getEvdoDbm();
if (false) {
Slog.d(TAG, "use Evdo level=" + iconLevel + " to replace Cdma Level=" + getCdmaLevel());
}
} else {
iconLevel = getCdmaLevel();
+ dBm = mSignalStrength.getCdmaDbm();
}
}
mPhoneData.iconId = iconList[iconLevel];
mService.updateIcon(mPhoneIcon, mPhoneData, null);
+ mPhoneDbmData.text = Integer.toString(dBm);
+ mService.updateIcon(mPhoneDbmIcon, mPhoneDbmData, null);
}
private int getCdmaLevel() {
@@ -1212,11 +1256,15 @@ public class StatusBarPolicy {
} else if (action.equals(BluetoothPbap.PBAP_STATE_CHANGED_ACTION)) {
mBluetoothPbapState = intent.getIntExtra(BluetoothPbap.PBAP_STATE,
BluetoothPbap.STATE_DISCONNECTED);
+ } else if (action.equals(BluetoothHid.HID_DEVICE_STATE_CHANGED_ACTION)) {
+ mBluetoothHidState = intent.getIntExtra(BluetoothHid.HID_DEVICE_STATE,
+ BluetoothHid.STATE_DISCONNECTED);
} else {
return;
}
if (mBluetoothHeadsetState == BluetoothHeadset.STATE_CONNECTED || mBluetoothA2dpConnected ||
+ mBluetoothHidState == BluetoothHid.STATE_CONNECTED ||
mBluetoothPbapState == BluetoothPbap.STATE_CONNECTED) {
iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth_connected;
}
diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java
index 93c8d34..df7c689 100644
--- a/services/java/com/android/server/status/StatusBarService.java
+++ b/services/java/com/android/server/status/StatusBarService.java
@@ -41,6 +41,7 @@ import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.provider.Telephony;
+import android.util.Log;
import android.util.Slog;
import android.view.Display;
import android.view.Gravity;
@@ -55,6 +56,7 @@ import android.view.WindowManager;
import android.view.WindowManagerImpl;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
+import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RemoteViews;
import android.widget.ScrollView;
@@ -67,6 +69,12 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
+import android.provider.Settings;
+import java.lang.reflect.Field;
+
+import android.graphics.PorterDuff.Mode;
+import android.graphics.drawable.StateListDrawable;
+
/**
* The public (ok, semi-public) service for the status bar.
@@ -88,6 +96,9 @@ public class StatusBarService extends IStatusBar.Stub
static final String TAG = "StatusBar";
static final boolean SPEW = false;
+ private boolean mShowPlmnSb;
+ private boolean mShowSpnSb;
+
static final int EXPANDED_LEAVE_ALONE = -10000;
static final int EXPANDED_FULL_OPEN = -10001;
@@ -101,6 +112,7 @@ public class StatusBarService extends IStatusBar.Stub
private static final int OP_EXPAND = 5;
private static final int OP_TOGGLE = 6;
private static final int OP_DISABLE = 7;
+
private class PendingOp {
IBinder key;
int code;
@@ -206,6 +218,7 @@ public class StatusBarService extends IStatusBar.Stub
private Ticker mTicker;
private View mTickerView;
private boolean mTicking;
+ private TickerView tickerView;
// Tracking finger for opening/closing.
int mEdgeBorder; // corresponds to R.dimen.status_bar_edge_ignore
@@ -224,6 +237,22 @@ public class StatusBarService extends IStatusBar.Stub
boolean mAnimatingReveal = false;
int mViewDelta;
int[] mAbsPos = new int[2];
+ private int blackColor = 0xff000000;
+ private int whiteColor = 0xffffffff;
+ private int notificationTitleColor = blackColor;
+ private int notificationTextColor = blackColor;
+ private int notificationTimeColor = blackColor;
+ boolean custNotBar = false;
+ boolean custExpBar = false;
+ int notifBarColorMask;
+ int expBarColorMask;
+ Mode notifPDMode = Mode.SCREEN;
+ Mode expPDMode = Mode.SCREEN;
+ Drawable closerDrawable;
+ Drawable expBarBackDrawable;
+ Drawable expBarHeadDrawable;
+ Drawable expBarNotifTitleDrawable;
+
// for disabling the status bar
ArrayList<DisableRecord> mDisableRecords = new ArrayList<DisableRecord>();
@@ -234,9 +263,13 @@ public class StatusBarService extends IStatusBar.Stub
*/
public StatusBarService(Context context) {
mContext = context;
+ notificationTitleColor = Settings.System.getInt(mContext.getContentResolver(), Settings.System.NOTIF_ITEM_TITLE_COLOR, blackColor);
+ notificationTextColor = Settings.System.getInt(mContext.getContentResolver(), Settings.System.NOTIF_ITEM_TEXT_COLOR, blackColor);
+ notificationTimeColor = Settings.System.getInt(mContext.getContentResolver(), Settings.System.NOTIF_ITEM_TIME_COLOR, blackColor);
mDisplay = ((WindowManager)context.getSystemService(
Context.WINDOW_SERVICE)).getDefaultDisplay();
makeStatusBarView(context);
+ updateColors();
mUninstallReceiver = new UninstallReceiver();
}
@@ -251,7 +284,7 @@ public class StatusBarService extends IStatusBar.Stub
Resources res = context.getResources();
mRightIconSlots = res.getStringArray(com.android.internal.R.array.status_bar_icon_order);
mRightIcons = new StatusBarIcon[mRightIconSlots.length];
-
+ getNotBarConfig();
ExpandedView expanded = (ExpandedView)View.inflate(context,
com.android.internal.R.layout.status_bar_expanded, null);
expanded.mService = this;
@@ -265,14 +298,23 @@ public class StatusBarService extends IStatusBar.Stub
if (bg != null) {
mPixelFormat = bg.getOpacity();
}
-
mStatusBarView = sb;
+ mDateView = (DateView)sb.findViewById(R.id.date);
+
+ if (custNotBar) {
+ mStatusBarView.setBackgroundDrawable(res.getDrawable(com.android.internal.R.drawable.statusbar_background_sq,
+ notifBarColorMask, notifPDMode));
+ mDateView.setBackgroundDrawable(res.getDrawable(com.android.internal.R.drawable.statusbar_background_sq,
+ notifBarColorMask, notifPDMode));
+ mDateView.setPadding(6, 0, 6, 0);
+ }
+
mStatusIcons = (LinearLayout)sb.findViewById(R.id.statusIcons);
mNotificationIcons = (IconMerger)sb.findViewById(R.id.notificationIcons);
mNotificationIcons.service = this;
mIcons = (LinearLayout)sb.findViewById(R.id.icons);
mTickerView = sb.findViewById(R.id.ticker);
- mDateView = (DateView)sb.findViewById(R.id.date);
+
mExpandedDialog = new ExpandedDialog(context);
mExpandedView = expanded;
@@ -288,21 +330,33 @@ public class StatusBarService extends IStatusBar.Stub
mPlmnLabel = (TextView)expanded.findViewById(R.id.plmnLabel);
mScrollView = (ScrollView)expanded.findViewById(R.id.scroll);
mNotificationLinearLayout = expanded.findViewById(R.id.notificationLinearLayout);
-
+ if (custExpBar) {
+ mExpandedView.findViewById(R.id.exp_view_lin_layout).
+ setBackgroundDrawable(expBarHeadDrawable);
+ mNoNotificationsTitle.setBackgroundDrawable(expBarNotifTitleDrawable);
+ mOngoingTitle.setBackgroundDrawable(expBarNotifTitleDrawable);
+ mLatestTitle.setBackgroundDrawable(expBarNotifTitleDrawable);
+ }
mOngoingTitle.setVisibility(View.GONE);
mLatestTitle.setVisibility(View.GONE);
mTicker = new MyTicker(context, sb);
- TickerView tickerView = (TickerView)sb.findViewById(R.id.tickerText);
+ tickerView = (TickerView)sb.findViewById(R.id.tickerText);
tickerView.mTicker = mTicker;
mTrackingView = (TrackingView)View.inflate(context,
com.android.internal.R.layout.status_bar_tracking, null);
mTrackingView.mService = this;
mCloseView = (CloseDragHandle)mTrackingView.findViewById(R.id.close);
+ if (custExpBar) {
+ ImageView iv = (ImageView)mTrackingView.findViewById(R.id.close_image);
+ mCloseView.removeAllViews();
+ iv.setImageDrawable(closerDrawable);
+ iv.setColorFilter(expBarColorMask, expPDMode);
+ mCloseView.addView(iv);
+ }
mCloseView.mService = this;
-
mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
// add the more icon for the notifications
@@ -828,7 +882,8 @@ public class StatusBarService extends IStatusBar.Stub
};
View makeNotificationView(StatusBarNotification notification, ViewGroup parent) {
- NotificationData n = notification.data;
+ Resources res = mContext.getResources();
+ NotificationData n = notification.data;
RemoteViews remoteViews = n.contentView;
if (remoteViews == null) {
return null;
@@ -838,9 +893,22 @@ public class StatusBarService extends IStatusBar.Stub
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(com.android.internal.R.layout.status_bar_latest_event, parent, false);
-
- // bind the click event to the content area
ViewGroup content = (ViewGroup)row.findViewById(com.android.internal.R.id.content);
+ if (custExpBar) {
+ StateListDrawable sld = new StateListDrawable();
+ int stateFocused = android.R.attr.state_focused;
+ int statePressed = android.R.attr.state_pressed;
+ Drawable colornormal = res.getDrawable(com.android.internal.R.drawable.status_bar_item_background_normal_cust);
+ Drawable colorfocused = res.getDrawable(com.android.internal.R.drawable.status_bar_item_background_focus_cust);
+ Drawable colorpressed = res.getDrawable(com.android.internal.R.drawable.status_bar_item_background_pressed_cust);
+ sld.addState(new int[] {stateFocused}, colorfocused);
+ sld.addState(new int[] {statePressed}, colorpressed);
+ sld.addState(new int[] {}, colornormal);
+ sld.mutate();
+ sld.setColorFilter(expBarColorMask, expPDMode);
+ content.setBackgroundDrawable(sld);
+
+ }
content.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
content.setOnFocusChangeListener(mFocusChangeListener);
PendingIntent contentIntent = n.contentIntent;
@@ -860,7 +928,12 @@ public class StatusBarService extends IStatusBar.Stub
Slog.e(TAG, "couldn't inflate view for package " + n.pkg, exception);
return null;
}
- content.addView(child);
+
+ // This will try to handle text color for all notifications from apps, applying the appropriate
+ // color if ID is possible, otherwise setting it to notification text color
+ startRecurse(child);
+
+ content.addView(child);
row.setDrawingCacheEnabled(true);
@@ -870,6 +943,43 @@ public class StatusBarService extends IStatusBar.Stub
return row;
}
+ void startRecurse(View v) {
+ ViewGroup vg = (ViewGroup) v;
+ int childcount = vg.getChildCount();
+ if (childcount > 0) {
+ int i;
+ for (i = 0; i < childcount; i++) {
+ try {
+ setViewColors((TextView) vg.getChildAt(i));
+ } catch (Exception e) { }
+ try {
+ startRecurse((View) vg.getChildAt(i));
+ } catch (Exception e) { }
+ }
+ }
+ }
+
+ void setViewColors(TextView tv) {
+ int tvID = 0;
+ try {
+ tvID = tv.getId();
+ switch (tvID) {
+ case com.android.internal.R.id.title:
+ tv.setTextColor(notificationTitleColor);
+ break;
+ case com.android.internal.R.id.text:
+ tv.setTextColor(notificationTextColor);
+ break;
+ case com.android.internal.R.id.time:
+ tv.setTextColor(notificationTimeColor);
+ break;
+ default:
+ tv.setTextColor(notificationTextColor);
+ }
+ } catch (Exception e) { }
+ }
+
+
void addNotificationView(StatusBarNotification notification) {
if (notification.view != null) {
throw new RuntimeException("Assertion failed: notification.view="
@@ -1510,7 +1620,7 @@ public class StatusBarService extends IStatusBar.Stub
Drawable bg;
/// ---------- Tracking View --------------
- pixelFormat = PixelFormat.RGBX_8888;
+ pixelFormat = PixelFormat.TRANSLUCENT;
bg = mTrackingView.getBackground();
if (bg != null) {
pixelFormat = bg.getOpacity();
@@ -1730,6 +1840,17 @@ public class StatusBarService extends IStatusBar.Stub
}
}
}
+
+ private void updateColors() {
+ mDateView.setTextColor(Settings.System.getInt(mContext.getContentResolver(), Settings.System.DATE_COLOR, blackColor));
+ mNoNotificationsTitle.setTextColor(Settings.System.getInt(mContext.getContentResolver(), Settings.System.NO_NOTIF_COLOR, whiteColor));
+ mLatestTitle.setTextColor(Settings.System.getInt(mContext.getContentResolver(), Settings.System.LATEST_NOTIF_COLOR, whiteColor));
+ mOngoingTitle.setTextColor(Settings.System.getInt(mContext.getContentResolver(), Settings.System.ONGOING_NOTIF_COLOR, whiteColor));
+ mSpnLabel.setTextColor(Settings.System.getInt(mContext.getContentResolver(), Settings.System.SPN_LABEL_COLOR, blackColor));
+ mPlmnLabel.setTextColor(Settings.System.getInt(mContext.getContentResolver(), Settings.System.PLMN_LABEL_COLOR, blackColor));
+ mClearButton.setTextColor(Settings.System.getInt(mContext.getContentResolver(), Settings.System.CLEAR_BUTTON_LABEL_COLOR, blackColor));
+ tickerView.updateColors(Settings.System.getInt(mContext.getContentResolver(), Settings.System.NEW_NOTIF_TICKER_COLOR, blackColor));
+ }
private View.OnClickListener mClearButtonListener = new View.OnClickListener() {
public void onClick(View v) {
@@ -1737,7 +1858,7 @@ public class StatusBarService extends IStatusBar.Stub
addPendingOp(OP_EXPAND, null, false);
}
};
-
+
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
@@ -1758,12 +1879,16 @@ public class StatusBarService extends IStatusBar.Stub
};
void updateNetworkName(boolean showSpn, String spn, boolean showPlmn, String plmn) {
+ // Double carrier
+ mShowPlmnSb = (Settings.System.getInt(mContext.getContentResolver(), Settings.System.SHOW_PLMN_SB, 1) == 1);
+ mShowSpnSb = (Settings.System.getInt(mContext.getContentResolver(), Settings.System.SHOW_SPN_SB, 1) == 1);
if (false) {
Slog.d(TAG, "updateNetworkName showSpn=" + showSpn + " spn=" + spn
+ " showPlmn=" + showPlmn + " plmn=" + plmn);
}
boolean something = false;
- if (showPlmn) {
+ // Double carrier - bcrook
+ if (showPlmn && mShowPlmnSb) {
mPlmnLabel.setVisibility(View.VISIBLE);
if (plmn != null) {
mPlmnLabel.setText(plmn);
@@ -1774,7 +1899,8 @@ public class StatusBarService extends IStatusBar.Stub
mPlmnLabel.setText("");
mPlmnLabel.setVisibility(View.GONE);
}
- if (showSpn && spn != null) {
+ // Double carrier - bcrook, refinements from Wysie
+ if (showSpn && spn != null && mShowSpnSb) {
mSpnLabel.setText(spn);
mSpnLabel.setVisibility(View.VISIBLE);
something = true;
@@ -1878,4 +2004,38 @@ public class StatusBarService extends IStatusBar.Stub
}
}
}
+
+ private void getNotBarConfig() {
+ Resources res = mContext.getResources();
+ /*
+ * Setup color and bar type for notification strip
+ */
+ boolean useCustom = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.NOTIF_BAR_CUSTOM, 0) == 1;
+ notifBarColorMask = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.NOTIF_BAR_COLOR, whiteColor);
+ if (useCustom) {
+ custNotBar = true;
+ } else {
+ custNotBar = false;
+ }
+ /*
+ * Setup colors for expanded notification drawables
+ */
+ boolean useCustomExp = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.NOTIF_EXPANDED_BAR_CUSTOM, 0) == 1;
+ expBarColorMask = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.NOTIF_EXPANDED_BAR_COLOR, whiteColor);
+ int noalpha = expBarColorMask | 0xFF000000;
+ if (useCustomExp) {
+ closerDrawable = res.getDrawable(com.android.internal.R.drawable.status_bar_close_on_cust);
+ expBarHeadDrawable = res.getDrawable(com.android.internal.R.drawable.status_bar_header_background_cust,
+ expBarColorMask, expPDMode);
+ expBarNotifTitleDrawable = res.getDrawable(com.android.internal.R.drawable.title_bar_portrait_cust,
+ noalpha, expPDMode); // always solid
+ custExpBar = true;
+ } else {
+ custExpBar = false;
+ }
+ }
}
diff --git a/services/java/com/android/server/status/TickerView.java b/services/java/com/android/server/status/TickerView.java
index 099dffb..40e1462 100644
--- a/services/java/com/android/server/status/TickerView.java
+++ b/services/java/com/android/server/status/TickerView.java
@@ -19,11 +19,13 @@ package com.android.server.status;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextSwitcher;
+import android.widget.TextView;
public class TickerView extends TextSwitcher
{
Ticker mTicker;
+ private int textColor = 0xFF000000;
public TickerView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -34,5 +36,24 @@ public class TickerView extends TextSwitcher
super.onSizeChanged(w, h, oldw, oldh);
mTicker.reflowText();
}
+
+ @Override
+ public void setText(CharSequence text) {
+ final TextView t = (TextView) getNextView();
+ t.setTextColor(textColor);
+ t.setText(text);
+ showNext();
+ }
+
+ @Override
+ public void setCurrentText(CharSequence text) {
+ final TextView t = (TextView) getCurrentView();
+ t.setTextColor(textColor);
+ t.setText(text);
+ }
+
+ public void updateColors(int color) {
+ textColor = color;
+ }
}
diff --git a/services/java/com/android/server/status/TrackingPatternView.java b/services/java/com/android/server/status/TrackingPatternView.java
index 2c91aa4..46648af 100644
--- a/services/java/com/android/server/status/TrackingPatternView.java
+++ b/services/java/com/android/server/status/TrackingPatternView.java
@@ -17,7 +17,9 @@
package com.android.server.status;
import android.content.Context;
+import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.provider.Settings;
import android.util.AttributeSet;
import android.util.Slog;
import android.view.View;
@@ -25,6 +27,10 @@ import android.graphics.BitmapFactory;
import android.graphics.Bitmap;
import android.graphics.Paint;
import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.drawable.BitmapDrawable;
+
public class TrackingPatternView extends View {
private Bitmap mTexture;
@@ -34,9 +40,7 @@ public class TrackingPatternView extends View {
public TrackingPatternView(Context context, AttributeSet attrs) {
super(context, attrs);
-
- mTexture = BitmapFactory.decodeResource(getResources(),
- com.android.internal.R.drawable.status_bar_background);
+ setTexture();
mTextureWidth = mTexture.getWidth();
mTextureHeight = mTexture.getHeight();
@@ -67,4 +71,21 @@ public class TrackingPatternView extends View {
x += textureWidth;
}
}
+
+ private void setTexture() {
+ boolean useCustomExp = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.NOTIF_EXPANDED_BAR_CUSTOM, 0) == 1;
+ int expBarColorMask = Settings.System.getInt(mContext.getContentResolver(),
+ Settings.System.NOTIF_EXPANDED_BAR_COLOR, 0xFF000000);
+ if (useCustomExp) {
+ Bitmap tempbm = BitmapFactory.decodeResource(getResources(),
+ com.android.internal.R.drawable.status_bar_background_cust);
+ Bitmap mutable = Bitmap.createBitmap(tempbm.getWidth(), tempbm.getHeight(), Bitmap.Config.ARGB_8888);
+ mutable.eraseColor(expBarColorMask);
+ mTexture = mutable;
+ } else {
+ mTexture = BitmapFactory.decodeResource(getResources(),
+ com.android.internal.R.drawable.status_bar_background);
+ }
+ }
}
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 32e7176..83c662c 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -55,6 +55,12 @@ public class PhoneNumberUtils
public static final char WILD = 'N';
/*
+ * Calling Line Identification Restriction (CLIR)
+ */
+ private static final String CLIR_ON = "*31#+";
+ private static final String CLIR_OFF = "#31#+";
+
+ /*
* TOA = TON + NPI
* See TS 24.008 section 10.5.4.7 for details.
* These are the only really useful TOA values
@@ -179,8 +185,6 @@ public class PhoneNumberUtils
* Please note that the GSM wild character is allowed in the result.
* This must be resolved before dialing.
*
- * Allows + only in the first position in the result string.
- *
* Returns null if phoneNumber == null
*/
public static String
@@ -203,6 +207,11 @@ public class PhoneNumberUtils
}
}
+ int pos = addPlusChar(phoneNumber);
+ if (pos >= 0 && ret.length() > pos) {
+ ret.insert(pos, '+');
+ }
+
return ret.toString();
}
@@ -304,6 +313,28 @@ public class PhoneNumberUtils
}
}
+ /** GSM codes
+ * Finds if a GSM code includes the international prefix (+).
+ *
+ * @param number the number to dial.
+ *
+ * @return the position where the + char will be inserted, -1 if the GSM code was not found.
+ */
+ private static int
+ addPlusChar(String number) {
+ int pos = -1;
+
+ if (number.startsWith(CLIR_OFF)) {
+ pos = CLIR_OFF.length() - 1;
+ }
+
+ if (number.startsWith(CLIR_ON)) {
+ pos = CLIR_ON.length() - 1;
+ }
+
+ return pos;
+ }
+
/**
* Extracts the post-dial sequence of DTMF control digits, pauses, and
* waits. Strips separators. This string may be empty, but will not be null
diff --git a/telephony/java/com/android/internal/telephony/AdnRecordCache.java b/telephony/java/com/android/internal/telephony/AdnRecordCache.java
index c8c0658..a175d49 100644
--- a/telephony/java/com/android/internal/telephony/AdnRecordCache.java
+++ b/telephony/java/com/android/internal/telephony/AdnRecordCache.java
@@ -186,7 +186,12 @@ public final class AdnRecordCache extends Handler implements IccConstants {
}
ArrayList<AdnRecord> oldAdnList;
- oldAdnList = getRecordsIfLoaded(efid);
+
+ if (efid == EF_PBR) {
+ oldAdnList = mUsimPhoneBookManager.loadEfFilesFromUsim();
+ } else {
+ oldAdnList = getRecordsIfLoaded(efid);
+ }
if (oldAdnList == null) {
sendErrorResponse(response, "Adn list not exist for EF:" + efid);
@@ -208,6 +213,17 @@ public final class AdnRecordCache extends Handler implements IccConstants {
return;
}
+ if (efid == EF_PBR) {
+ AdnRecord foundAdn = oldAdnList.get(index-1);
+ efid = foundAdn.efid;
+ extensionEF = foundAdn.extRecord;
+ index = foundAdn.recordNumber;
+
+ newAdn.efid = efid;
+ newAdn.extRecord = extensionEF;
+ newAdn.recordNumber = index;
+ }
+
Message pendingResponse = userWriteResponse.get(efid);
if (pendingResponse != null) {
@@ -331,6 +347,7 @@ public final class AdnRecordCache extends Handler implements IccConstants {
if (ar.exception == null) {
adnLikeFiles.get(efid).set(index - 1, adn);
+ mUsimPhoneBookManager.invalidateCache();
}
Message response = userWriteResponse.get(efid);
diff --git a/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
index 9f8e57f..176b087 100644
--- a/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
@@ -144,6 +144,9 @@ public abstract class IccPhoneBookInterfaceManager extends IIccPhoneBook.Stub {
if (DBG) logd("updateAdnRecordsInEfBySearch: efid=" + efid +
" ("+ oldTag + "," + oldPhoneNumber + ")"+ "==>" +
" ("+ newTag + "," + newPhoneNumber + ")"+ " pin2=" + pin2);
+
+ efid = updateEfForIccType(efid);
+
synchronized(mLock) {
checkThread();
success = false;
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 627d94d..92a6173 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -443,7 +443,8 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if ((state == State.IDLE || state == State.SCANNING)
&& (gprsState == ServiceState.STATE_IN_SERVICE || noAutoAttach)
&& mGsmPhone.mSIMRecords.getRecordsLoaded()
- && phone.getState() == Phone.State.IDLE
+ && (mGsmPhone.mSST.isConcurrentVoiceAndData() ||
+ phone.getState() == Phone.State.IDLE )
&& isDataAllowed()
&& !mIsPsRestricted
&& desiredPowerState ) {
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
index bcbd127..6a65b87 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmMmiCode.java
@@ -124,8 +124,12 @@ public final class GsmMmiCode extends Handler implements MmiCode {
// See TS 22.030 6.5.2 "Structure of the MMI"
+ // Note that some nonstandard MMI codes seem to end with an asterisk, eg. "#190*1660#*"
+ // (http://code.google.com/p/android/issues/detail?id=2226). Make sure this doesn't get
+ // merged into MATCH_GROUP_DIALING_NUMBER.
+
static Pattern sPatternSuppService = Pattern.compile(
- "((\\*|#|\\*#|\\*\\*|##)(\\d{2,3})(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#)(.*)");
+ "((\\*|#|\\*#|\\*\\*|##)(\\d{2,3})(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*)(\\*([^*#]*))?)?)?)?#\\*?)(.*)");
/* 1 2 3 4 5 6 7 8 9 10 11 12
1 = Full string up to and including #
@@ -134,7 +138,7 @@ public final class GsmMmiCode extends Handler implements MmiCode {
5 = SIA
7 = SIB
9 = SIC
- 10 = dialing number
+ 12 = dialing number
*/
static final int MATCH_GROUP_POUND_STRING = 1;
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
index d711a80..b4e7b63 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
@@ -559,6 +559,13 @@ public final class SIMRecords extends IccRecords {
break;
case EVENT_GET_CPHS_MAILBOX_DONE:
case EVENT_GET_MBDN_DONE:
+ //Resetting the voice mail number and voice mail tag to null
+ //as these should be updated from the data read from EF_MBDN.
+ //If they are not reset, incase of invalid data/exception these
+ //variables are retaining their previous values and are
+ //causing invalid voice mailbox info display to user.
+ voiceMailNum = null;
+ voiceMailTag = null;
isRecordLoadResponse = true;
ar = (AsyncResult)msg.obj;
diff --git a/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java b/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
index 41e527c..b642541 100644..100755
--- a/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
+++ b/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
@@ -53,6 +53,7 @@ public class UsimPhoneBookManager extends Handler implements IccConstants {
private ArrayList<byte[]> mIapFileRecord;
private ArrayList<byte[]> mEmailFileRecord;
private Map<Integer, ArrayList<String>> mEmailsForAdnRec;
+ private boolean mRefreshCache = false;
private static final int EVENT_PBR_LOAD_DONE = 1;
private static final int EVENT_USIM_ADN_LOAD_DONE = 2;
@@ -91,11 +92,19 @@ public class UsimPhoneBookManager extends Handler implements IccConstants {
mEmailFileRecord = null;
mPbrFile = null;
mIsPbrPresent = true;
+ mRefreshCache = false;
}
public ArrayList<AdnRecord> loadEfFilesFromUsim() {
synchronized (mLock) {
- if (!mPhoneBookRecords.isEmpty()) return mPhoneBookRecords;
+ if (!mPhoneBookRecords.isEmpty()) {
+ if (mRefreshCache) {
+ mRefreshCache = false;
+ refreshCache();
+ }
+ return mPhoneBookRecords;
+ }
+
if (!mIsPbrPresent) return null;
// Check if the PBR file is present in the cache, if not read it
@@ -116,6 +125,20 @@ public class UsimPhoneBookManager extends Handler implements IccConstants {
return mPhoneBookRecords;
}
+ private void refreshCache() {
+ if (mPbrFile == null) return;
+ mPhoneBookRecords.clear();
+
+ int numRecs = mPbrFile.mFileIds.size();
+ for (int i = 0; i < numRecs; i++) {
+ readAdnFileAndWait(i);
+ }
+ }
+
+ public void invalidateCache() {
+ mRefreshCache = true;
+ }
+
private void readPbrFileAndWait() {
mPhone.getIccFileHandler().loadEFLinearFixedAll(EF_PBR, obtainMessage(EVENT_PBR_LOAD_DONE));
try {
diff --git a/tests/CoreTests/android/AndroidManifest.xml b/tests/CoreTests/android/AndroidManifest.xml
index f02673c..8331f0c 100644
--- a/tests/CoreTests/android/AndroidManifest.xml
+++ b/tests/CoreTests/android/AndroidManifest.xml
@@ -24,6 +24,7 @@
<uses-permission android:name="android.permission.CHANGE_CONFIGURATION" />
<uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- location test permissions -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
diff --git a/tests/CoreTests/android/core/HttpHeaderTest.java b/tests/CoreTests/android/core/HttpHeaderTest.java
new file mode 100644
index 0000000..a5d4857
--- /dev/null
+++ b/tests/CoreTests/android/core/HttpHeaderTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+package android.core;
+
+import android.test.AndroidTestCase;
+import org.apache.http.util.CharArrayBuffer;
+
+import android.net.http.Headers;
+
+public class HttpHeaderTest extends AndroidTestCase {
+
+ static final String LAST_MODIFIED = "Last-Modified: Fri, 18 Jun 2010 09:56:47 GMT";
+ static final String CACHE_CONTROL_MAX_AGE = "Cache-Control:max-age=15";
+ static final String CACHE_CONTROL_PRIVATE = "Cache-Control: private";
+
+ /**
+ * Tests that cache control header supports multiple instances of the header,
+ * according to HTTP specification.
+ *
+ * The HTTP specification states the following about the fields:
+ * Multiple message-header fields with the same field-name MAY be present
+ * in a message if and only if the entire field-value for that header field
+ * is defined as a comma-separated list [i.e., #(values)]. It MUST be
+ * possible to combine the multiple header fields into one "field-name:
+ * field-value" pair, without changing the semantics of the message, by
+ * appending each subsequent field-value to the first, each separated by a
+ * comma. The order in which header fields with the same field-name are
+ * received is therefore significant to the interpretation of the combined
+ * field value, and thus a proxy MUST NOT change the order of these field
+ * values when a message is forwarded.
+ */
+ public void testCacheControl() throws Exception {
+ Headers h = new Headers();
+ CharArrayBuffer buffer = new CharArrayBuffer(64);
+
+ buffer.append(CACHE_CONTROL_MAX_AGE);
+ h.parseHeader(buffer);
+
+ buffer.clear();
+ buffer.append(LAST_MODIFIED);
+ h.parseHeader(buffer);
+ assertEquals("max-age=15", h.getCacheControl());
+
+ buffer.clear();
+ buffer.append(CACHE_CONTROL_PRIVATE);
+ h.parseHeader(buffer);
+ assertEquals("max-age=15,private", h.getCacheControl());
+ }
+}
diff --git a/tests/CoreTests/android/core/ProxyTest.java b/tests/CoreTests/android/core/ProxyTest.java
new file mode 100644
index 0000000..12acfe8
--- /dev/null
+++ b/tests/CoreTests/android/core/ProxyTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+package android.core;
+
+import org.apache.http.HttpHost;
+
+import android.content.Context;
+import android.net.Proxy;
+import android.test.AndroidTestCase;
+
+/**
+ * Proxy tests
+ */
+public class ProxyTest extends AndroidTestCase {
+ private Context mContext;
+ private HttpHost mHttpHost;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mContext = getContext();
+ mHttpHost = null;
+ String proxyHost = Proxy.getHost(mContext);
+ int proxyPort = Proxy.getPort(mContext);
+ if (proxyHost != null) {
+ mHttpHost = new HttpHost(proxyHost, proxyPort, "http");
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Bad url parameter should not cause any exception.
+ */
+ public void testProxyGetPreferredHttpHost_UrlBad() throws Exception {
+ assertEquals(mHttpHost, Proxy.getPreferredHttpHost(mContext, null));
+ assertEquals(mHttpHost, Proxy.getPreferredHttpHost(mContext, ""));
+ assertEquals(mHttpHost, Proxy.getPreferredHttpHost(mContext, "bad:"));
+ assertEquals(mHttpHost, Proxy.getPreferredHttpHost(mContext, "bad"));
+ assertEquals(mHttpHost, Proxy.getPreferredHttpHost(mContext, "bad:\\"));
+ assertEquals(mHttpHost, Proxy.getPreferredHttpHost(mContext, "bad://#"));
+ assertEquals(mHttpHost, Proxy.getPreferredHttpHost(mContext, "://#"));
+ }
+
+ /**
+ * Proxy (if available) should be returned when url parameter is not localhost.
+ */
+ public void testProxyGetPreferredHttpHost_UrlNotlLocalhost() throws Exception {
+ assertEquals(mHttpHost, Proxy.getPreferredHttpHost(mContext, "http://"));
+ assertEquals(mHttpHost, Proxy.getPreferredHttpHost(mContext, "http://example.com"));
+ assertEquals(mHttpHost, Proxy.getPreferredHttpHost(mContext, "http://example.com/"));
+ assertEquals(mHttpHost, Proxy.getPreferredHttpHost(mContext, "http://192.168.0.1/"));
+ assertEquals(mHttpHost, Proxy.getPreferredHttpHost(mContext, "file:///foo/bar"));
+ assertEquals(mHttpHost, Proxy.getPreferredHttpHost(mContext, "rtsp://example.com"));
+ assertEquals(mHttpHost, Proxy.getPreferredHttpHost(mContext, "rtsp://example.com/"));
+ assertEquals(mHttpHost, Proxy.getPreferredHttpHost(mContext, "javascript:alert(1)"));
+ }
+
+ /**
+ * No proxy should be returned when url parameter is localhost.
+ */
+ public void testProxyGetPreferredHttpHost_UrlLocalhost() throws Exception {
+ assertNull(Proxy.getPreferredHttpHost(mContext, "http://localhost"));
+ assertNull(Proxy.getPreferredHttpHost(mContext, "http://localhost/"));
+ assertNull(Proxy.getPreferredHttpHost(mContext, "http://localhost/hej.html"));
+ assertNull(Proxy.getPreferredHttpHost(mContext, "http://127.0.0.1"));
+ assertNull(Proxy.getPreferredHttpHost(mContext, "http://127.0.0.1/"));
+ assertNull(Proxy.getPreferredHttpHost(mContext, "http://127.0.0.1/hej.html"));
+ assertNull(Proxy.getPreferredHttpHost(mContext, "http://127.0.0.1:80/"));
+ assertNull(Proxy.getPreferredHttpHost(mContext, "http://127.0.0.1:8080/"));
+ assertNull(Proxy.getPreferredHttpHost(mContext, "rtsp://127.0.0.1/"));
+ assertNull(Proxy.getPreferredHttpHost(mContext, "rtsp://localhost/"));
+ assertNull(Proxy.getPreferredHttpHost(mContext, "https://localhost/"));
+ }
+}
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index a2f085a..a84492d 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -12,6 +12,8 @@
#include <utils/ResourceTypes.h>
#include <stdarg.h>
+#include <set>
+
#define NOISY(x) //x
status_t compileXmlFile(const sp<AaptAssets>& assets,
@@ -2516,6 +2518,34 @@ ResourceFilter::match(const ResTable_config& config)
return true;
}
+class entry_sort_t {
+public:
+ sp<ResourceTable::Package> p;
+ sp<ResourceTable::Type> t;
+ sp<ResourceTable::ConfigList> c;
+ ResourceTable::ConfigDescription config;
+ sp<ResourceTable::Entry> e;
+
+ entry_sort_t() { }
+ entry_sort_t(
+ sp<ResourceTable::Package> p,
+ sp<ResourceTable::Type> t,
+ sp<ResourceTable::ConfigList> c,
+ const ResourceTable::ConfigDescription &config,
+ sp<ResourceTable::Entry> e)
+ : p(p), t(t), c(c), config(config), e(e) { }
+
+ bool operator < (const entry_sort_t &o) const {
+ int cmp;
+ if ((cmp = compare_type(config, o.config))) return cmp < 0;
+ if ((cmp = compare_type(t, o.t))) return cmp < 0;
+ if ((cmp = compare_type(e, o.e))) return cmp < 0;
+ if ((cmp = compare_type(c, o.c))) return cmp < 0;
+ if ((cmp = compare_type(p, o.p))) return cmp < 0;
+ return false;
+ }
+};
+
status_t ResourceTable::flatten(Bundle* bundle, const sp<AaptFile>& dest)
{
ResourceFilter filter;
@@ -2528,6 +2558,7 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp<AaptFile>& dest)
size_t pi;
bool useUTF8 = !bundle->getWantUTF16() && bundle->isMinSdkAtLeast(SDK_FROYO);
+ std::set< entry_sort_t > sortedEntries;
// Iterate through all data, collecting all values (strings,
// references, etc).
@@ -2568,10 +2599,7 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp<AaptFile>& dest)
continue;
}
e->setNameIndex(keyStrings.add(e->getName(), true));
- status_t err = e->prepareFlatten(&valueStrings, this);
- if (err != NO_ERROR) {
- return err;
- }
+ sortedEntries.insert(entry_sort_t(p, t, c, config, e));
}
}
}
@@ -2580,6 +2608,16 @@ status_t ResourceTable::flatten(Bundle* bundle, const sp<AaptFile>& dest)
p->setKeyStrings(keyStrings.createStringBlock());
}
+ for (std::set< entry_sort_t >::iterator ei=sortedEntries.begin(); ei!=sortedEntries.end(); ++ei) {
+ sp<Entry> e = ei->e;
+ status_t err = e->prepareFlatten(&valueStrings, this);
+ if (err != NO_ERROR) {
+ return err;
+ }
+ }
+
+ sortedEntries.clear();
+
ssize_t strAmt = 0;
// Now build the array of package chunks.
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas.java b/tools/layoutlib/bridge/src/android/graphics/Canvas.java
index d5d315e..08092a2 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas.java
@@ -49,6 +49,8 @@ import javax.microedition.khronos.opengles.GL;
*/
public class Canvas extends _Original_Canvas {
+ private static final char FIRST_RIGHT_TO_LEFT = '\u0590';
+ private static final char LAST_RIGHT_TO_LEFT = '\u07b1';
private BufferedImage mBufferedImage;
private final Stack<Graphics2D> mGraphicsStack = new Stack<Graphics2D>();
private final ILayoutLog mLogger;
@@ -644,11 +646,111 @@ public class Canvas extends _Original_Canvas {
getGraphics2d().scale(sx, sy);
}
- /* (non-Javadoc)
- * @see android.graphics.Canvas#drawText(char[], int, int, float, float, android.graphics.Paint)
- */
- @Override
- public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
+ public char[] bidiProcess(char[] text,int start,int src_count) {
+ String str;
+ String oldstr=new String(text,start,src_count);
+ boolean hasbidi=false;
+ int strlen=oldstr.length();
+ char[] ca=new char[strlen];
+
+ oldstr.getChars(0, strlen, ca, 0);
+ for (int i=0;i<oldstr.length();i++){
+ if (ca[i]>=FIRST_RIGHT_TO_LEFT&&ca[i]<=LAST_RIGHT_TO_LEFT){
+ hasbidi=true;
+ break;
+ }
+ }
+ if (hasbidi) {
+ char[] ca2=new char[strlen];
+ int count=0,srcindex=0;
+ boolean rtlmode=true;
+ for (int i=0;i<strlen;i++){
+ srcindex=strlen-1-i;
+ if (ca[srcindex]>=FIRST_RIGHT_TO_LEFT&&ca[srcindex]<=LAST_RIGHT_TO_LEFT){
+ ca2[i]=ca[srcindex];
+ rtlmode=true;
+ }
+ else {
+ srcindex=strlen-1-i;
+ if (count==0) {
+ if (ca[srcindex]<='\u002f' ||
+ (ca[srcindex]>'\u0039' && ca[srcindex]<='\u0040') ||
+ (ca[srcindex]>'\u005a' && ca[srcindex]<='\u0060')||
+ (ca[srcindex]>'\u007a' && ca[srcindex]<='\u00BF')) {
+
+ if (rtlmode){
+ switch (ca[srcindex]) {
+ case '[':
+ ca2[i]=']';
+ break;
+ case ']':
+ ca2[i]='[';
+ break;
+ case '}':
+ ca2[i]='{';
+ break;
+ case '{':
+ ca2[i]='}';
+ break;
+ case '(':
+ ca2[i]=')';
+ break;
+ case ')':
+ ca2[i]='(';
+ break;
+ case '>':
+ ca2[i]='<';
+ break;
+ case '<':
+ ca2[i]='>';
+ break;
+ default:
+ ca2[i]=ca[srcindex];
+ break;
+ }
+ } else ca2[i]=ca[srcindex];
+ } else {
+
+ while (((srcindex-count)>=0)&&(ca[srcindex-count]<FIRST_RIGHT_TO_LEFT)){
+ count++;
+ }
+ int index=0;
+ int punctuation_marks=0;
+
+ while ((srcindex-(count)>=0) &&
+ (ca[srcindex-(count-1)]<='\u002f' ||
+ (ca[srcindex-(count-1)]>'\u0039' && ca[srcindex-(count-1)]<='\u0040') ||
+ (ca[srcindex-(count-1)]>'\u005a' && ca[srcindex-(count-1)]<='\u0060')||
+ (ca[srcindex-(count-1)]>'\u007a' && ca[srcindex-(count-1)]<='\u00BF'))){
+ ca2[i+(count-1)]=ca[srcindex-(count-1)];
+ count--;
+ punctuation_marks++;
+ }
+
+ while (count>0){
+ ca2[i+index]=ca[srcindex-(count-1)];
+ count--;
+ index++;
+ }
+ count=index+punctuation_marks-1;
+ }
+ }
+ else {
+ count--;
+ }
+ rtlmode=false;
+ }
+ }
+ str=new String(ca2);
+ } else
+ {
+ str=new String(oldstr);
+ }
+ return str.toCharArray();
+
+ }
+
+ public void drawText(char[] text, int index, int count, float x, float y, Paint paint, boolean bidi) {
// WARNING: the logic in this method is similar to Paint.measureText.
// Any change to this method should be reflected in Paint.measureText
Graphics2D g = getGraphics2d();
@@ -681,21 +783,29 @@ public class Canvas extends _Original_Canvas {
FontInfo mainFont = fonts.get(0);
int i = index;
int lastIndex = index + count;
+ char[] bidiText;
+ if (bidi) {
+ bidiText=bidiProcess(text,index,count);
+ i=0;
+ lastIndex=count;
+ } else {
+ bidiText=text;
+ }
while (i < lastIndex) {
// always start with the main font.
- int upTo = mainFont.mFont.canDisplayUpTo(text, i, lastIndex);
+ int upTo = mainFont.mFont.canDisplayUpTo(bidiText, i, lastIndex);
if (upTo == -1) {
// draw all the rest and exit.
g.setFont(mainFont.mFont);
- g.drawChars(text, i, lastIndex - i, (int)x, (int)y);
+ g.drawChars(bidiText, i, lastIndex - i, (int)x, (int)y);
return;
} else if (upTo > 0) {
// draw what's possible
g.setFont(mainFont.mFont);
- g.drawChars(text, i, upTo - i, (int)x, (int)y);
+ g.drawChars(bidiText, i, upTo - i, (int)x, (int)y);
// compute the width that was drawn to increase x
- x += mainFont.mMetrics.charsWidth(text, i, upTo - i);
+ x += mainFont.mMetrics.charsWidth(bidiText, i, upTo - i);
// move index to the first non displayed char.
i = upTo;
@@ -715,15 +825,15 @@ public class Canvas extends _Original_Canvas {
// need to check that the font can display the character. We test
// differently if the char is a high surrogate.
- int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1;
- upTo = fontInfo.mFont.canDisplayUpTo(text, i, i + charCount);
+ int charCount = Character.isHighSurrogate(bidiText[i]) ? 2 : 1;
+ upTo = fontInfo.mFont.canDisplayUpTo(bidiText, i, i + charCount);
if (upTo == -1) {
// draw that char
g.setFont(fontInfo.mFont);
- g.drawChars(text, i, charCount, (int)x, (int)y);
+ g.drawChars(bidiText, i, charCount, (int)x, (int)y);
// update x
- x += fontInfo.mMetrics.charsWidth(text, i, charCount);
+ x += fontInfo.mMetrics.charsWidth(bidiText, i, charCount);
// update the index in the text, and move on
i += charCount;
@@ -736,13 +846,13 @@ public class Canvas extends _Original_Canvas {
// in case no font can display the char, display it with the main font.
// (it'll put a square probably)
if (foundFont == false) {
- int charCount = Character.isHighSurrogate(text[i]) ? 2 : 1;
+ int charCount = Character.isHighSurrogate(bidiText[i]) ? 2 : 1;
g.setFont(mainFont.mFont);
- g.drawChars(text, i, charCount, (int)x, (int)y);
+ g.drawChars(bidiText, i, charCount, (int)x, (int)y);
// measure it to advance x
- x += mainFont.mMetrics.charsWidth(text, i, charCount);
+ x += mainFont.mMetrics.charsWidth(bidiText, i, charCount);
// and move to the next chars.
i += charCount;
@@ -755,6 +865,13 @@ public class Canvas extends _Original_Canvas {
}
/* (non-Javadoc)
+ * @see android.graphics.Canvas#drawText(char[], int, int, float, float, android.graphics.Paint)
+ */
+ @Override
+ public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
+ drawText(text, index, count, x, y, paint, true);
+ }
+ /* (non-Javadoc)
* @see android.graphics.Canvas#drawText(java.lang.CharSequence, int, int, float, float, android.graphics.Paint)
*/
@Override
@@ -1140,7 +1257,10 @@ public class Canvas extends _Original_Canvas {
public void drawTextOnPath(char[] text, int index, int count, Path path, float offset,
float offset2, Paint paint) {
// TODO Auto-generated method stub
- super.drawTextOnPath(text, index, count, path, offset, offset2, paint);
+ int i = 0;
+ char[] bidiText;
+ bidiText=bidiProcess(text,index,count);
+ super.drawTextOnPath(bidiText, i, count, path, offset, offset2, paint);
}
/* (non-Javadoc)
@@ -1149,7 +1269,10 @@ public class Canvas extends _Original_Canvas {
@Override
public void drawTextOnPath(String text, Path path, float offset, float offset2, Paint paint) {
// TODO Auto-generated method stub
- super.drawTextOnPath(text, path, offset, offset2, paint);
+ int i = 0;
+ String bidiText;
+ bidiText=new String(bidiProcess(text.toCharArray(),0,text.length()));
+ super.drawTextOnPath(bidiText, path, offset, offset2, paint);
}
/* (non-Javadoc)
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint.java b/tools/layoutlib/bridge/src/android/graphics/Paint.java
index 619ab30..d13b5fe 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint.java
@@ -283,6 +283,8 @@ public class Paint extends _Original_Paint {
mStyle = src.mStyle;
mFlags = src.mFlags;
+ updateFontObject();
+
super.set(src);
}
}
diff --git a/vpn/java/android/net/vpn/OpenvpnProfile.java b/vpn/java/android/net/vpn/OpenvpnProfile.java
new file mode 100644
index 0000000..f1fd2f6
--- /dev/null
+++ b/vpn/java/android/net/vpn/OpenvpnProfile.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vpn;
+
+import android.os.Parcel;
+
+/**
+ * The profile for Openvpn type of VPN.
+ * {@hide}
+ */
+public class OpenvpnProfile extends VpnProfile {
+ private static final long serialVersionUID = 1L;
+
+ private static final String PROTO_UDP = "udp";
+
+ private static final String PROTO_TCP = "tcp";
+
+ private static final String DEVICE_TUN = "tun";
+
+ private static final String DEVICE_TAP = "tap";
+
+ // Standard Settings
+ private boolean mUserAuth = false;
+
+ private String mCA;
+
+ private String mCert;
+
+ // Advanced Settings
+ private int mPort = 1194;
+
+ private String mProto = PROTO_UDP;
+
+ private boolean mUseCompLzo = false;
+
+ private boolean mSupplyAddr = false;
+
+ private boolean mRedirectGateway = false;
+
+ private String mLocalAddr;
+
+ private String mRemoteAddr;
+
+ private String mDevice = DEVICE_TUN;
+
+ private String mCipher;
+
+ private int mKeySize;
+
+ private String mExtra;
+
+ @Override
+ public VpnType getType() {
+ return VpnType.OPENVPN;
+ }
+
+ public void setPort(String port) {
+ try {
+ mPort = Integer.parseInt(port);
+ } catch (NumberFormatException e) {
+ // no update
+ }
+ }
+
+ public String getPort() {
+ return Integer.toString(mPort);
+ }
+
+ public String getProto() {
+ return mProto;
+ }
+
+ public CharSequence[] getProtoList() {
+ String[] s = new String[2];
+ s[0] = PROTO_UDP;
+ s[1] = PROTO_TCP;
+ return s;
+ }
+
+ public void setProto(String p) {
+ if (p.contains(PROTO_TCP))
+ mProto = PROTO_TCP;
+ else if (p.contains(PROTO_UDP))
+ mProto = PROTO_UDP;
+ }
+
+ public String getDevice() {
+ return mDevice;
+ }
+
+ public CharSequence[] getDeviceList() {
+ String[] s = new String[2];
+ s[0] = DEVICE_TUN;
+ s[1] = DEVICE_TAP;
+ return s;
+ }
+
+ public void setDevice(String p) {
+ if (p.contains(DEVICE_TAP))
+ mDevice = DEVICE_TAP;
+ else if (p.contains(DEVICE_TUN))
+ mDevice = DEVICE_TUN;
+ }
+
+ public boolean getUserAuth() {
+ return mUserAuth;
+ }
+
+ public void setUserAuth(boolean auth) {
+ mUserAuth = auth;
+ }
+
+ public String getCAName() {
+ return mCA;
+ }
+
+ public void setCAName(String name) {
+ mCA = name;
+ }
+
+ public String getCertName() {
+ return mCert;
+ }
+
+ public void setCertName(String name) {
+ mCert = name;
+ }
+
+ public void setUseCompLzo(boolean b) {
+ mUseCompLzo = b;
+ }
+
+ public boolean getUseCompLzo() {
+ return mUseCompLzo;
+ }
+
+ public void setRedirectGateway(boolean b) {
+ mRedirectGateway = b;
+ }
+
+ public boolean getRedirectGateway() {
+ return mRedirectGateway;
+ }
+
+ public void setSupplyAddr(boolean b) {
+ mSupplyAddr = b;
+ }
+
+ public boolean getSupplyAddr() {
+ return mSupplyAddr;
+ }
+
+ public void setLocalAddr(String addr) {
+ mLocalAddr = addr;
+ }
+
+ public String getLocalAddr() {
+ return mLocalAddr;
+ }
+
+ public void setRemoteAddr(String addr) {
+ mRemoteAddr = addr;
+ }
+
+ public String getRemoteAddr() {
+ return mRemoteAddr;
+ }
+
+ public void setCipher(String cipher) {
+ mCipher = cipher;
+ }
+
+ public String getCipher() {
+ return mCipher;
+ }
+
+ public void setKeySize(String keysize) {
+ try {
+ if (keysize.equals("0"))
+ mKeySize = 0;
+ else
+ mKeySize = Integer.parseInt(keysize);
+ } catch (NumberFormatException e) {
+ // no update
+ }
+ }
+
+ public String getKeySize() {
+ return Integer.toString(mKeySize);
+ }
+
+ public void setExtra(String extra) {
+ mExtra = extra;
+ }
+
+ public String getExtra() {
+ return mExtra;
+ }
+
+ @Override
+ protected void readFromParcel(Parcel in) {
+ super.readFromParcel(in);
+ mPort = in.readInt();
+ mProto = in.readString();
+ mUserAuth = in.readInt() == 1;
+ mCA = in.readString();
+ mCert = in.readString();
+ mUseCompLzo = in.readInt() == 1;
+ mRedirectGateway = in.readInt() == 1;
+ mSupplyAddr = in.readInt() == 1;
+ mLocalAddr = in.readString();
+ mRemoteAddr = in.readString();
+ mDevice = in.readString();
+ mCipher = in.readString();
+ mKeySize = in.readInt();
+ mExtra = in.readString();
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ super.writeToParcel(parcel, flags);
+ parcel.writeInt(mPort);
+ parcel.writeString(mProto);
+ parcel.writeInt(mUserAuth ? 1 : 0);
+ parcel.writeString(mCA);
+ parcel.writeString(mCert);
+ parcel.writeInt(mUseCompLzo ? 1 : 0);
+ parcel.writeInt(mRedirectGateway ? 1 : 0);
+ parcel.writeInt(mSupplyAddr ? 1 : 0);
+ parcel.writeString(mLocalAddr);
+ parcel.writeString(mRemoteAddr);
+ parcel.writeString(mDevice);
+ parcel.writeString(mCipher);
+ parcel.writeInt(mKeySize);
+ parcel.writeString(mExtra);
+ }
+}
diff --git a/vpn/java/android/net/vpn/VpnManager.java b/vpn/java/android/net/vpn/VpnManager.java
index ce522c8..c588076 100644
--- a/vpn/java/android/net/vpn/VpnManager.java
+++ b/vpn/java/android/net/vpn/VpnManager.java
@@ -69,7 +69,7 @@ public class VpnManager {
/** Error code to indicate a successful connection. */
public static final int VPN_ERROR_NO_ERROR = 0;
- public static final String PROFILES_PATH = "/misc/vpn/profiles";
+ public static final String PROFILES_PATH = "/data/misc/vpn/profiles";
private static final String PACKAGE_PREFIX =
VpnManager.class.getPackage().getName() + ".";
diff --git a/vpn/java/android/net/vpn/VpnType.java b/vpn/java/android/net/vpn/VpnType.java
index 356f8b1..2157067 100644
--- a/vpn/java/android/net/vpn/VpnType.java
+++ b/vpn/java/android/net/vpn/VpnType.java
@@ -28,7 +28,8 @@ public enum VpnType {
L2TP_IPSEC_PSK("L2TP/IPSec PSK", R.string.l2tp_ipsec_psk_vpn_description,
L2tpIpsecPskProfile.class),
L2TP_IPSEC("L2TP/IPSec CRT", R.string.l2tp_ipsec_crt_vpn_description,
- L2tpIpsecProfile.class);
+ L2tpIpsecProfile.class),
+ OPENVPN("OpenVPN", R.string.openvpn_vpn_description, OpenvpnProfile.class);
private String mDisplayName;
private int mDescriptionId;
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index f98cd28..f4afc36 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -16,8 +16,6 @@
package android.net.wifi;
-import android.net.DhcpInfo;
-
/**
* Native calls for sending requests to the supplicant daemon, and for
* receiving asynchronous events. All methods of the form "xxxxCommand()"
@@ -143,10 +141,6 @@ public class WifiNative {
public native static boolean clearBlacklistCommand();
- public native static boolean doDhcpRequest(DhcpInfo results);
-
- public native static String getDhcpError();
-
/**
* Wait for the supplicant to send an event, returning the event string.
* @return the event string sent by the supplicant.
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 3813015..542a0ac 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -69,7 +69,7 @@ import java.util.concurrent.atomic.AtomicInteger;
public class WifiStateTracker extends NetworkStateTracker {
private static final boolean LOCAL_LOGD = Config.LOGD || false;
-
+
private static final String TAG = "WifiStateTracker";
// Event log tags (must be in sync with event-log-tags)
@@ -216,12 +216,12 @@ public class WifiStateTracker extends NetworkStateTracker {
private boolean mUseStaticIp = false;
private int mReconnectCount;
- // used to store the (non-persisted) num determined during device boot
+ // used to store the (non-persisted) num determined during device boot
// (from mcc or other phone info) before the driver is started.
private int mNumAllowedChannels = 0;
// Variables relating to the 'available networks' notification
-
+
/**
* The icon to show in the 'available networks' notification. This will also
* be the ID of the Notification given to the NotificationManager.
@@ -273,7 +273,7 @@ public class WifiStateTracker extends NetworkStateTracker {
* Observes the static IP address settings.
*/
private SettingsObserver mSettingsObserver;
-
+
private boolean mIsScanModeActive;
private boolean mEnableRssiPolling;
@@ -313,8 +313,6 @@ public class WifiStateTracker extends NetworkStateTracker {
private String mInterfaceName;
private static String LS = System.getProperty("line.separator");
- private static String[] sDnsPropNames;
-
/**
* A structure for supplying information about a supplicant state
* change in the STATE_CHANGE event message that comes from the
@@ -350,7 +348,7 @@ public class WifiStateTracker extends NetworkStateTracker {
public WifiStateTracker(Context context, Handler target) {
super(context, target, ConnectivityManager.TYPE_WIFI, 0, "WIFI", "");
-
+
mWifiInfo = new WifiInfo();
mWifiMonitor = new WifiMonitor(this);
mHaveIpAddress = false;
@@ -363,7 +361,7 @@ public class WifiStateTracker extends NetworkStateTracker {
mRunState = RUN_STATE_STARTING;
// Setting is in seconds
- NOTIFICATION_REPEAT_DELAY_MS = Settings.Secure.getInt(context.getContentResolver(),
+ NOTIFICATION_REPEAT_DELAY_MS = Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY, 900) * 1000l;
mNotificationEnabledSettingObserver = new NotificationEnabledSettingObserver(new Handler());
mNotificationEnabledSettingObserver.register();
@@ -371,9 +369,9 @@ public class WifiStateTracker extends NetworkStateTracker {
mSettingsObserver = new SettingsObserver(new Handler());
mInterfaceName = SystemProperties.get("wifi.interface", "tiwlan0");
- sDnsPropNames = new String[] {
- "dhcp." + mInterfaceName + ".dns1",
- "dhcp." + mInterfaceName + ".dns2"
+ mDnsPropNames = new String[] {
+ "net." + mInterfaceName + ".dns1",
+ "net." + mInterfaceName + ".dns2"
};
mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
@@ -418,15 +416,6 @@ public class WifiStateTracker extends NetworkStateTracker {
}
/**
- * Return the IP addresses of the DNS servers available for the WLAN
- * network interface.
- * @return a list of DNS addresses, with no holes.
- */
- public String[] getNameServers() {
- return getNameServerList(sDnsPropNames);
- }
-
- /**
* Return the name of our WLAN network interface.
* @return the name of our interface.
*/
@@ -994,10 +983,10 @@ public class WifiStateTracker extends NetworkStateTracker {
// Wi-Fi network state changed:
// [31- 6] Reserved for future use
- // [ 5- 0] Detailed state ordinal (as defined by NetworkInfo.DetailedState)
+ // [ 5- 0] Detailed state ordinal (as defined by NetworkInfo.DetailedState)
eventLogParam = (result.state.ordinal() & 0x3f);
EventLog.writeEvent(EVENTLOG_NETWORK_STATE_CHANGED, eventLogParam);
-
+
if (LOCAL_LOGD) Log.v(TAG, "New network state is " + result.state);
/*
* If we're in scan-only mode, don't advance the state machine, and
@@ -1085,7 +1074,7 @@ public class WifiStateTracker extends NetworkStateTracker {
checkPollTimer();
}
break;
-
+
case EVENT_DEFERRED_DISCONNECT:
if (mWifiInfo.getSupplicantState() != SupplicantState.UNINITIALIZED) {
handleDisconnectedState(DetailedState.DISCONNECTED, true);
@@ -1137,7 +1126,7 @@ public class WifiStateTracker extends NetworkStateTracker {
if (LOCAL_LOGD) Log.v(TAG, "IP configuration: " + mDhcpInfo);
// Wi-Fi interface configuration state changed:
// [31- 1] Reserved for future use
- // [ 0- 0] Interface configuration succeeded (1) or failed (0)
+ // [ 0- 0] Interface configuration succeeded (1) or failed (0)
EventLog.writeEvent(EVENTLOG_INTERFACE_CONFIGURATION_STATE_CHANGED, 1);
// We've connected successfully, so allow the notification again in the future
@@ -1357,7 +1346,7 @@ public class WifiStateTracker extends NetworkStateTracker {
int netId = -1;
String[] lines = reply.split("\n");
for (String line : lines) {
- String[] prop = line.split(" *= *");
+ String[] prop = line.split(" *= *", 2);
if (prop.length < 2)
continue;
String name = prop[0];
@@ -2094,7 +2083,7 @@ public class WifiStateTracker extends NetworkStateTracker {
numOpenNetworks++;
}
}
-
+
if (numOpenNetworks > 0) {
if (++mNumScansSinceNetworkStateChange >= NUM_SCANS_BEFORE_ACTUALLY_SCANNING) {
/*
@@ -2110,7 +2099,7 @@ public class WifiStateTracker extends NetworkStateTracker {
}
}
}
-
+
// No open networks in range, remove the notification
setNotificationVisible(false, 0, false, 0);
}
@@ -2125,13 +2114,13 @@ public class WifiStateTracker extends NetworkStateTracker {
* visible or invisible.
*/
public void setNotificationVisible(boolean visible, int numNetworks, boolean force, int delay) {
-
+
// Since we use auto cancel on the notification, when the
// mNetworksAvailableNotificationShown is true, the notification may
// have actually been canceled. However, when it is false we know
// for sure that it is not being shown (it will not be shown any other
// place than here)
-
+
// If it should be hidden and it is already hidden, then noop
if (!visible && !mNotificationShown && !force) {
return;
@@ -2139,12 +2128,12 @@ public class WifiStateTracker extends NetworkStateTracker {
Message message;
if (visible) {
-
+
// Not enough time has passed to show the notification again
if (System.currentTimeMillis() < mNotificationRepeatTime) {
return;
}
-
+
if (mNotification == null) {
// Cache the Notification mainly so we can remove the
// EVENT_NOTIFICATION_CHANGED message with this Notification from
@@ -2163,22 +2152,22 @@ public class WifiStateTracker extends NetworkStateTracker {
com.android.internal.R.plurals.wifi_available_detailed, numNetworks);
mNotification.tickerText = title;
mNotification.setLatestEventInfo(mContext, title, details, mNotification.contentIntent);
-
+
mNotificationRepeatTime = System.currentTimeMillis() + NOTIFICATION_REPEAT_DELAY_MS;
message = mTarget.obtainMessage(EVENT_NOTIFICATION_CHANGED, 1,
ICON_NETWORKS_AVAILABLE, mNotification);
-
+
} else {
// Remove any pending messages to show the notification
mTarget.removeMessages(EVENT_NOTIFICATION_CHANGED, mNotification);
-
+
message = mTarget.obtainMessage(EVENT_NOTIFICATION_CHANGED, 0, ICON_NETWORKS_AVAILABLE);
}
mTarget.sendMessageDelayed(message, delay);
-
+
mNotificationShown = visible;
}
@@ -2193,7 +2182,7 @@ public class WifiStateTracker extends NetworkStateTracker {
mNotificationRepeatTime = 0;
mNumScansSinceNetworkStateChange = 0;
}
-
+
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
@@ -2217,7 +2206,7 @@ public class WifiStateTracker extends NetworkStateTracker {
private class DhcpHandler extends Handler {
private Handler mTarget;
-
+
/**
* Whether to skip the DHCP result callback to the target. For example,
* this could be set if the network we were requesting an IP for has
@@ -2237,11 +2226,11 @@ public class WifiStateTracker extends NetworkStateTracker {
* in an error state and we will not disable coexistence.
*/
private BluetoothHeadset mBluetoothHeadset;
-
+
public DhcpHandler(Looper looper, Handler target) {
super(looper);
mTarget = target;
-
+
mBluetoothHeadset = new BluetoothHeadset(mContext, null);
}
@@ -2250,7 +2239,7 @@ public class WifiStateTracker extends NetworkStateTracker {
switch (msg.what) {
case EVENT_DHCP_START:
-
+
boolean modifiedBluetoothCoexistenceMode = false;
if (shouldDisableCoexistenceMode()) {
/*
@@ -2319,7 +2308,7 @@ public class WifiStateTracker extends NetworkStateTracker {
* headset/handsfree state is disconnected. This means if it is in an
* error state, we will NOT disable coexistence mode to err on the side
* of safety.
- *
+ *
* @return Whether to disable coexistence mode.
*/
private boolean shouldDisableCoexistenceMode() {
@@ -2327,7 +2316,7 @@ public class WifiStateTracker extends NetworkStateTracker {
return state == BluetoothHeadset.STATE_DISCONNECTED;
}
}
-
+
private void checkUseStaticIp() {
mUseStaticIp = false;
final ContentResolver cr = mContext.getContentResolver();