summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.xml601
-rw-r--r--cmds/stagefright/record.cpp60
-rw-r--r--core/java/android/app/Activity.java13
-rw-r--r--core/java/android/app/ActivityThread.java11
-rw-r--r--core/java/android/app/backup/package.html6
-rw-r--r--core/java/android/database/sqlite/SQLiteDebug.java2
-rw-r--r--core/java/android/hardware/Camera.java25
-rw-r--r--core/java/android/net/DownloadManager.java23
-rw-r--r--core/java/android/net/LocalSocket.java7
-rw-r--r--core/java/android/os/BatteryStats.java25
-rw-r--r--core/java/android/os/RecoverySystem.java15
-rw-r--r--core/java/android/provider/Downloads.java15
-rw-r--r--core/java/android/provider/Settings.java9
-rw-r--r--core/java/android/webkit/WebView.java19
-rw-r--r--core/java/android/widget/EdgeGlow.java106
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java80
-rw-r--r--[-rwxr-xr-x]core/res/res/drawable-hdpi/btn_circle_disable.pngbin2601 -> 2727 bytes
-rw-r--r--[-rwxr-xr-x]core/res/res/drawable-hdpi/btn_circle_disable_focused.pngbin2729 -> 2330 bytes
-rw-r--r--[-rwxr-xr-x]core/res/res/drawable-hdpi/expander_ic_maximized.9.pngbin2993 -> 2955 bytes
-rw-r--r--[-rwxr-xr-x]core/res/res/drawable-hdpi/expander_ic_minimized.9.pngbin2955 -> 2993 bytes
-rw-r--r--core/res/res/drawable-hdpi/jog_tab_left_confirm_gray.pngbin6964 -> 5415 bytes
-rw-r--r--core/res/res/drawable-hdpi/jog_tab_left_confirm_green.pngbin11428 -> 5929 bytes
-rw-r--r--core/res/res/drawable-hdpi/jog_tab_left_confirm_yellow.pngbin11501 -> 5861 bytes
-rw-r--r--core/res/res/drawable-hdpi/jog_tab_left_normal.pngbin10304 -> 5013 bytes
-rw-r--r--core/res/res/drawable-hdpi/jog_tab_left_pressed.pngbin9897 -> 5240 bytes
-rw-r--r--core/res/res/drawable-hdpi/jog_tab_right_confirm_gray.pngbin6402 -> 5297 bytes
-rw-r--r--core/res/res/drawable-hdpi/jog_tab_right_confirm_green.pngbin10627 -> 5735 bytes
-rw-r--r--core/res/res/drawable-hdpi/jog_tab_right_confirm_yellow.pngbin10912 -> 5681 bytes
-rw-r--r--core/res/res/drawable-hdpi/jog_tab_right_normal.pngbin9768 -> 4765 bytes
-rw-r--r--core/res/res/drawable-hdpi/jog_tab_right_pressed.pngbin9250 -> 5039 bytes
-rw-r--r--core/res/res/drawable-hdpi/overscroll_edge.pngbin4515 -> 3582 bytes
-rw-r--r--[-rwxr-xr-x]core/res/res/drawable-hdpi/popup_center_dark.9.pngbin1139 -> 1151 bytes
-rw-r--r--[-rwxr-xr-x]core/res/res/drawable-hdpi/stat_notify_chat.pngbin1663 -> 1625 bytes
-rw-r--r--core/res/res/drawable-mdpi/expander_ic_maximized.9.pngbin1150 -> 1929 bytes
-rw-r--r--core/res/res/drawable-mdpi/expander_ic_minimized.9.pngbin1167 -> 1982 bytes
-rw-r--r--core/res/res/drawable-mdpi/jog_tab_left_confirm_gray.pngbin4306 -> 4963 bytes
-rw-r--r--core/res/res/drawable-mdpi/jog_tab_left_confirm_green.pngbin6753 -> 5516 bytes
-rw-r--r--core/res/res/drawable-mdpi/jog_tab_left_confirm_yellow.pngbin6879 -> 5310 bytes
-rw-r--r--core/res/res/drawable-mdpi/jog_tab_left_normal.pngbin6227 -> 4204 bytes
-rw-r--r--core/res/res/drawable-mdpi/jog_tab_left_pressed.pngbin5994 -> 4399 bytes
-rw-r--r--core/res/res/drawable-mdpi/jog_tab_right_confirm_gray.pngbin3959 -> 4887 bytes
-rw-r--r--core/res/res/drawable-mdpi/jog_tab_right_confirm_green.pngbin6278 -> 5472 bytes
-rw-r--r--core/res/res/drawable-mdpi/jog_tab_right_confirm_yellow.pngbin6392 -> 5181 bytes
-rw-r--r--core/res/res/drawable-mdpi/jog_tab_right_normal.pngbin5750 -> 4135 bytes
-rw-r--r--core/res/res/drawable-mdpi/jog_tab_right_pressed.pngbin5626 -> 4221 bytes
-rw-r--r--core/res/res/drawable-mdpi/overscroll_edge.pngbin0 -> 2180 bytes
-rw-r--r--core/res/res/drawable-mdpi/overscroll_glow.pngbin0 -> 30390 bytes
-rw-r--r--core/res/res/drawable-mdpi/text_select_handle_middle.pngbin0 -> 742 bytes
-rw-r--r--core/tests/coretests/AndroidManifest.xml1
-rw-r--r--core/tests/coretests/src/android/net/DownloadManagerBaseTest.java31
-rw-r--r--core/tests/coretests/src/android/net/DownloadManagerIntegrationTest.java264
-rw-r--r--core/tests/hosttests/src/android/net/DownloadManagerHostTests.java27
-rw-r--r--core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java57
-rw-r--r--core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestRunner.java2
-rw-r--r--include/camera/CameraParameters.h14
-rw-r--r--libs/camera/CameraParameters.cpp2
-rw-r--r--location/java/android/location/Geocoder.java8
-rw-r--r--location/java/android/location/GeocoderParams.java2
-rw-r--r--location/java/android/location/ILocationManager.aidl2
-rw-r--r--location/java/android/location/provider/GeocodeProvider.java2
-rw-r--r--location/java/android/location/provider/LocationProvider.java2
-rw-r--r--media/java/android/media/AudioEffect.java68
-rw-r--r--media/libstagefright/codecs/aacdec/AACDecoder.cpp69
-rw-r--r--media/libstagefright/include/AACDecoder.h2
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.pngbin4228 -> 1732 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g_fully.pngbin4240 -> 1742 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.pngbin4423 -> 1861 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g_fully.pngbin4458 -> 1896 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g.pngbin4515 -> 1911 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g_fully.pngbin4534 -> 1966 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.pngbin4429 -> 1891 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g_fully.pngbin4454 -> 1917 bytes
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java17
-rw-r--r--services/java/com/android/server/ConnectivityService.java43
-rw-r--r--services/java/com/android/server/LocationManagerService.java2
-rw-r--r--services/java/com/android/server/PackageManagerService.java20
-rw-r--r--services/java/com/android/server/WifiService.java36
-rw-r--r--services/java/com/android/server/WindowManagerService.java5
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java140
-rw-r--r--services/java/com/android/server/am/ActivityStack.java38
-rw-r--r--telephony/java/com/android/internal/telephony/CallManager.java133
-rw-r--r--telephony/java/com/android/internal/telephony/Phone.java4
-rwxr-xr-xtelephony/java/com/android/internal/telephony/sip/SipPhone.java30
-rwxr-xr-xtelephony/java/com/android/internal/telephony/sip/SipPhoneBase.java2
-rw-r--r--wifi/java/android/net/wifi/IWifiManager.aidl2
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java6
88 files changed, 1226 insertions, 847 deletions
diff --git a/api/current.xml b/api/current.xml
index 8651c4d7e6e9..760e5e05c4ac 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -76944,11 +76944,11 @@
visibility="public"
>
</field>
-<field name="FOCUS_MODE_CONTINUOUS"
+<field name="FOCUS_MODE_CONTINUOUS_VIDEO"
type="java.lang.String"
transient="false"
volatile="false"
- value="&quot;continuous&quot;"
+ value="&quot;continuous-video&quot;"
static="true"
final="true"
deprecated="not deprecated"
@@ -82537,8 +82537,8 @@
<exception name="IOException" type="java.io.IOException">
</exception>
</method>
-<method name="isImplemented"
- return="java.lang.Boolean"
+<method name="isPresent"
+ return="boolean"
abstract="false"
native="false"
synchronized="false"
@@ -82549,75 +82549,6 @@
>
</method>
</class>
-<class name="GeocoderParams"
- extends="java.lang.Object"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.os.Parcelable">
-</implements>
-<method name="describeContents"
- return="int"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getClientPackage"
- return="java.lang.String"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="getLocale"
- return="java.util.Locale"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="writeToParcel"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="parcel" type="android.os.Parcel">
-</parameter>
-<parameter name="flags" type="int">
-</parameter>
-</method>
-<field name="CREATOR"
- type="android.os.Parcelable.Creator"
- transient="false"
- volatile="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
<class name="GpsSatellite"
extends="java.lang.Object"
abstract="false"
@@ -84209,396 +84140,6 @@
</field>
</class>
</package>
-<package name="android.location.provider"
->
-<class name="GeocodeProvider"
- extends="java.lang.Object"
- abstract="true"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="GeocodeProvider"
- type="android.location.provider.GeocodeProvider"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="getBinder"
- return="android.os.IBinder"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onGetFromLocation"
- return="java.lang.String"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="latitude" type="double">
-</parameter>
-<parameter name="longitude" type="double">
-</parameter>
-<parameter name="maxResults" type="int">
-</parameter>
-<parameter name="params" type="android.location.GeocoderParams">
-</parameter>
-<parameter name="addrs" type="java.util.List&lt;android.location.Address&gt;">
-</parameter>
-</method>
-<method name="onGetFromLocationName"
- return="java.lang.String"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="locationName" type="java.lang.String">
-</parameter>
-<parameter name="lowerLeftLatitude" type="double">
-</parameter>
-<parameter name="lowerLeftLongitude" type="double">
-</parameter>
-<parameter name="upperRightLatitude" type="double">
-</parameter>
-<parameter name="upperRightLongitude" type="double">
-</parameter>
-<parameter name="maxResults" type="int">
-</parameter>
-<parameter name="params" type="android.location.GeocoderParams">
-</parameter>
-<parameter name="addrs" type="java.util.List&lt;android.location.Address&gt;">
-</parameter>
-</method>
-</class>
-<class name="LocationProvider"
- extends="java.lang.Object"
- abstract="true"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="LocationProvider"
- type="android.location.provider.LocationProvider"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="getBinder"
- return="android.os.IBinder"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onAddListener"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="uid" type="int">
-</parameter>
-<parameter name="ws" type="android.os.WorkSource">
-</parameter>
-</method>
-<method name="onDisable"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onEnable"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onEnableLocationTracking"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="enable" type="boolean">
-</parameter>
-</method>
-<method name="onGetAccuracy"
- return="int"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onGetInternalState"
- return="java.lang.String"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onGetPowerRequirement"
- return="int"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onGetStatus"
- return="int"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="extras" type="android.os.Bundle">
-</parameter>
-</method>
-<method name="onGetStatusUpdateTime"
- return="long"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onHasMonetaryCost"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onMeetsCriteria"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="criteria" type="android.location.Criteria">
-</parameter>
-</method>
-<method name="onRemoveListener"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="uid" type="int">
-</parameter>
-<parameter name="ws" type="android.os.WorkSource">
-</parameter>
-</method>
-<method name="onRequiresCell"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onRequiresNetwork"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onRequiresSatellite"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onSendExtraCommand"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="command" type="java.lang.String">
-</parameter>
-<parameter name="extras" type="android.os.Bundle">
-</parameter>
-</method>
-<method name="onSetMinTime"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="minTime" type="long">
-</parameter>
-<parameter name="ws" type="android.os.WorkSource">
-</parameter>
-</method>
-<method name="onSupportsAltitude"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onSupportsBearing"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onSupportsSpeed"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="onUpdateLocation"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="location" type="android.location.Location">
-</parameter>
-</method>
-<method name="onUpdateNetworkState"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="state" type="int">
-</parameter>
-<parameter name="info" type="android.net.NetworkInfo">
-</parameter>
-</method>
-<method name="reportLocation"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="location" type="android.location.Location">
-</parameter>
-</method>
-</class>
-</package>
<package name="android.media"
>
<class name="AsyncPlayer"
@@ -85188,6 +84729,39 @@
<parameter name="value" type="short">
</parameter>
</method>
+<field name="ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.media.action.DISPLAY_AUDIO_EFFECT_CONTROL_PANEL&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="ALREADY_EXISTS"
type="int"
transient="false"
@@ -85199,6 +84773,50 @@
visibility="public"
>
</field>
+<field name="CONTENT_TYPE_GAME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTENT_TYPE_MOVIE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTENT_TYPE_MUSIC"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="CONTENT_TYPE_VOICE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="EFFECT_AUXILIARY"
type="java.lang.String"
transient="false"
@@ -85347,6 +84965,39 @@
visibility="public"
>
</field>
+<field name="EXTRA_AUDIO_SESSION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.media.extra.AUDIO_SESSION&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_CONTENT_TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.media.extra.CONTENT_TYPE&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_PACKAGE_NAME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.media.extra.PACKAGE_NAME&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="NATIVE_EVENT_CONTROL_STATUS"
type="int"
transient="false"
@@ -96356,6 +96007,17 @@
visibility="public"
>
</field>
+<field name="ERROR_FILE_ALREADY_EXISTS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1009"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="ERROR_FILE_ERROR"
type="int"
transient="false"
@@ -96630,6 +96292,19 @@
<parameter name="value" type="java.lang.String">
</parameter>
</method>
+<method name="setShowRunningNotification"
+ return="android.net.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="show" type="boolean">
+</parameter>
+</method>
<method name="setTitle"
return="android.net.DownloadManager.Request"
abstract="false"
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
index c4242817bf4e..b7182991eaea 100644
--- a/cmds/stagefright/record.cpp
+++ b/cmds/stagefright/record.cpp
@@ -36,24 +36,30 @@ static const int32_t kFramerate = 24; // fps
static const int32_t kIFramesIntervalSec = 1;
static const int32_t kVideoBitRate = 512 * 1024;
static const int32_t kAudioBitRate = 12200;
-static const int32_t kColorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
static const int64_t kDurationUs = 10000000LL; // 10 seconds
#if 1
class DummySource : public MediaSource {
public:
- DummySource(int width, int height)
+ DummySource(int width, int height, int colorFormat)
: mWidth(width),
mHeight(height),
+ mColorFormat(colorFormat),
mSize((width * height * 3) / 2) {
mGroup.add_buffer(new MediaBuffer(mSize));
+
+ // Check the color format to make sure
+ // that the buffer size mSize it set correctly above.
+ CHECK(colorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
+ colorFormat == OMX_COLOR_FormatYUV420Planar);
}
virtual sp<MetaData> getFormat() {
sp<MetaData> meta = new MetaData;
meta->setInt32(kKeyWidth, mWidth);
meta->setInt32(kKeyHeight, mHeight);
+ meta->setInt32(kKeyColorFormat, mColorFormat);
meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_RAW);
return meta;
@@ -100,6 +106,7 @@ protected:
private:
MediaBufferGroup mGroup;
int mWidth, mHeight;
+ int mColorFormat;
size_t mSize;
int64_t mNumFramesOutput;;
@@ -139,20 +146,47 @@ sp<MediaSource> createSource(const char *filename) {
return source;
}
+enum {
+ kYUV420SP = 0,
+ kYUV420P = 1,
+};
+
+// returns -1 if mapping of the given color is unsuccessful
+// returns an omx color enum value otherwise
+static int translateColorToOmxEnumValue(int color) {
+ switch (color) {
+ case kYUV420SP:
+ return OMX_COLOR_FormatYUV420SemiPlanar;
+ case kYUV420P:
+ return OMX_COLOR_FormatYUV420Planar;
+ default:
+ fprintf(stderr, "Unsupported color: %d\n", color);
+ return -1;
+ }
+}
+
int main(int argc, char **argv) {
android::ProcessState::self()->startThreadPool();
DataSource::RegisterDefaultSniffers();
#if 1
- if (argc != 2) {
- fprintf(stderr, "usage: %s filename\n", argv[0]);
+ if (argc != 3) {
+ fprintf(stderr, "usage: %s <filename> <input_color_format>\n", argv[0]);
+ fprintf(stderr, " <input_color_format>: 0 (YUV420SP) or 1 (YUV420P)\n");
return 1;
}
+ int colorFormat = translateColorToOmxEnumValue(atoi(argv[2]));
+ if (colorFormat == -1) {
+ fprintf(stderr, "input color format must be 0 (YUV420SP) or 1 (YUV420P)\n");
+ return 1;
+ }
OMXClient client;
CHECK_EQ(client.connect(), OK);
+ status_t err = OK;
+
#if 0
sp<MediaSource> source = createSource(argv[1]);
@@ -173,7 +207,7 @@ int main(int argc, char **argv) {
#else
int width = 720;
int height = 480;
- sp<MediaSource> decoder = new DummySource(width, height);
+ sp<MediaSource> decoder = new DummySource(width, height, colorFormat);
#endif
sp<MetaData> enc_meta = new MetaData;
@@ -187,7 +221,7 @@ int main(int argc, char **argv) {
enc_meta->setInt32(kKeyStride, width);
enc_meta->setInt32(kKeySliceHeight, height);
enc_meta->setInt32(kKeyIFramesInterval, kIFramesIntervalSec);
- enc_meta->setInt32(kKeyColorFormat, kColorFormat);
+ enc_meta->setInt32(kKeyColorFormat, colorFormat);
sp<MediaSource> encoder =
OMXCodec::Create(
@@ -197,14 +231,14 @@ int main(int argc, char **argv) {
sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4");
writer->addSource(encoder);
writer->setMaxFileDuration(kDurationUs);
- writer->start();
+ CHECK_EQ(OK, writer->start());
while (!writer->reachedEOS()) {
fprintf(stderr, ".");
usleep(100000);
}
- writer->stop();
+ err = writer->stop();
#else
- encoder->start();
+ CHECK_EQ(OK, encoder->start());
MediaBuffer *buffer;
while (encoder->read(&buffer) == OK) {
@@ -222,7 +256,7 @@ int main(int argc, char **argv) {
buffer = NULL;
}
- encoder->stop();
+ err = encoder->stop();
#endif
printf("$\n");
@@ -247,12 +281,16 @@ int main(int argc, char **argv) {
buffer = NULL;
}
- source->stop();
+ err = source->stop();
delete source;
source = NULL;
#endif
+ if (err != OK && err != ERROR_END_OF_STREAM) {
+ fprintf(stderr, "record failed: %d\n", err);
+ return 1;
+ }
return 0;
}
#else
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 6e6e86f78950..72bf825ea2c3 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1427,7 +1427,9 @@ public class Activity extends ContextThemeWrapper
* <li> The function will be called between {@link #onStop} and
* {@link #onDestroy}.
* <li> A new instance of the activity will <em>always</em> be immediately
- * created after this one's {@link #onDestroy()} is called.
+ * created after this one's {@link #onDestroy()} is called. In particular,
+ * <em>no</em> messages will be dispatched during this time (when the returned
+ * object does not have an activity to be associated with).
* <li> The object you return here will <em>always</em> be available from
* the {@link #getLastNonConfigurationInstance()} method of the following
* activity instance as described there.
@@ -1440,6 +1442,15 @@ public class Activity extends ContextThemeWrapper
* may change based on the configuration, including any data loaded from
* resources such as strings, layouts, or drawables.
*
+ * <p>The guarantee of no message handling during the switch to the next
+ * activity simplifies use with active objects. For example if your retained
+ * state is an {@link android.os.AsyncTask} you are guaranteed that its
+ * call back functions (like {@link android.os.AsyncTask#onPostExecute}) will
+ * not be called from the call here until you execute the next instance's
+ * {@link #onCreate(Bundle)}. (Note however that there is of course no such
+ * guarantee for {@link android.os.AsyncTask#doInBackground} since that is
+ * running in a separate thread.)
+ *
* @return Return any Object holding the desired state to propagate to the
* next activity instance.
*/
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index d8b525346362..3c7bebfa5d7b 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -363,7 +363,8 @@ public final class ActivityThread {
private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
private static final String ONE_COUNT_COLUMN = "%17s %8d";
private static final String TWO_COUNT_COLUMNS = "%17s %8d %17s %8d";
- private static final String DB_INFO_FORMAT = " %8d %8d %10d %s";
+ private static final String TWO_COUNT_COLUMNS_DB = "%20s %8d %20s %8d";
+ private static final String DB_INFO_FORMAT = " %8d %8d %14d %s";
// Formatting for checkin service - update version if row format changes
private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 1;
@@ -806,15 +807,15 @@ public final class ActivityThread {
// SQLite mem info
pw.println(" ");
pw.println(" SQL");
- printRow(pw, TWO_COUNT_COLUMNS, "heap:", sqliteAllocated, "memoryUsed:",
+ printRow(pw, TWO_COUNT_COLUMNS_DB, "heap:", sqliteAllocated, "MEMORY_USED:",
stats.memoryUsed / 1024);
- printRow(pw, TWO_COUNT_COLUMNS, "pageCacheOverflo:", stats.pageCacheOverflo / 1024,
- "largestMemAlloc:", stats.largestMemAlloc / 1024);
+ printRow(pw, TWO_COUNT_COLUMNS_DB, "PAGECACHE_OVERFLOW:",
+ stats.pageCacheOverflo / 1024, "MALLOC_SIZE:", stats.largestMemAlloc / 1024);
pw.println(" ");
int N = stats.dbStats.size();
if (N > 0) {
pw.println(" DATABASES");
- printRow(pw, " %8s %8s %10s %s", "Pagesize", "Dbsize", "Lookaside", "Dbname");
+ printRow(pw, " %8s %8s %14s %s", "pgsz", "dbsz", "Lookaside(b)", "Dbname");
for (int i = 0; i < N; i++) {
DbStats dbStats = stats.dbStats.get(i);
printRow(pw, DB_INFO_FORMAT, dbStats.pageSize, dbStats.dbSize,
diff --git a/core/java/android/app/backup/package.html b/core/java/android/app/backup/package.html
index ae29994ab5a9..e14034973ddd 100644
--- a/core/java/android/app/backup/package.html
+++ b/core/java/android/app/backup/package.html
@@ -3,6 +3,9 @@
<p>Contains the backup and restore functionality available to
applications. If a user wipes the data on their device or upgrades to a new Android-powered
device, all applications that have enabled backup will restore the user's previous data.</p>
+
+<p>For a detailed guide to using the backup APIs, see the <a
+href="{@docRoot}guide/topics/data/backup.html">Data Backup</a> developer guide.</p>
{@more}
<p>All backup and restore operations are controlled by the {@link
@@ -22,8 +25,5 @@ employing backup helpers such as {@link android.app.backup.SharedPreferencesBack
<li>Restore the data saved to remote storage</li>
</ul>
-<p>For a detailed guide to using the backup APIs, see the <a
-href="{@docRoot}guide/topics/data/backup.html">Data Backup</a> developer guide.</p>
-
</BODY>
</HTML>
diff --git a/core/java/android/database/sqlite/SQLiteDebug.java b/core/java/android/database/sqlite/SQLiteDebug.java
index 89c3f96a7783..b2a166b06fdf 100644
--- a/core/java/android/database/sqlite/SQLiteDebug.java
+++ b/core/java/android/database/sqlite/SQLiteDebug.java
@@ -134,7 +134,7 @@ public final class SQLiteDebug {
public DbStats(String dbName, long pageCount, long pageSize, int lookaside) {
this.dbName = dbName;
- this.pageSize = pageSize;
+ this.pageSize = pageSize / 1024;
dbSize = (pageCount * pageSize) / 1024;
this.lookaside = lookaside;
}
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 26600f35da5f..0d8228ce1e1a 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -1182,14 +1182,17 @@ public class Camera {
public static final String FOCUS_MODE_EDOF = "edof";
/**
- * Continuous auto focus mode. The camera continuously tries to focus.
- * This is ideal for shooting video or shooting photo of moving object.
- * Auto focus starts when the parameter is set. Applications should not
- * call {@link #autoFocus(AutoFocusCallback)} in this mode. To stop
- * continuous focus, applications should change the focus mode to other
- * modes.
- */
- public static final String FOCUS_MODE_CONTINUOUS = "continuous";
+ * Continuous auto focus mode intended for video recording. The camera
+ * continuously tries to focus. This is ideal for shooting video.
+ * Applications still can call {@link
+ * #takePicture(Camera.ShutterCallback, Camera.PictureCallback,
+ * Camera.PictureCallback)} in this mode but the subject may not be in
+ * focus. Auto focus starts when the parameter is set. Applications
+ * should not call {@link #autoFocus(AutoFocusCallback)} in this mode.
+ * To stop continuous focus, applications should change the focus mode
+ * to other modes.
+ */
+ public static final String FOCUS_MODE_CONTINUOUS_VIDEO = "continuous-video";
// Indices for focus distance array.
/**
@@ -2023,7 +2026,7 @@ public class Camera {
* @see #FOCUS_MODE_MACRO
* @see #FOCUS_MODE_FIXED
* @see #FOCUS_MODE_EDOF
- * @see #FOCUS_MODE_CONTINUOUS
+ * @see #FOCUS_MODE_CONTINUOUS_VIDEO
*/
public String getFocusMode() {
return get(KEY_FOCUS_MODE);
@@ -2225,8 +2228,8 @@ public class Camera {
* #autoFocus(AutoFocusCallback)}, {@link #cancelAutoFocus}, or {@link
* #startPreview()}. Applications can call {@link #getParameters()}
* and this method anytime to get the latest focus distances. If the
- * focus mode is FOCUS_MODE_CONTINUOUS, focus distances may change from
- * time to time.
+ * focus mode is FOCUS_MODE_CONTINUOUS_VIDEO, focus distances may change
+ * from time to time.
*
* This method is intended to estimate the distance between the camera
* and the subject. After autofocus, the subject distance may be within
diff --git a/core/java/android/net/DownloadManager.java b/core/java/android/net/DownloadManager.java
index 5320da3bc75c..0e671e930062 100644
--- a/core/java/android/net/DownloadManager.java
+++ b/core/java/android/net/DownloadManager.java
@@ -25,7 +25,6 @@ import android.os.ParcelFileDescriptor;
import android.provider.BaseColumns;
import android.provider.Downloads;
-import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -195,6 +194,12 @@ public class DownloadManager {
public final static int ERROR_CANNOT_RESUME = 1008;
/**
+ * Value of {@link #COLUMN_ERROR_CODE} when the requested destination file already exists (the
+ * download manager will not overwrite an existing file).
+ */
+ public final static int ERROR_FILE_ALREADY_EXISTS = 1009;
+
+ /**
* Broadcast intent action sent by the download manager when a download completes.
*/
public final static String ACTION_DOWNLOAD_COMPLETE = "android.intent.action.DOWNLOAD_COMPLETE";
@@ -235,10 +240,11 @@ public class DownloadManager {
Downloads.COLUMN_URI,
Downloads.COLUMN_MIME_TYPE,
Downloads.COLUMN_TOTAL_BYTES,
- Downloads._DATA,
Downloads.COLUMN_STATUS,
Downloads.COLUMN_CURRENT_BYTES,
Downloads.COLUMN_LAST_MODIFICATION,
+ Downloads.COLUMN_DESTINATION,
+ Downloads.Impl.COLUMN_FILE_NAME_HINT,
};
private static final Set<String> LONG_COLUMNS = new HashSet<String>(
@@ -359,7 +365,6 @@ public class DownloadManager {
*
* @param show whether the download manager should show a notification for this download.
* @return this object
- * @hide
*/
public Request setShowRunningNotification(boolean show) {
mShowNotification = show;
@@ -820,15 +825,10 @@ public class DownloadManager {
}
private String getLocalUri() {
- String localUri = getUnderlyingString(Downloads.Impl._DATA);
- if (localUri == null) {
- return null;
- }
-
long destinationType = getUnderlyingLong(Downloads.Impl.COLUMN_DESTINATION);
if (destinationType == Downloads.Impl.DESTINATION_FILE_URI) {
- // return file URI for external download
- return Uri.fromFile(new File(localUri)).toString();
+ // return client-provided file URI for external download
+ return getUnderlyingString(Downloads.Impl.COLUMN_FILE_NAME_HINT);
}
// return content URI for cache download
@@ -894,6 +894,9 @@ public class DownloadManager {
case Downloads.Impl.STATUS_CANNOT_RESUME:
return ERROR_CANNOT_RESUME;
+ case Downloads.Impl.STATUS_FILE_ALREADY_EXISTS_ERROR:
+ return ERROR_FILE_ALREADY_EXISTS;
+
default:
return ERROR_UNKNOWN;
}
diff --git a/core/java/android/net/LocalSocket.java b/core/java/android/net/LocalSocket.java
index 4039a690de57..3ee8a80e9968 100644
--- a/core/java/android/net/LocalSocket.java
+++ b/core/java/android/net/LocalSocket.java
@@ -70,8 +70,11 @@ public class LocalSocket {
if (!implCreated) {
synchronized (this) {
if (!implCreated) {
- implCreated = true;
- impl.create(true);
+ try {
+ impl.create(true);
+ } finally {
+ implCreated = true;
+ }
}
}
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 1e88c5647666..ba8014f2a3fa 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -397,7 +397,7 @@ public abstract class BatteryStats implements Parcelable {
}
}
- public final class HistoryItem implements Parcelable {
+ public final static class HistoryItem implements Parcelable {
public HistoryItem next;
public long time;
@@ -482,6 +482,18 @@ public abstract class BatteryStats implements Parcelable {
dest.writeInt(states);
}
+ public void setTo(HistoryItem o) {
+ time = o.time;
+ cmd = o.cmd;
+ batteryLevel = o.batteryLevel;
+ batteryStatus = o.batteryStatus;
+ batteryHealth = o.batteryHealth;
+ batteryPlugType = o.batteryPlugType;
+ batteryTemperature = o.batteryTemperature;
+ batteryVoltage = o.batteryVoltage;
+ states = o.states;
+ }
+
public void setTo(long time, byte cmd, HistoryItem o) {
this.time = time;
this.cmd = cmd;
@@ -526,6 +538,10 @@ public abstract class BatteryStats implements Parcelable {
}
}
+ public abstract boolean startIteratingHistoryLocked();
+
+ public abstract boolean getNextHistoryLocked(HistoryItem out);
+
/**
* Return the current history of battery state changes.
*/
@@ -1688,8 +1704,8 @@ public abstract class BatteryStats implements Parcelable {
*/
@SuppressWarnings("unused")
public void dumpLocked(PrintWriter pw) {
- HistoryItem rec = getHistory();
- if (rec != null) {
+ final HistoryItem rec = new HistoryItem();
+ if (startIteratingHistoryLocked()) {
pw.println("Battery History:");
long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
int oldState = 0;
@@ -1698,7 +1714,7 @@ public abstract class BatteryStats implements Parcelable {
int oldPlug = -1;
int oldTemp = -1;
int oldVolt = -1;
- while (rec != null) {
+ while (getNextHistoryLocked(rec)) {
pw.print(" ");
TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
pw.print(" ");
@@ -1803,7 +1819,6 @@ public abstract class BatteryStats implements Parcelable {
pw.println();
}
oldState = rec.states;
- rec = rec.next;
}
pw.println("");
}
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 5fea6fec453f..e56e25774d0f 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -307,8 +307,10 @@ public class RecoverySystem {
* Requires the {@link android.Manifest.permission#REBOOT} permission.
*
* @param context the Context to use
- * @param packageFile the update package to install. Currently
- * must be on the /cache or /data partitions.
+ * @param packageFile the update package to install. Must be on
+ * a partition mountable by recovery. (The set of partitions
+ * known to recovery may vary from device to device. Generally,
+ * /cache and /data are safe.)
*
* @throws IOException if writing the recovery command file
* fails, or if the reboot itself fails.
@@ -316,15 +318,6 @@ public class RecoverySystem {
public static void installPackage(Context context, File packageFile)
throws IOException {
String filename = packageFile.getCanonicalPath();
-
- if (filename.startsWith("/cache/")) {
- filename = "CACHE:" + filename.substring(7);
- } else if (filename.startsWith("/data/")) {
- filename = "DATA:" + filename.substring(6);
- } else {
- throw new IllegalArgumentException(
- "Must start with /cache or /data: " + filename);
- }
Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
String arg = "--update_package=" + filename;
bootCommand(context, arg);
diff --git a/core/java/android/provider/Downloads.java b/core/java/android/provider/Downloads.java
index 74c7372144bd..1e358c9d0281 100644
--- a/core/java/android/provider/Downloads.java
+++ b/core/java/android/provider/Downloads.java
@@ -895,6 +895,14 @@ public final class Downloads {
*/
public static final String COLUMN_IS_VISIBLE_IN_DOWNLOADS_UI = "is_visible_in_downloads_ui";
+ /**
+ * If true, the user has confirmed that this download can proceed over the mobile network
+ * even though it exceeds the recommended maximum size.
+ * <P>Type: BOOLEAN</P>
+ */
+ public static final String COLUMN_BYPASS_RECOMMENDED_SIZE_LIMIT =
+ "bypass_recommended_size_limit";
+
/*
* Lists the destinations that an application can specify for a download.
*/
@@ -1077,7 +1085,12 @@ public final class Downloads {
/**
* The lowest-valued error status that is not an actual HTTP status code.
*/
- public static final int MIN_ARTIFICIAL_ERROR_STATUS = 489;
+ public static final int MIN_ARTIFICIAL_ERROR_STATUS = 488;
+
+ /**
+ * The requested destination file already exists.
+ */
+ public static final int STATUS_FILE_ALREADY_EXISTS_ERROR = 488;
/**
* Some possibly transient error occurred, but we can't resume the download.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index fd601159981d..69151dff34d0 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -3428,6 +3428,15 @@ public final class Settings {
"download_manager_max_bytes_over_mobile";
/**
+ * The recommended maximum size, in bytes, of a download that the download manager should
+ * transfer over a non-wifi connection. Over this size, the use will be warned, but will
+ * have the option to start the download over the mobile connection anyway.
+ * @hide
+ */
+ public static final String DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE =
+ "download_manager_recommended_max_bytes_over_mobile";
+
+ /**
* ms during which to consume extra events related to Inet connection condition
* after a transtion to fully-connected
* @hide
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 456e0d9dd6e2..c9835a01003f 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1284,13 +1284,18 @@ public class WebView extends AbsoluteLayout
return mDatabase.getHttpAuthUsernamePassword(host, realm);
}
+ private void clearHelpers() {
+ clearTextEntry(false);
+ selectionDone();
+ }
+
/**
* Destroy the internal state of the WebView. This method should be called
* after the WebView has been removed from the view system. No other
* methods may be called on a WebView after destroy.
*/
public void destroy() {
- clearTextEntry(false);
+ clearHelpers();
if (mWebViewCore != null) {
// Set the handlers to null before destroying WebViewCore so no
// more messages will be posted.
@@ -1608,7 +1613,7 @@ public class WebView extends AbsoluteLayout
arg.mUrl = url;
arg.mExtraHeaders = extraHeaders;
mWebViewCore.sendMessage(EventHub.LOAD_URL, arg);
- clearTextEntry(false);
+ clearHelpers();
}
/**
@@ -1637,7 +1642,7 @@ public class WebView extends AbsoluteLayout
arg.mUrl = url;
arg.mPostData = postData;
mWebViewCore.sendMessage(EventHub.POST_URL, arg);
- clearTextEntry(false);
+ clearHelpers();
} else {
loadUrl(url);
}
@@ -1693,7 +1698,7 @@ public class WebView extends AbsoluteLayout
arg.mEncoding = encoding;
arg.mHistoryUrl = historyUrl;
mWebViewCore.sendMessage(EventHub.LOAD_DATA, arg);
- clearTextEntry(false);
+ clearHelpers();
}
/**
@@ -1710,7 +1715,7 @@ public class WebView extends AbsoluteLayout
* Reload the current url.
*/
public void reload() {
- clearTextEntry(false);
+ clearHelpers();
switchOutDrawHistory();
mWebViewCore.sendMessage(EventHub.RELOAD);
}
@@ -1790,7 +1795,7 @@ public class WebView extends AbsoluteLayout
private void goBackOrForward(int steps, boolean ignoreSnapshot) {
if (steps != 0) {
- clearTextEntry(false);
+ clearHelpers();
mWebViewCore.sendMessage(EventHub.GO_BACK_FORWARD, steps,
ignoreSnapshot ? 1 : 0);
}
@@ -4421,7 +4426,7 @@ public class WebView extends AbsoluteLayout
@Override
protected void onDetachedFromWindow() {
- clearTextEntry(false);
+ clearHelpers();
dismissZoomControl();
if (hasWindowFocus()) setActive(false);
super.onDetachedFromWindow();
diff --git a/core/java/android/widget/EdgeGlow.java b/core/java/android/widget/EdgeGlow.java
index 93222e1c00fc..e24f49543496 100644
--- a/core/java/android/widget/EdgeGlow.java
+++ b/core/java/android/widget/EdgeGlow.java
@@ -36,25 +36,26 @@ public class EdgeGlow {
private static final int PULL_TIME = 250;
// Time it will take for a pulled glow to decay to partial strength before release
- private static final int PULL_DECAY_TIME = 1000;
+ private static final int PULL_DECAY_TIME = 10000;
+ private static final float MAX_ALPHA = 1.f;
private static final float HELD_EDGE_ALPHA = 0.7f;
private static final float HELD_EDGE_SCALE_Y = 0.5f;
private static final float HELD_GLOW_ALPHA = 0.5f;
private static final float HELD_GLOW_SCALE_Y = 0.5f;
- private static final float MAX_GLOW_HEIGHT = 0.33f;
+ private static final float MAX_GLOW_HEIGHT = 3.f;
- private static final float PULL_GLOW_BEGIN = 0.5f;
+ private static final float PULL_GLOW_BEGIN = 1.f;
private static final float PULL_EDGE_BEGIN = 0.6f;
// Minimum velocity that will be absorbed
- private static final int MIN_VELOCITY = 750;
-
+ private static final int MIN_VELOCITY = 100;
+
private static final float EPSILON = 0.001f;
- private Drawable mEdge;
- private Drawable mGlow;
+ private final Drawable mEdge;
+ private final Drawable mGlow;
private int mWidth;
private int mHeight;
@@ -73,9 +74,9 @@ public class EdgeGlow {
private float mGlowScaleYFinish;
private long mStartTime;
- private int mDuration;
+ private float mDuration;
- private Interpolator mInterpolator;
+ private final Interpolator mInterpolator;
private static final int STATE_IDLE = 0;
private static final int STATE_PULL = 1;
@@ -83,6 +84,17 @@ public class EdgeGlow {
private static final int STATE_RECEDE = 3;
private static final int STATE_PULL_DECAY = 4;
+ // How much dragging should effect the height of the edge image.
+ // Number determined by user testing.
+ private static final int PULL_DISTANCE_EDGE_FACTOR = 5;
+
+ // How much dragging should effect the height of the glow image.
+ // Number determined by user testing.
+ private static final int PULL_DISTANCE_GLOW_FACTOR = 10;
+
+ private static final int VELOCITY_EDGE_FACTOR = 8;
+ private static final int VELOCITY_GLOW_FACTOR = 16;
+
private int mState = STATE_IDLE;
private float mPullDistance;
@@ -109,6 +121,7 @@ public class EdgeGlow {
/**
* Call when the object is pulled by the user.
+ *
* @param deltaDistance Change in distance since the last call
*/
public void onPull(float deltaDistance) {
@@ -127,11 +140,12 @@ public class EdgeGlow {
mPullDistance += deltaDistance;
float distance = Math.abs(mPullDistance);
- mEdgeAlpha = mEdgeAlphaStart = Math.max(PULL_EDGE_BEGIN, Math.min(distance, 1.f));
- mEdgeScaleY = mEdgeScaleYStart = Math.max(HELD_EDGE_SCALE_Y, Math.min(distance, 2.f));
+ mEdgeAlpha = mEdgeAlphaStart = Math.max(PULL_EDGE_BEGIN, Math.min(distance, MAX_ALPHA));
+ mEdgeScaleY = mEdgeScaleYStart = Math.max(
+ HELD_EDGE_SCALE_Y, Math.min(distance * PULL_DISTANCE_EDGE_FACTOR, 1.f));
- mGlowAlpha = mGlowAlphaStart = Math.max(0.5f,
- Math.min(mGlowAlpha + Math.abs(deltaDistance), 1.f));
+ mGlowAlpha = mGlowAlphaStart = Math.max(
+ 0.5f, Math.min(mGlowAlpha + Math.abs(deltaDistance), MAX_ALPHA));
float glowChange = Math.abs(deltaDistance);
if (deltaDistance > 0 && mPullDistance < 0) {
@@ -140,7 +154,8 @@ public class EdgeGlow {
if (mPullDistance == 0) {
mGlowScaleY = 0;
}
- mGlowScaleY = mGlowScaleYStart = Math.max(0, mGlowScaleY + glowChange * 2);
+ mGlowScaleY = mGlowScaleYStart = Math.max(
+ 0, mGlowScaleY + glowChange * PULL_DISTANCE_GLOW_FACTOR);
mEdgeAlphaFinish = mEdgeAlpha;
mEdgeScaleYFinish = mEdgeScaleY;
@@ -165,9 +180,9 @@ public class EdgeGlow {
mGlowScaleYStart = mGlowScaleY;
mEdgeAlphaFinish = 0.f;
- mEdgeScaleYFinish = 0.1f;
+ mEdgeScaleYFinish = 0.f;
mGlowAlphaFinish = 0.f;
- mGlowScaleYFinish = 0.1f;
+ mGlowScaleYFinish = 0.f;
mStartTime = AnimationUtils.currentAnimationTimeMillis();
mDuration = RECEDE_TIME;
@@ -175,6 +190,7 @@ public class EdgeGlow {
/**
* Call when the effect absorbs an impact at the given velocity.
+ *
* @param velocity Velocity at impact in pixels per second.
*/
public void onAbsorb(int velocity) {
@@ -182,27 +198,43 @@ public class EdgeGlow {
velocity = Math.max(MIN_VELOCITY, Math.abs(velocity));
mStartTime = AnimationUtils.currentAnimationTimeMillis();
- mDuration = (int) (velocity * 0.03f);
+ mDuration = 0.1f + (velocity * 0.03f);
+ // The edge should always be at least partially visible, regardless
+ // of velocity.
mEdgeAlphaStart = 0.5f;
mEdgeScaleYStart = 0.2f;
+ // The glow depends more on the velocity, and therefore starts out
+ // nearly invisible.
mGlowAlphaStart = 0.5f;
mGlowScaleYStart = 0.f;
- mEdgeAlphaFinish = Math.max(0, Math.min(velocity * 0.01f, 1));
+ // Factor the velocity by 8. Testing on device shows this works best to
+ // reflect the strength of the user's scrolling.
+ mEdgeAlphaFinish = Math.max(0, Math.min(velocity * VELOCITY_EDGE_FACTOR, 1));
+ // Edge should never get larger than the size of its asset.
mEdgeScaleYFinish = 1.f;
- mGlowAlphaFinish = 1.f;
- mGlowScaleYFinish = Math.min(velocity * 0.001f, 1);
+
+ // Growth for the size of the glow should be quadratic to properly
+ // respond
+ // to a user's scrolling speed. The faster the scrolling speed, the more
+ // intense the effect should be for both the size and the saturation.
+ mGlowScaleYFinish = Math.min(0.025f + (velocity * (velocity / 100) * 0.00015f), 1.75f);
+ // Alpha should change for the glow as well as size.
+ mGlowAlphaFinish = Math.max(
+ mGlowAlphaStart, Math.min(velocity * VELOCITY_GLOW_FACTOR * .00001f, MAX_ALPHA));
}
+
/**
- * Draw into the provided canvas.
- * Assumes that the canvas has been rotated accordingly and the size has been set.
- * The effect will be drawn the full width of X=0 to X=width, emitting from Y=0 and extending
- * to some factor < 1.f of height.
+ * Draw into the provided canvas. Assumes that the canvas has been rotated
+ * accordingly and the size has been set. The effect will be drawn the full
+ * width of X=0 to X=width, emitting from Y=0 and extending to some factor <
+ * 1.f of height.
*
* @param canvas Canvas to draw into
- * @return true if drawing should continue beyond this frame to continue the animation
+ * @return true if drawing should continue beyond this frame to continue the
+ * animation
*/
public boolean draw(Canvas canvas) {
update();
@@ -213,15 +245,14 @@ public class EdgeGlow {
final float distScale = (float) mHeight / mWidth;
mGlow.setAlpha((int) (Math.max(0, Math.min(mGlowAlpha, 1)) * 255));
- mGlow.setBounds(0, 0, mWidth, (int) Math.min(glowHeight * mGlowScaleY * distScale * 0.6f,
- mHeight * MAX_GLOW_HEIGHT));
+ // Width of the image should be 3 * the width of the screen.
+ // Should start off screen to the left.
+ mGlow.setBounds(-mWidth, 0, mWidth * 2, (int) Math.min(
+ glowHeight * mGlowScaleY * distScale * 0.6f, mHeight * MAX_GLOW_HEIGHT));
mGlow.draw(canvas);
mEdge.setAlpha((int) (Math.max(0, Math.min(mEdgeAlpha, 1)) * 255));
- mEdge.setBounds(0,
- 0,
- mWidth,
- (int) (edgeHeight * mEdgeScaleY));
+ mEdge.setBounds(0, 0, mWidth, (int) (edgeHeight * mEdgeScaleY));
mEdge.draw(canvas);
return mState != STATE_IDLE;
@@ -229,7 +260,7 @@ public class EdgeGlow {
private void update() {
final long time = AnimationUtils.currentAnimationTimeMillis();
- final float t = Math.min((float) (time - mStartTime) / mDuration, 1.f);
+ final float t = Math.min((time - mStartTime) / mDuration, 1.f);
final float interp = mInterpolator.getInterpolation(t);
@@ -251,7 +282,7 @@ public class EdgeGlow {
mGlowScaleYStart = mGlowScaleY;
mEdgeAlphaFinish = 0.f;
- mEdgeScaleYFinish = 0.1f;
+ mEdgeScaleYFinish = mEdgeScaleY;
mGlowAlphaFinish = 0.f;
mGlowScaleYFinish = mGlowScaleY;
break;
@@ -265,10 +296,11 @@ public class EdgeGlow {
mGlowAlphaStart = mGlowAlpha;
mGlowScaleYStart = mGlowScaleY;
- mEdgeAlphaFinish = Math.min(mEdgeAlphaStart, HELD_EDGE_ALPHA);
- mEdgeScaleYFinish = Math.min(mEdgeScaleYStart, HELD_EDGE_SCALE_Y);
- mGlowAlphaFinish = Math.min(mGlowAlphaStart, HELD_GLOW_ALPHA);
- mGlowScaleYFinish = Math.min(mGlowScaleY, HELD_GLOW_SCALE_Y);
+ // After a pull, the glow should fade to nothing.
+ mEdgeAlphaFinish = 0.f;
+ mEdgeScaleYFinish = 0.f;
+ mGlowAlphaFinish = 0.f;
+ mGlowScaleYFinish = 0.f;
break;
case STATE_PULL_DECAY:
// Do nothing; wait for release
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index c2d003e96293..6e5c47fa1044 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -51,6 +51,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.ReentrantLock;
/**
* All information we are collecting about things that can happen that impact
@@ -3834,6 +3835,22 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ private HistoryItem mHistoryIterator;
+
+ public boolean startIteratingHistoryLocked() {
+ return (mHistoryIterator = mHistory) != null;
+ }
+
+ public boolean getNextHistoryLocked(HistoryItem out) {
+ HistoryItem cur = mHistoryIterator;
+ if (cur == null) {
+ return false;
+ }
+ out.setTo(cur);
+ mHistoryIterator = cur.next;
+ return true;
+ }
+
@Override
public HistoryItem getHistory() {
return mHistory;
@@ -3960,7 +3977,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
if (mFile != null) {
- writeLocked();
+ writeAsyncLocked();
}
}
}
@@ -4356,11 +4373,22 @@ public final class BatteryStatsImpl extends BatteryStats {
}
public void shutdownLocked() {
- writeLocked();
+ writeSyncLocked();
mShuttingDown = true;
}
- public void writeLocked() {
+ Parcel mPendingWrite = null;
+ final ReentrantLock mWriteLock = new ReentrantLock();
+
+ public void writeAsyncLocked() {
+ writeLocked(false);
+ }
+
+ public void writeSyncLocked() {
+ writeLocked(true);
+ }
+
+ void writeLocked(boolean sync) {
if (mFile == null) {
Slog.w("BatteryStats", "writeLocked: no file associated with this instance");
return;
@@ -4370,23 +4398,51 @@ public final class BatteryStatsImpl extends BatteryStats {
return;
}
+ Parcel out = Parcel.obtain();
+ writeSummaryToParcel(out);
+ mLastWriteTime = SystemClock.elapsedRealtime();
+
+ if (mPendingWrite != null) {
+ mPendingWrite.recycle();
+ }
+ mPendingWrite = out;
+
+ if (sync) {
+ commitPendingDataToDisk();
+ } else {
+ Thread thr = new Thread("BatteryStats-Write") {
+ @Override
+ public void run() {
+ Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+ commitPendingDataToDisk();
+ }
+ };
+ thr.start();
+ }
+ }
+
+ public void commitPendingDataToDisk() {
+ Parcel next;
+ synchronized (this) {
+ next = mPendingWrite;
+ mPendingWrite = null;
+
+ mWriteLock.lock();
+ }
+
try {
FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
- Parcel out = Parcel.obtain();
- writeSummaryToParcel(out);
- stream.write(out.marshall());
- out.recycle();
-
+ stream.write(next.marshall());
stream.flush();
stream.close();
mFile.commit();
-
- mLastWriteTime = SystemClock.elapsedRealtime();
- return;
} catch (IOException e) {
Slog.w("BatteryStats", "Error writing battery statistics", e);
+ mFile.rollback();
+ } finally {
+ next.recycle();
+ mWriteLock.unlock();
}
- mFile.rollback();
}
static byte[] readFully(FileInputStream stream) throws java.io.IOException {
diff --git a/core/res/res/drawable-hdpi/btn_circle_disable.png b/core/res/res/drawable-hdpi/btn_circle_disable.png
index 3f859cb57a64..39652a855800 100755..100644
--- a/core/res/res/drawable-hdpi/btn_circle_disable.png
+++ b/core/res/res/drawable-hdpi/btn_circle_disable.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_circle_disable_focused.png b/core/res/res/drawable-hdpi/btn_circle_disable_focused.png
index 66251b87bb74..1aa7ffe69b11 100755..100644
--- a/core/res/res/drawable-hdpi/btn_circle_disable_focused.png
+++ b/core/res/res/drawable-hdpi/btn_circle_disable_focused.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/expander_ic_maximized.9.png b/core/res/res/drawable-hdpi/expander_ic_maximized.9.png
index 0c19bb782a60..2ec27afa7725 100755..100644
--- a/core/res/res/drawable-hdpi/expander_ic_maximized.9.png
+++ b/core/res/res/drawable-hdpi/expander_ic_maximized.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/expander_ic_minimized.9.png b/core/res/res/drawable-hdpi/expander_ic_minimized.9.png
index 2ec27afa7725..0c19bb782a60 100755..100644
--- a/core/res/res/drawable-hdpi/expander_ic_minimized.9.png
+++ b/core/res/res/drawable-hdpi/expander_ic_minimized.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_left_confirm_gray.png b/core/res/res/drawable-hdpi/jog_tab_left_confirm_gray.png
index 34992082225d..f8dc42ae1a24 100644
--- a/core/res/res/drawable-hdpi/jog_tab_left_confirm_gray.png
+++ b/core/res/res/drawable-hdpi/jog_tab_left_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_left_confirm_green.png b/core/res/res/drawable-hdpi/jog_tab_left_confirm_green.png
index 91eaec88c243..92b24b0d9fdf 100644
--- a/core/res/res/drawable-hdpi/jog_tab_left_confirm_green.png
+++ b/core/res/res/drawable-hdpi/jog_tab_left_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_left_confirm_yellow.png b/core/res/res/drawable-hdpi/jog_tab_left_confirm_yellow.png
index e5bc5f69a9b0..8208b20d6697 100644
--- a/core/res/res/drawable-hdpi/jog_tab_left_confirm_yellow.png
+++ b/core/res/res/drawable-hdpi/jog_tab_left_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_left_normal.png b/core/res/res/drawable-hdpi/jog_tab_left_normal.png
index 5326c7c4f0c7..4c877434b915 100644
--- a/core/res/res/drawable-hdpi/jog_tab_left_normal.png
+++ b/core/res/res/drawable-hdpi/jog_tab_left_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_left_pressed.png b/core/res/res/drawable-hdpi/jog_tab_left_pressed.png
index 7b906dfe147b..150c73507e3f 100644
--- a/core/res/res/drawable-hdpi/jog_tab_left_pressed.png
+++ b/core/res/res/drawable-hdpi/jog_tab_left_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_right_confirm_gray.png b/core/res/res/drawable-hdpi/jog_tab_right_confirm_gray.png
index ea8c3157f173..11ab30c10f4f 100644
--- a/core/res/res/drawable-hdpi/jog_tab_right_confirm_gray.png
+++ b/core/res/res/drawable-hdpi/jog_tab_right_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_right_confirm_green.png b/core/res/res/drawable-hdpi/jog_tab_right_confirm_green.png
index aa0ceb943dbd..a9122855b24d 100644
--- a/core/res/res/drawable-hdpi/jog_tab_right_confirm_green.png
+++ b/core/res/res/drawable-hdpi/jog_tab_right_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_right_confirm_yellow.png b/core/res/res/drawable-hdpi/jog_tab_right_confirm_yellow.png
index 3cfeb67e6e63..0dd84fa487b2 100644
--- a/core/res/res/drawable-hdpi/jog_tab_right_confirm_yellow.png
+++ b/core/res/res/drawable-hdpi/jog_tab_right_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_right_normal.png b/core/res/res/drawable-hdpi/jog_tab_right_normal.png
index da7726b262cf..e0f1a0a04876 100644
--- a/core/res/res/drawable-hdpi/jog_tab_right_normal.png
+++ b/core/res/res/drawable-hdpi/jog_tab_right_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/jog_tab_right_pressed.png b/core/res/res/drawable-hdpi/jog_tab_right_pressed.png
index 450a325b27aa..f41d6f59c5fc 100644
--- a/core/res/res/drawable-hdpi/jog_tab_right_pressed.png
+++ b/core/res/res/drawable-hdpi/jog_tab_right_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/overscroll_edge.png b/core/res/res/drawable-hdpi/overscroll_edge.png
index f8e40ecfd7cd..5969093efc25 100644
--- a/core/res/res/drawable-hdpi/overscroll_edge.png
+++ b/core/res/res/drawable-hdpi/overscroll_edge.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/popup_center_dark.9.png b/core/res/res/drawable-hdpi/popup_center_dark.9.png
index e2e983f3f0a2..ac1f92dfff88 100755..100644
--- a/core/res/res/drawable-hdpi/popup_center_dark.9.png
+++ b/core/res/res/drawable-hdpi/popup_center_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_chat.png b/core/res/res/drawable-hdpi/stat_notify_chat.png
index 097a979a5c7b..71ea8de6b682 100755..100644
--- a/core/res/res/drawable-hdpi/stat_notify_chat.png
+++ b/core/res/res/drawable-hdpi/stat_notify_chat.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/expander_ic_maximized.9.png b/core/res/res/drawable-mdpi/expander_ic_maximized.9.png
index 465cabd7e929..d5c32766cece 100644
--- a/core/res/res/drawable-mdpi/expander_ic_maximized.9.png
+++ b/core/res/res/drawable-mdpi/expander_ic_maximized.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/expander_ic_minimized.9.png b/core/res/res/drawable-mdpi/expander_ic_minimized.9.png
index 9967ecbd6c1e..4515b42177bb 100644
--- a/core/res/res/drawable-mdpi/expander_ic_minimized.9.png
+++ b/core/res/res/drawable-mdpi/expander_ic_minimized.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_left_confirm_gray.png b/core/res/res/drawable-mdpi/jog_tab_left_confirm_gray.png
index e8544ff9515a..b5d3290b4a9b 100644
--- a/core/res/res/drawable-mdpi/jog_tab_left_confirm_gray.png
+++ b/core/res/res/drawable-mdpi/jog_tab_left_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_left_confirm_green.png b/core/res/res/drawable-mdpi/jog_tab_left_confirm_green.png
index d0ba8f8fbed5..e4cff64100f5 100644
--- a/core/res/res/drawable-mdpi/jog_tab_left_confirm_green.png
+++ b/core/res/res/drawable-mdpi/jog_tab_left_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_left_confirm_yellow.png b/core/res/res/drawable-mdpi/jog_tab_left_confirm_yellow.png
index 861e17a7f173..d50181447e01 100644
--- a/core/res/res/drawable-mdpi/jog_tab_left_confirm_yellow.png
+++ b/core/res/res/drawable-mdpi/jog_tab_left_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_left_normal.png b/core/res/res/drawable-mdpi/jog_tab_left_normal.png
index 7af1b855006b..42f7e39d2d54 100644
--- a/core/res/res/drawable-mdpi/jog_tab_left_normal.png
+++ b/core/res/res/drawable-mdpi/jog_tab_left_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_left_pressed.png b/core/res/res/drawable-mdpi/jog_tab_left_pressed.png
index b76e83e9573e..888f19b5e7fc 100644
--- a/core/res/res/drawable-mdpi/jog_tab_left_pressed.png
+++ b/core/res/res/drawable-mdpi/jog_tab_left_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_right_confirm_gray.png b/core/res/res/drawable-mdpi/jog_tab_right_confirm_gray.png
index 814a50d25756..7fc930ebf931 100644
--- a/core/res/res/drawable-mdpi/jog_tab_right_confirm_gray.png
+++ b/core/res/res/drawable-mdpi/jog_tab_right_confirm_gray.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_right_confirm_green.png b/core/res/res/drawable-mdpi/jog_tab_right_confirm_green.png
index cf157fc837ed..1a08be8a81e2 100644
--- a/core/res/res/drawable-mdpi/jog_tab_right_confirm_green.png
+++ b/core/res/res/drawable-mdpi/jog_tab_right_confirm_green.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_right_confirm_yellow.png b/core/res/res/drawable-mdpi/jog_tab_right_confirm_yellow.png
index 66557319d14f..2aa40363aec7 100644
--- a/core/res/res/drawable-mdpi/jog_tab_right_confirm_yellow.png
+++ b/core/res/res/drawable-mdpi/jog_tab_right_confirm_yellow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_right_normal.png b/core/res/res/drawable-mdpi/jog_tab_right_normal.png
index 479c9a5f2f52..10710fbb01c6 100644
--- a/core/res/res/drawable-mdpi/jog_tab_right_normal.png
+++ b/core/res/res/drawable-mdpi/jog_tab_right_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/jog_tab_right_pressed.png b/core/res/res/drawable-mdpi/jog_tab_right_pressed.png
index 454aaf2216de..021e96ba2c42 100644
--- a/core/res/res/drawable-mdpi/jog_tab_right_pressed.png
+++ b/core/res/res/drawable-mdpi/jog_tab_right_pressed.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/overscroll_edge.png b/core/res/res/drawable-mdpi/overscroll_edge.png
new file mode 100644
index 000000000000..22f4ef88a464
--- /dev/null
+++ b/core/res/res/drawable-mdpi/overscroll_edge.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/overscroll_glow.png b/core/res/res/drawable-mdpi/overscroll_glow.png
new file mode 100644
index 000000000000..761fb74c3692
--- /dev/null
+++ b/core/res/res/drawable-mdpi/overscroll_glow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_middle.png b/core/res/res/drawable-mdpi/text_select_handle_middle.png
new file mode 100644
index 000000000000..201e7f9f5fab
--- /dev/null
+++ b/core/res/res/drawable-mdpi/text_select_handle_middle.png
Binary files differ
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index f09421bca74f..487a00daa66c 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -35,6 +35,7 @@
android:label="@string/permlab_testDenied"
android:description="@string/permdesc_testDenied" />
+ <uses-permission android:name="android.permission.ACCESS_CACHE_FILESYSTEM" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
diff --git a/core/tests/coretests/src/android/net/DownloadManagerBaseTest.java b/core/tests/coretests/src/android/net/DownloadManagerBaseTest.java
index ee0f5f14516d..a7ec7d5fd523 100644
--- a/core/tests/coretests/src/android/net/DownloadManagerBaseTest.java
+++ b/core/tests/coretests/src/android/net/DownloadManagerBaseTest.java
@@ -27,6 +27,7 @@ import android.net.NetworkInfo;
import android.net.DownloadManager.Query;
import android.net.DownloadManager.Request;
import android.net.wifi.WifiManager;
+import android.os.Bundle;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.os.SystemClock;
@@ -43,9 +44,12 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.TimeoutException;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
+import java.util.Set;
import java.util.Vector;
import junit.framework.AssertionFailedError;
@@ -67,6 +71,7 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase {
protected static final String LOG_TAG = "android.net.DownloadManagerBaseTest";
protected static final int HTTP_OK = 200;
+ protected static final int HTTP_REDIRECT = 307;
protected static final int HTTP_PARTIAL_CONTENT = 206;
protected static final int HTTP_NOT_FOUND = 404;
protected static final int HTTP_SERVICE_UNAVAILABLE = 503;
@@ -119,6 +124,7 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase {
public static class MultipleDownloadsCompletedReceiver extends BroadcastReceiver {
private volatile int mNumDownloadsCompleted = 0;
+ private Set<Long> downloadIds = Collections.synchronizedSet(new HashSet<Long>());
/**
* {@inheritDoc}
@@ -129,6 +135,8 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase {
++mNumDownloadsCompleted;
Log.i(LOG_TAG, "MultipleDownloadsCompletedReceiver got intent: " +
intent.getAction() + " --> total count: " + mNumDownloadsCompleted);
+ Bundle extras = intent.getExtras();
+ downloadIds.add(new Long(extras.getLong(DownloadManager.EXTRA_DOWNLOAD_ID)));
}
}
@@ -142,6 +150,18 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase {
public int numDownloadsCompleted() {
return mNumDownloadsCompleted;
}
+
+ /**
+ * Gets the list of download IDs.
+ * @return A Set<Long> with the ids of the completed downloads.
+ */
+ public Set<Long> getDownloadIds() {
+ synchronized(downloadIds) {
+ Set<Long> returnIds = new HashSet<Long>(downloadIds);
+ return returnIds;
+ }
+ }
+
}
public static class WiFiChangedReceiver extends BroadcastReceiver {
@@ -196,6 +216,17 @@ public class DownloadManagerBaseTest extends InstrumentationTestCase {
}
/**
+ * Helper to enqueue a response from the MockWebServer with no body.
+ *
+ * @param status The HTTP status code to return for this response
+ * @return Returns the mock web server response that was queued (which can be modified)
+ */
+ protected MockResponse enqueueResponse(int status) {
+ return doEnqueueResponse(status);
+
+ }
+
+ /**
* Helper to enqueue a response from the MockWebServer.
*
* @param status The HTTP status code to return for this response
diff --git a/core/tests/coretests/src/android/net/DownloadManagerIntegrationTest.java b/core/tests/coretests/src/android/net/DownloadManagerIntegrationTest.java
index be3cbf729458..a61f02d637df 100644
--- a/core/tests/coretests/src/android/net/DownloadManagerIntegrationTest.java
+++ b/core/tests/coretests/src/android/net/DownloadManagerIntegrationTest.java
@@ -21,6 +21,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
+import android.net.DownloadManager;
import android.net.DownloadManager.Query;
import android.net.DownloadManager.Request;
import android.net.DownloadManagerBaseTest.DataType;
@@ -28,6 +29,7 @@ import android.net.DownloadManagerBaseTest.MultipleDownloadsCompletedReceiver;
import android.net.wifi.WifiManager;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
+import android.os.StatFs;
import android.os.SystemClock;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.LargeTest;
@@ -36,10 +38,13 @@ import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
+import java.util.Iterator;
import java.util.Random;
+import java.util.Set;
import junit.framework.AssertionFailedError;
@@ -51,8 +56,11 @@ import coretestutils.http.MockWebServer;
*/
public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest {
- private static String LOG_TAG = "android.net.DownloadManagerIntegrationTest";
- private static String PROHIBITED_DIRECTORY = "/system";
+ private final static String LOG_TAG = "android.net.DownloadManagerIntegrationTest";
+ private final static String PROHIBITED_DIRECTORY =
+ Environment.getRootDirectory().getAbsolutePath();
+ private final static String CACHE_DIR =
+ Environment.getDownloadCacheDirectory().getAbsolutePath();
protected MultipleDownloadsCompletedReceiver mReceiver = null;
/**
@@ -74,25 +82,48 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest {
public void tearDown() throws Exception {
super.tearDown();
setWiFiStateOn(true);
+ removeAllCurrentDownloads();
if (mReceiver != null) {
mContext.unregisterReceiver(mReceiver);
mReceiver = null;
- removeAllCurrentDownloads();
}
}
/**
* Helper that does the actual basic download verification.
*/
- protected void doBasicDownload(byte[] blobData) throws Exception {
+ protected long doBasicDownload(byte[] blobData) throws Exception {
long dlRequest = doStandardEnqueue(blobData);
// wait for the download to complete
waitForDownloadOrTimeout(dlRequest);
- verifyAndCleanupSingleFileDownload(dlRequest, blobData);
assertEquals(1, mReceiver.numDownloadsCompleted());
+ return dlRequest;
+ }
+
+ /**
+ * Verifies a particular error code was received from a download
+ *
+ * @param uri The uri to enqueue to the DownloadManager
+ * @param error The error code expected
+ * @throws an Exception if the test fails
+ */
+ @LargeTest
+ public void doErrorTest(Uri uri, int error) throws Exception {
+ Request request = new Request(uri);
+ request.setTitle(DEFAULT_FILENAME);
+
+ long dlRequest = mDownloadManager.enqueue(request);
+ waitForDownloadOrTimeout(dlRequest);
+
+ Cursor cursor = getCursor(dlRequest);
+ try {
+ verifyInt(cursor, DownloadManager.COLUMN_ERROR_CODE, error);
+ } finally {
+ cursor.close();
+ }
}
/**
@@ -103,7 +134,8 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest {
int fileSize = 500 * 1024; // 500k
byte[] blobData = generateData(fileSize, DataType.BINARY);
- doBasicDownload(blobData);
+ long dlRequest = doBasicDownload(blobData);
+ verifyAndCleanupSingleFileDownload(dlRequest, blobData);
}
/**
@@ -114,7 +146,8 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest {
int fileSize = 300000;
byte[] blobData = generateData(fileSize, DataType.TEXT);
- doBasicDownload(blobData);
+ long dlRequest = doBasicDownload(blobData);
+ verifyAndCleanupSingleFileDownload(dlRequest, blobData);
}
/**
@@ -348,34 +381,209 @@ public class DownloadManagerIntegrationTest extends DownloadManagerBaseTest {
}
/**
- * Tests trying to download two large files (50M bytes, followed by 60M bytes)
+ * Tests downloading a file to cache when there isn't enough space in the cache to hold the
+ * entire file.
*/
@LargeTest
- public void testInsufficientSpaceSingleFiles() throws Exception {
- long fileSize1 = 50000000L;
- long fileSize2 = 60000000L;
- File largeFile1 = createFileOnSD(null, fileSize1, DataType.TEXT, null);
- File largeFile2 = createFileOnSD(null, fileSize2, DataType.TEXT, null);
+ public void testDownloadToCache_whenFull() throws Exception {
+ int DOWNLOAD_FILE_SIZE = 500000;
+
+ StatFs fs = new StatFs(CACHE_DIR);
+ Log.i(LOG_TAG, "getAvailableBlocks: " + fs.getAvailableBlocks());
+ Log.i(LOG_TAG, "getBlockSize: " + fs.getBlockSize());
+
+ int blockSize = fs.getBlockSize();
+ int availableBlocks = fs.getAvailableBlocks();
+ int availableBytes = blockSize * availableBlocks;
+ File outFile = null;
try {
- long dlRequest = doStandardEnqueue(largeFile1);
- waitForDownloadOrTimeout(dlRequest);
- ParcelFileDescriptor pfd = mDownloadManager.openDownloadedFile(dlRequest);
- verifyFileContents(pfd, largeFile1);
- verifyFileSize(pfd, largeFile1.length());
+ // fill cache to ensure we don't have enough space - take half the size of the
+ // download size, and leave that much freespace left on the cache partition
+ if (DOWNLOAD_FILE_SIZE <= availableBytes) {
+ int writeSizeBytes = availableBytes - (DOWNLOAD_FILE_SIZE / 2);
+
+ int writeSizeBlocks = writeSizeBytes / blockSize;
+ int remainderSizeBlocks = availableBlocks - writeSizeBlocks;
+
+ FileOutputStream fo = null;
+ try {
+ outFile = File.createTempFile("DM_TEST", null, new File(CACHE_DIR));
+ Log.v(LOG_TAG, "writing " + writeSizeBlocks + " blocks to file "
+ + outFile.getAbsolutePath());
+
+ fo = new FileOutputStream(outFile);
+
+ byte[] buffer = new byte[blockSize];
+ while (fs.getAvailableBlocks() >= remainderSizeBlocks) {
+ fo.write(buffer);
+ fs.restat(CACHE_DIR);
+ }
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "error filling file: ", e);
+ throw e;
+ } finally {
+ if (fo != null) {
+ fo.close();
+ }
+ }
+ }
- dlRequest = doStandardEnqueue(largeFile2);
- waitForDownloadOrTimeout(dlRequest);
- Cursor cursor = getCursor(dlRequest);
- try {
- verifyInt(cursor, DownloadManager.COLUMN_ERROR_CODE,
- DownloadManager.ERROR_INSUFFICIENT_SPACE);
- } finally {
- cursor.close();
+ assertTrue(DOWNLOAD_FILE_SIZE > (fs.getAvailableBlocks() * blockSize));
+ byte[] blobData = generateData(DOWNLOAD_FILE_SIZE, DataType.TEXT);
+ long dlRequest = doBasicDownload(blobData);
+ verifyAndCleanupSingleFileDownload(dlRequest, blobData);
+
+ } finally {
+ if (outFile != null) {
+ outFile.delete();
}
+ }
+ }
+
+ /**
+ * Tests that files are not deleted when DOWNLOAD_CACHE_NON_PURGEABLE is set, even if we've
+ * run out of space.
+ */
+ @LargeTest
+ public void testDownloadCacheNonPurgeable() throws Exception {
+ int fileSize = 10000000;
+ byte[] blobData = generateData(fileSize, DataType.BINARY);
+ long dlRequest = -1;
+
+ // Fill up the cache partition until there's not enough room for another download.
+ // Note that we need to initiate a download first, then check for the available space. This
+ // is b/c there could be some files that are still left in the cache that can (and will be)
+ // cleared out, but not until DM gets a request for a download and reclaims that
+ // space first.
+ boolean spaceAvailable = true;
+ while (spaceAvailable) {
+ dlRequest = doStandardEnqueue(blobData);
+ waitForDownloadOrTimeout(dlRequest);
+
+ // Check if we've filled up the cache yet
+ StatFs fs = new StatFs(CACHE_DIR);
+ Log.i(LOG_TAG, "getAvailableBlocks: " + fs.getAvailableBlocks());
+ Log.i(LOG_TAG, "getBlockSize: " + fs.getBlockSize());
+ int availableBytes = fs.getBlockSize() * fs.getAvailableBlocks();
+ spaceAvailable = (availableBytes > fileSize) ? true : false;
+ }
+
+ // Now add one more download (should not fit in the space left over)
+ dlRequest = doStandardEnqueue(blobData);
+ waitForDownloadOrTimeout(dlRequest);
+
+ // For the last download we should have failed b/c there is not enough space left in cache
+ Cursor cursor = getCursor(dlRequest);
+ try {
+ verifyInt(cursor, DownloadManager.COLUMN_ERROR_CODE,
+ DownloadManager.ERROR_INSUFFICIENT_SPACE);
+ } finally {
+ cursor.close();
+ }
+ }
+
+ /**
+ * Tests that we get the correct download ID from the download notification.
+ */
+ @LargeTest
+ public void testGetDownloadIdOnNotification() throws Exception {
+ byte[] blobData = generateData(3000, DataType.TEXT); // file size = 3000 bytes
+
+ MockResponse response = enqueueResponse(HTTP_OK, blobData);
+ long dlRequest = doCommonStandardEnqueue();
+ waitForDownloadOrTimeout(dlRequest);
+
+ Set<Long> ids = mReceiver.getDownloadIds();
+ assertEquals(1, ids.size());
+ Iterator<Long> it = ids.iterator();
+ assertEquals("Download ID received from notification does not match initial id!",
+ dlRequest, it.next().longValue());
+ }
+
+ /**
+ * Tests the download failure error after too many redirects (>5).
+ */
+ @LargeTest
+ public void testErrorTooManyRedirects() throws Exception {
+ Uri uri = getServerUri(DEFAULT_FILENAME);
+
+ // force 6 redirects
+ for (int i = 0; i < 6; ++i) {
+ MockResponse response = enqueueResponse(HTTP_REDIRECT);
+ response.addHeader("Location", uri.toString());
+ }
+ doErrorTest(uri, DownloadManager.ERROR_TOO_MANY_REDIRECTS);
+ }
+
+ /**
+ * Tests the download failure error from an unhandled HTTP status code
+ */
+ @LargeTest
+ public void testErrorUnhandledHttpCode() throws Exception {
+ Uri uri = getServerUri(DEFAULT_FILENAME);
+ MockResponse response = enqueueResponse(HTTP_PARTIAL_CONTENT);
+
+ doErrorTest(uri, DownloadManager.ERROR_UNHANDLED_HTTP_CODE);
+ }
+
+ /**
+ * Tests the download failure error from an unhandled HTTP status code
+ */
+ @LargeTest
+ public void testErrorHttpDataError_invalidRedirect() throws Exception {
+ Uri uri = getServerUri(DEFAULT_FILENAME);
+ MockResponse response = enqueueResponse(HTTP_REDIRECT);
+ response.addHeader("Location", "://blah.blah.blah.com");
+
+ doErrorTest(uri, DownloadManager.ERROR_HTTP_DATA_ERROR);
+ }
+
+ /**
+ * Tests that we can remove a download from the download manager.
+ */
+ @LargeTest
+ public void testRemoveDownload() throws Exception {
+ int fileSize = 100 * 1024; // 100k
+ byte[] blobData = generateData(fileSize, DataType.BINARY);
+
+ long dlRequest = doBasicDownload(blobData);
+ Cursor cursor = mDownloadManager.query(new Query().setFilterById(dlRequest));
+ try {
+ assertEquals("The count of downloads with this ID is not 1!", 1, cursor.getCount());
+ mDownloadManager.remove(dlRequest);
+ cursor.requery();
+ assertEquals("The count of downloads with this ID is not 0!", 0, cursor.getCount());
+ } finally {
+ cursor.close();
+ }
+ }
+
+ /**
+ * Tests that we can set the title of a download.
+ */
+ @LargeTest
+ public void testSetTitle() throws Exception {
+ int fileSize = 50 * 1024; // 50k
+ byte[] blobData = generateData(fileSize, DataType.BINARY);
+ MockResponse response = enqueueResponse(HTTP_OK, blobData);
+
+ // An arbitrary unicode string title
+ final String title = "\u00a5123;\"\u0152\u017d \u054b \u0a07 \ucce0 \u6820\u03a8\u5c34" +
+ "\uf4ad\u0da9\uc0c5\uc1a8 \uf4c5 \uf4aa\u0023\'";
+
+ Uri uri = getServerUri(DEFAULT_FILENAME);
+ Request request = new Request(uri);
+ request.setTitle(title);
+
+ long dlRequest = mDownloadManager.enqueue(request);
+ waitForDownloadOrTimeout(dlRequest);
+
+ Cursor cursor = getCursor(dlRequest);
+ try {
+ verifyString(cursor, DownloadManager.COLUMN_TITLE, title);
} finally {
- largeFile1.delete();
- largeFile2.delete();
+ cursor.close();
}
}
}
diff --git a/core/tests/hosttests/src/android/net/DownloadManagerHostTests.java b/core/tests/hosttests/src/android/net/DownloadManagerHostTests.java
index ed280c916ec4..df781bf46676 100644
--- a/core/tests/hosttests/src/android/net/DownloadManagerHostTests.java
+++ b/core/tests/hosttests/src/android/net/DownloadManagerHostTests.java
@@ -54,8 +54,10 @@ public class DownloadManagerHostTests extends DeviceTestCase {
private static final String EXTERNAL_DOWNLOAD_URI_KEY = "external_download_uri";
// Note: External environment variable ANDROID_TEST_EXTERNAL_URI must be set to point to the
// external URI under which the files downloaded by the tests can be found. Note that the Uri
- // must be accessible by the device during a test run.
- private static String EXTERNAL_DOWNLOAD_URI_VALUE = null;
+ // must be accessible by the device during a test run. Correspondingly,
+ // ANDROID_TEST_EXTERNAL_LARGE_URI should point to the external URI of the folder containing
+ // large files.
+ private static String externalDownloadUriValue = null;
Hashtable<String, String> mExtraParams = null;
@@ -69,8 +71,8 @@ public class DownloadManagerHostTests extends DeviceTestCase {
// ensure apk path has been set before test is run
assertNotNull(getTestAppPath());
mPMUtils = new PackageManagerHostTestUtils(getDevice());
- EXTERNAL_DOWNLOAD_URI_VALUE = System.getenv("ANDROID_TEST_EXTERNAL_URI");
- assertNotNull(EXTERNAL_DOWNLOAD_URI_VALUE);
+ externalDownloadUriValue = System.getenv("ANDROID_TEST_EXTERNAL_URI");
+ assertNotNull(externalDownloadUriValue);
mExtraParams = getExtraParams();
}
@@ -79,7 +81,7 @@ public class DownloadManagerHostTests extends DeviceTestCase {
*/
protected Hashtable<String, String> getExtraParams() {
Hashtable<String, String> extraParams = new Hashtable<String, String>();
- extraParams.put(EXTERNAL_DOWNLOAD_URI_KEY, EXTERNAL_DOWNLOAD_URI_VALUE);
+ extraParams.put(EXTERNAL_DOWNLOAD_URI_KEY, externalDownloadUriValue);
return extraParams;
}
@@ -198,4 +200,19 @@ public class DownloadManagerHostTests extends DeviceTestCase {
DOWNLOAD_TEST_RUNNER_NAME, mExtraParams);
assertTrue(testPassed);
}
+
+ /**
+ * Spawns a device-based function to test 15 concurrent downloads of 5,000,000-byte files
+ *
+ * @throws Exception if the test failed at any point
+ */
+ public void testDownloadMultipleSimultaneously() throws Exception {
+ mPMUtils.installAppAndVerifyExistsOnDevice(String.format("%s%s%s", getTestAppPath(),
+ File.separator, FILE_DOWNLOAD_APK), FILE_DOWNLOAD_PKG, true);
+
+ boolean testPassed = mPMUtils.runDeviceTestsDidAllTestsPass(FILE_DOWNLOAD_PKG,
+ FILE_DOWNLOAD_CLASS, "runDownloadMultipleSimultaneously",
+ DOWNLOAD_TEST_RUNNER_NAME, mExtraParams);
+ assertTrue(testPassed);
+ }
}
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java
index ef8135398583..0293ded853c1 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestApp.java
@@ -35,6 +35,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
+import java.util.HashSet;
import coretestutils.http.MockResponse;
import coretestutils.http.MockWebServer;
@@ -55,8 +56,13 @@ public class DownloadManagerTestApp extends DownloadManagerBaseTest {
protected static String DOWNLOAD_10MB_FILENAME = "External10mb.apk";
protected static long DOWNLOAD_10MB_FILESIZE = 10258741;
+ private static final String FILE_CONCURRENT_DOWNLOAD_FILE_PREFIX = "file";
+ private static final String FILE_CONCURRENT_DOWNLOAD_FILE_EXTENSION = ".bin";
+ protected static long CONCURRENT_DOWNLOAD_FILESIZE = 1000000;
+
// Values to be obtained from TestRunner
private String externalDownloadUriValue = null;
+ private String externalLargeDownloadUriValue = null;
/**
* {@inheritDoc }
@@ -65,12 +71,24 @@ public class DownloadManagerTestApp extends DownloadManagerBaseTest {
public void setUp() throws Exception {
super.setUp();
DownloadManagerTestRunner mRunner = (DownloadManagerTestRunner)getInstrumentation();
- externalDownloadUriValue = mRunner.externalDownloadUriValue;
+ externalDownloadUriValue = normalizeUri(mRunner.externalDownloadUriValue);
assertNotNull(externalDownloadUriValue);
- if (!externalDownloadUriValue.endsWith("/")) {
- externalDownloadUriValue += "/";
+ externalLargeDownloadUriValue = normalizeUri(mRunner.externalDownloadUriValue);
+ assertNotNull(externalLargeDownloadUriValue);
+ }
+
+ /**
+ * Normalizes a uri to ensure it ends with a "/"
+ *
+ * @param uri The uri to normalize (or null)
+ * @return The normalized uri, or null if null was passed in
+ */
+ public String normalizeUri(String uri) {
+ if (uri != null && !uri.endsWith("/")) {
+ uri += "/";
}
+ return uri;
}
/**
@@ -460,4 +478,37 @@ public class DownloadManagerTestApp extends DownloadManagerBaseTest {
downloadedFile.delete();
}
}
+
+ /**
+ * Tests 15 concurrent downloads of 1,000,000-byte files.
+ *
+ * @throws Exception if test failed
+ */
+ public void runDownloadMultipleSimultaneously() throws Exception {
+ final int TOTAL_DOWNLOADS = 15;
+ HashSet<Long> downloadIds = new HashSet<Long>(TOTAL_DOWNLOADS);
+ MultipleDownloadsCompletedReceiver receiver = registerNewMultipleDownloadsReceiver();
+
+ // Make sure there are no pending downloads currently going on
+ removeAllCurrentDownloads();
+
+ try {
+ for (int i = 0; i < TOTAL_DOWNLOADS; ++i) {
+ long dlRequest = -1;
+ String filename = FILE_CONCURRENT_DOWNLOAD_FILE_PREFIX + i
+ + FILE_CONCURRENT_DOWNLOAD_FILE_EXTENSION;
+ Uri remoteUri = getExternalFileUri(filename);
+ Request request = new Request(remoteUri);
+ request.setTitle(filename);
+ dlRequest = mDownloadManager.enqueue(request);
+ assertTrue(dlRequest != -1);
+ downloadIds.add(dlRequest);
+ }
+
+ waitForDownloadsOrTimeout(DEFAULT_WAIT_POLL_TIME, 15 * 60 * 2000); // wait 15 mins max
+ assertEquals(TOTAL_DOWNLOADS, receiver.numDownloadsCompleted());
+ } finally {
+ removeAllCurrentDownloads();
+ }
+ }
}
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestRunner.java b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestRunner.java
index 0f166195b4be..27bf7e1e2497 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestRunner.java
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/src/com/android/frameworks/DownloadManagerTestRunner.java
@@ -30,7 +30,7 @@ import junit.framework.TestSuite;
*
* To run the download manager tests:
*
- * adb shell am instrument -e external_download_1mb_uri <uri> external_download_500k_uri <uri> \
+ * adb shell am instrument -e external_download_uri <uri> external_large_download_uri <uri> \
* -w com.android.frameworks.downloadmanagertests/.DownloadManagerTestRunner
*/
diff --git a/include/camera/CameraParameters.h b/include/camera/CameraParameters.h
index 7c5371aafe0c..53039a09153f 100644
--- a/include/camera/CameraParameters.h
+++ b/include/camera/CameraParameters.h
@@ -380,12 +380,14 @@ public:
// continuously. Applications should not call
// CameraHardwareInterface.autoFocus in this mode.
static const char FOCUS_MODE_EDOF[];
- // Continuous auto focus mode. The camera continuously tries to focus. This
- // is ideal for shooting video or shooting photo of moving object. Auto
- // focus starts when the parameter is set. Applications should not call
- // CameraHardwareInterface.autoFocus in this mode. To stop continuous
- // focus, applications should change the focus mode to other modes.
- static const char FOCUS_MODE_CONTINUOUS[];
+ // Continuous auto focus mode intended for video recording. The camera
+ // continuously tries to focus. This is ideal for shooting video.
+ // Applications still can call CameraHardwareInterface.takePicture in this
+ // mode but the subject may not be in focus. Auto focus starts when the
+ // parameter is set. Applications should not call
+ // CameraHardwareInterface.autoFocus in this mode. To stop continuous focus,
+ // applications should change the focus mode to other modes.
+ static const char FOCUS_MODE_CONTINUOUS_VIDEO[];
private:
DefaultKeyedVector<String8,String8> mMap;
diff --git a/libs/camera/CameraParameters.cpp b/libs/camera/CameraParameters.cpp
index 362d9ee1c15b..83e5e57f1f73 100644
--- a/libs/camera/CameraParameters.cpp
+++ b/libs/camera/CameraParameters.cpp
@@ -142,7 +142,7 @@ 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_CONTINUOUS[] = "continuous";
+const char CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO[] = "continuous-video";
CameraParameters::CameraParameters()
: mMap()
diff --git a/location/java/android/location/Geocoder.java b/location/java/android/location/Geocoder.java
index 546bb9d84c73..ac7eb8b18e97 100644
--- a/location/java/android/location/Geocoder.java
+++ b/location/java/android/location/Geocoder.java
@@ -41,7 +41,7 @@ import java.util.List;
* The Geocoder class requires a backend service that is not included in
* the core android framework. The Geocoder query methods will return an
* empty list if there no backend service in the platform. Use the
- * isImplemented() method to determine whether a Geocoder implementation
+ * isPresent() method to determine whether a Geocoder implementation
* exists.
*/
public final class Geocoder {
@@ -56,13 +56,13 @@ public final class Geocoder {
* connectivity may still cause these methods to return null or
* empty lists.
*/
- public static Boolean isImplemented() {
+ public static boolean isPresent() {
IBinder b = ServiceManager.getService(Context.LOCATION_SERVICE);
ILocationManager lm = ILocationManager.Stub.asInterface(b);
try {
- return lm.geocoderIsImplemented();
+ return lm.geocoderIsPresent();
} catch (RemoteException e) {
- Log.e(TAG, "isImplemented: got RemoteException", e);
+ Log.e(TAG, "isPresent: got RemoteException", e);
return false;
}
}
diff --git a/location/java/android/location/GeocoderParams.java b/location/java/android/location/GeocoderParams.java
index 8b8e63b2c98a..174fe3e0af2e 100644
--- a/location/java/android/location/GeocoderParams.java
+++ b/location/java/android/location/GeocoderParams.java
@@ -29,6 +29,8 @@ import java.util.Locale;
* as well as the Geocoder client's package name for geocoder server
* logging. This information is kept in a separate class to allow for
* future expansion of the IGeocodeProvider interface.
+ *
+ * @hide
*/
public class GeocoderParams implements Parcelable {
private Locale mLocale;
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 32d4b274f00c..2255bf2ecaaa 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -67,7 +67,7 @@ interface ILocationManager
// it need not be shared with other providers.
void reportLocation(in Location location, boolean passive);
- boolean geocoderIsImplemented();
+ boolean geocoderIsPresent();
String getFromLocation(double latitude, double longitude, int maxResults,
in GeocoderParams params, out List<Address> addrs);
String getFromLocationName(String locationName,
diff --git a/location/java/android/location/provider/GeocodeProvider.java b/location/java/android/location/provider/GeocodeProvider.java
index 9a587631690a..493c631eb693 100644
--- a/location/java/android/location/provider/GeocodeProvider.java
+++ b/location/java/android/location/provider/GeocodeProvider.java
@@ -29,6 +29,8 @@ import java.util.List;
* outside of the core android platform.
* Geocode providers can be implemented as services and return the result of
* {@link GeocodeProvider#getBinder()} in its getBinder() method.
+ *
+ * @hide
*/
public abstract class GeocodeProvider {
diff --git a/location/java/android/location/provider/LocationProvider.java b/location/java/android/location/provider/LocationProvider.java
index 95b4425bfc25..14dea1482e0f 100644
--- a/location/java/android/location/provider/LocationProvider.java
+++ b/location/java/android/location/provider/LocationProvider.java
@@ -34,6 +34,8 @@ import android.util.Log;
* outside of the core android platform.
* Location providers can be implemented as services and return the result of
* {@link LocationProvider#getBinder()} in its getBinder() method.
+ *
+ * @hide
*/
public abstract class LocationProvider {
diff --git a/media/java/android/media/AudioEffect.java b/media/java/android/media/AudioEffect.java
index ae67114a27fb..ed7601eb19c4 100644
--- a/media/java/android/media/AudioEffect.java
+++ b/media/java/android/media/AudioEffect.java
@@ -847,39 +847,40 @@ public class AudioEffect {
// -------------------------------------------------------------------------
/**
- * This intent launches an audio effect control panel UI. The goal of this intent is to enable
- * separate implementations of music/media player applications and audio effect control
- * application or services. This will allow platform vendors to offer more advanced control
- * options for standard effects or control for platform specific effects.
+ * Intent to launch an audio effect control panel UI.
+ * <p>The goal of this intent is to enable separate implementations of music/media player
+ * applications and audio effect control application or services.
+ * This will allow platform vendors to offer more advanced control options for standard effects
+ * or control for platform specific effects.
* <p>The intent carries a number of extras used by the player application to communicate
* necessary pieces of information to the control panel application.
* <p>The calling application must use the
* {@link android.app.Activity#startActivityForResult(Intent, int)} method to launch the
* control panel so that its package name is indicated and used by the control panel
* application to keep track of changes for this particular application.
- * <p>The android.media.EXTRA_AUDIO_SESSION extra will indicate an audio session to which the
+ * <p>The {@link #EXTRA_AUDIO_SESSION} extra will indicate an audio session to which the
* audio effects should be applied. If no audio session is specified, either one of the
* follownig will happen:
- * - If an audio session was previously opened by the calling application with
+ * <p>- If an audio session was previously opened by the calling application with
* {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} intent, the effect changes will
* be applied to that session.
- * - If no audio session is opened, the changes will be stored in the package specific storage
- * area and applied whenever a new audio session is opened by this application.
- * <p>The android.media.EXTRA_CONTENT_TYPE extra will help the control panel application
+ * <p>- If no audio session is opened, the changes will be stored in the package specific
+ * storage area and applied whenever a new audio session is opened by this application.
+ * <p>The {@link #EXTRA_CONTENT_TYPE} extra will help the control panel application
* customize both the UI layout and the default audio effect settings if none are already
* stored for the calling application.
- * {@hide} pending API council approval
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL =
"android.media.action.DISPLAY_AUDIO_EFFECT_CONTROL_PANEL";
/**
- * This intent indicates to the effect control application or service that a new audio session
- * is opened and requires audio effects to be applied. This is different from
- * {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL} in that no UI should be displayed in
- * this case. Music player applications can broadcast this intent before starting playback
- * to make sure that any audio effect settings previously selected by the user are applied.
+ * Intent to signal to the effect control application or service that a new audio session
+ * is opened and requires audio effects to be applied.
+ * <p>This is different from {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL} in that no
+ * UI should be displayed in this case. Music player applications can broadcast this intent
+ * before starting playback to make sure that any audio effect settings previously selected
+ * by the user are applied.
* <p>The effect control application receiving this intent will look for previously stored
* settings for the calling application, create all required audio effects and apply the
* effect settings to the specified audio session.
@@ -888,48 +889,50 @@ public class AudioEffect {
* <p>If no stored settings are found for the calling application, default settings for the
* content type indicated by {@link #EXTRA_CONTENT_TYPE} will be applied. The default settings
* for a given content type are platform specific.
- * {@hide} pending API council approval
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION =
"android.media.action.OPEN_AUDIO_EFFECT_CONTROL_SESSION";
/**
- * This intent indicates to the effect control application or service that an audio session
+ * Intent to signal to the effect control application or service that an audio session
* is closed and that effects should not be applied anymore.
- * <p>The effect control application receiving this intent will delete all effects on this
- * session and store current settings in package specific storage.
+ * <p>The effect control application receiving this intent will delete all effects on
+ * this session and store current settings in package specific storage.
* <p>The calling package name is indicated by the {@link #EXTRA_PACKAGE_NAME} extra and the
* audio session ID by the {@link #EXTRA_AUDIO_SESSION} extra. Both extras are mandatory.
* <p>It is good practice for applications to broadcast this intent when music playback stops
* and/or when exiting to free system resources consumed by audio effect engines.
- * {@hide} pending API council approval
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION =
"android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION";
/**
- * This extra indicates the ID of the audio session the effects should be applied to.
+ * Contains the ID of the audio session the effects should be applied to.
+ * <p>This extra is for use with {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL},
+ * {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} and
+ * {@link #ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION} intents.
* <p>The extra value is of type int and is the audio session ID.
- * @see android.media.MediaPlayer#setAudioSessionId(int) for details on audio sessions.
- * {@hide} pending API council approval
+ *
+ * @see android.media.MediaPlayer#setAudioSessionId(int)
*/
public static final String EXTRA_AUDIO_SESSION = "android.media.extra.AUDIO_SESSION";
/**
- * This extra indicates the package name of the calling application for
- * {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} and
+ * Contains the package name of the calling application.
+ * <p>This extra is for use with {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} and
* {@link #ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION} intents.
* <p>The extra value is a string containing the full package name.
- * {@hide} pending API council approval
*/
public static final String EXTRA_PACKAGE_NAME = "android.media.extra.PACKAGE_NAME";
/**
- * This extra indicates which type of content is played by the application. This information is
- * used by the effect control application to customize UI and default effect settings.
- * The content type is one of the following:
+ * Indicates which type of content is played by the application.
+ * <p>This extra is for use with {@link #ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL} and
+ * {@link #ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION} intents.
+ * <p>This information is used by the effect control application to customize UI and select
+ * appropriate default effect settings. The content type is one of the following:
* <ul>
* <li>{@link #CONTENT_TYPE_MUSIC}</li>
* <li>{@link #CONTENT_TYPE_MOVIE}</li>
@@ -937,28 +940,23 @@ public class AudioEffect {
* <li>{@link #CONTENT_TYPE_VOICE}</li>
* </ul>
* If omitted, the content type defaults to {@link #CONTENT_TYPE_MUSIC}.
- * {@hide} pending API council approval
*/
public static final String EXTRA_CONTENT_TYPE = "android.media.extra.CONTENT_TYPE";
/**
* Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is music
- * {@hide} pending API council approval
*/
public static final int CONTENT_TYPE_MUSIC = 0;
/**
- * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is video of movie
- * {@hide} pending API council approval
+ * Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is video or movie
*/
public static final int CONTENT_TYPE_MOVIE = 1;
/**
* Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is game audio
- * {@hide} pending API council approval
*/
public static final int CONTENT_TYPE_GAME = 2;
/**
* Value for {@link #EXTRA_CONTENT_TYPE} when the type of content played is voice audio
- * {@hide} pending API council approval
*/
public static final int CONTENT_TYPE_VOICE = 3;
diff --git a/media/libstagefright/codecs/aacdec/AACDecoder.cpp b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
index c5b51c054c5d..e4ed5e69b263 100644
--- a/media/libstagefright/codecs/aacdec/AACDecoder.cpp
+++ b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
@@ -123,6 +123,8 @@ status_t AACDecoder::start(MetaData *params) {
mAnchorTimeUs = 0;
mNumSamplesOutput = 0;
mStarted = true;
+ mNumDecodedBuffers = 0;
+ mUpsamplingFactor = 2;
return OK;
}
@@ -207,22 +209,65 @@ status_t AACDecoder::read(
Int decoderErr = PVMP4AudioDecodeFrame(mConfig, mDecoderBuf);
- // Check on the sampling rate to see whether it is changed.
- int32_t sampleRate;
- CHECK(mMeta->findInt32(kKeySampleRate, &sampleRate));
- if (mConfig->samplingRate != sampleRate) {
- mMeta->setInt32(kKeySampleRate, mConfig->samplingRate);
- LOGW("Sample rate was %d, but now is %d",
- sampleRate, mConfig->samplingRate);
- buffer->release();
- mInputBuffer->release();
- mInputBuffer = NULL;
- return INFO_FORMAT_CHANGED;
+ /*
+ * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
+ * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
+ * rate system and the sampling rate in the final output is actually
+ * doubled compared with the core AAC decoder sampling rate.
+ *
+ * Explicit signalling is done by explicitly defining SBR audio object
+ * type in the bitstream. Implicit signalling is done by embedding
+ * SBR content in AAC extension payload specific to SBR, and hence
+ * requires an AAC decoder to perform pre-checks on actual audio frames.
+ *
+ * Thus, we could not say for sure whether a stream is
+ * AAC+/eAAC+ until the first data frame is decoded.
+ */
+ if (++mNumDecodedBuffers <= 2) {
+ LOGV("audio/extended audio object type: %d + %d",
+ mConfig->audioObjectType, mConfig->extendedAudioObjectType);
+ LOGV("aac+ upsampling factor: %d desired channels: %d",
+ mConfig->aacPlusUpsamplingFactor, mConfig->desiredChannels);
+
+ CHECK(mNumDecodedBuffers > 0);
+ if (mNumDecodedBuffers == 1) {
+ mUpsamplingFactor = mConfig->aacPlusUpsamplingFactor;
+ // Check on the sampling rate to see whether it is changed.
+ int32_t sampleRate;
+ CHECK(mMeta->findInt32(kKeySampleRate, &sampleRate));
+ if (mConfig->samplingRate != sampleRate) {
+ mMeta->setInt32(kKeySampleRate, mConfig->samplingRate);
+ LOGW("Sample rate was %d Hz, but now is %d Hz",
+ sampleRate, mConfig->samplingRate);
+ buffer->release();
+ mInputBuffer->release();
+ mInputBuffer = NULL;
+ return INFO_FORMAT_CHANGED;
+ }
+ } else { // mNumDecodedBuffers == 2
+ if (mConfig->extendedAudioObjectType == MP4AUDIO_AAC_LC ||
+ mConfig->extendedAudioObjectType == MP4AUDIO_LTP) {
+ if (mUpsamplingFactor == 2) {
+ // The stream turns out to be not aacPlus mode anyway
+ LOGW("Disable AAC+/eAAC+ since extended audio object type is %d",
+ mConfig->extendedAudioObjectType);
+ mConfig->aacPlusEnabled = 0;
+ }
+ } else {
+ if (mUpsamplingFactor == 1) {
+ // aacPlus mode does not buy us anything, but to cause
+ // 1. CPU load to increase, and
+ // 2. a half speed of decoding
+ LOGW("Disable AAC+/eAAC+ since upsampling factor is 1");
+ mConfig->aacPlusEnabled = 0;
+ }
+ }
+ }
}
size_t numOutBytes =
mConfig->frameLength * sizeof(int16_t) * mConfig->desiredChannels;
- if (mConfig->aacPlusUpsamplingFactor == 2) {
+ if (mUpsamplingFactor == 2) {
if (mConfig->desiredChannels == 1) {
memcpy(&mConfig->pOutputBuffer[1024], &mConfig->pOutputBuffer[2048], numOutBytes * 2);
}
diff --git a/media/libstagefright/include/AACDecoder.h b/media/libstagefright/include/AACDecoder.h
index 200f93c646b8..886a3b723ebd 100644
--- a/media/libstagefright/include/AACDecoder.h
+++ b/media/libstagefright/include/AACDecoder.h
@@ -53,6 +53,8 @@ private:
int64_t mAnchorTimeUs;
int64_t mNumSamplesOutput;
status_t mInitCheck;
+ int64_t mNumDecodedBuffers;
+ int32_t mUpsamplingFactor;
MediaBuffer *mInputBuffer;
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png
index d0d13457b112..95866b12e611 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g_fully.png
index 5af2b050cb9e..5524e26ac7eb 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_connected_3g_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png
index 11ee0f289511..07ea499fb741 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g_fully.png
index 31c976a0d6cc..a8411fc6b552 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_in_3g_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g.png
index dba9675cd963..95bb3cd92510 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g_fully.png
index 3903545edde0..f7dda73f14b2 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_inandout_3g_fully.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png
index 04ec59e36d32..cac78027f574 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g_fully.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g_fully.png
index d44a4cfc1177..eb5150fac33d 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g_fully.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_data_out_3g_fully.png
Binary files differ
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
index 7ccf210f77be..0fc092ef9a09 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarPolicy.java
@@ -711,21 +711,20 @@ public class StatusBarPolicy {
ConnectivityManager.EXTRA_NETWORK_INFO));
int connectionStatus = intent.getIntExtra(ConnectivityManager.EXTRA_INET_CONDITION, 0);
Slog.d(TAG, "got CONNECTIVITY_ACTION - info=" + info + ", status = " + connectionStatus);
- if (info.isConnected() == false) return;
+
+ int inetCondition = (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
switch (info.getType()) {
case ConnectivityManager.TYPE_MOBILE:
- if (info.isConnected()) {
- updateDataNetType(info.getSubtype(), connectionStatus);
- updateDataIcon();
- updateSignalStrength(); // apply any change in connectionStatus
- }
+ mInetCondition = inetCondition;
+ updateDataNetType(info.getSubtype());
+ updateDataIcon();
+ updateSignalStrength(); // apply any change in connectionStatus
break;
case ConnectivityManager.TYPE_WIFI:
+ mInetCondition = inetCondition;
if (info.isConnected()) {
mIsWifiConnected = true;
- mInetCondition =
- (connectionStatus > INET_CONDITION_THRESHOLD ? 1 : 0);
int iconId;
if (mLastWifiSignalLevel == -1) {
iconId = sWifiSignalImages[mInetCondition][0];
@@ -738,7 +737,6 @@ public class StatusBarPolicy {
} else {
mLastWifiSignalLevel = -1;
mIsWifiConnected = false;
- mInetCondition = 0;
int iconId = sWifiSignalImages[0][0];
mService.setIcon("wifi", iconId, 0);
@@ -777,9 +775,8 @@ public class StatusBarPolicy {
@Override
public void onDataConnectionStateChanged(int state, int networkType) {
mDataState = state;
- updateDataNetType(networkType, 0);
+ updateDataNetType(networkType);
updateDataIcon();
- updateSignalStrength(); // apply the change in connection status
}
@Override
@@ -940,8 +937,7 @@ public class StatusBarPolicy {
return (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;
}
- private final void updateDataNetType(int net, int inetCondition) {
- mInetCondition = (inetCondition > INET_CONDITION_THRESHOLD ? 1 : 0);
+ private final void updateDataNetType(int net) {
switch (net) {
case TelephonyManager.NETWORK_TYPE_EDGE:
mDataIconList = sDataNetType_e[mInetCondition];
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
index af736aa33195..b5552770b656 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarService.java
@@ -82,7 +82,7 @@ import com.android.systemui.statusbar.policy.StatusBarPolicy;
public class StatusBarService extends Service implements CommandQueue.Callbacks {
static final String TAG = "StatusBarService";
- static final boolean SPEW = false;
+ static final boolean SPEW = true;
public static final String ACTION_STATUSBAR_START
= "com.android.internal.policy.statusbar.START";
@@ -1534,4 +1534,3 @@ public class StatusBarService extends Service implements CommandQueue.Callbacks
}
};
}
-
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java
index 55d31ec00e80..29df28eb1045 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbStorageActivity.java
@@ -30,6 +30,7 @@ import android.content.DialogInterface.OnCancelListener;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.hardware.Usb;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
@@ -70,11 +71,11 @@ public class UsbStorageActivity extends Activity
static final boolean localLOGV = false;
/** Used to detect when the USB cable is unplugged, so we can call finish() */
- private BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() {
+ private BroadcastReceiver mUsbStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- if (intent.getAction() == Intent.ACTION_BATTERY_CHANGED) {
- handleBatteryChanged(intent);
+ if (intent.getAction().equals(Usb.ACTION_USB_STATE)) {
+ handleUsbStateChanged(intent);
}
}
};
@@ -139,7 +140,7 @@ public class UsbStorageActivity extends Activity
super.onResume();
mStorageManager.registerListener(mStorageListener);
- registerReceiver(mBatteryReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+ registerReceiver(mUsbStateReceiver, new IntentFilter(Usb.ACTION_USB_STATE));
try {
switchDisplay(mStorageManager.isUsbMassStorageEnabled());
} catch (Exception ex) {
@@ -151,15 +152,15 @@ public class UsbStorageActivity extends Activity
protected void onPause() {
super.onPause();
- unregisterReceiver(mBatteryReceiver);
+ unregisterReceiver(mUsbStateReceiver);
if (mStorageManager == null && mStorageListener != null) {
mStorageManager.unregisterListener(mStorageListener);
}
}
- private void handleBatteryChanged(Intent intent) {
- int pluggedType = intent.getIntExtra("plugged", 0);
- if (pluggedType == 0) {
+ private void handleUsbStateChanged(Intent intent) {
+ boolean connected = intent.getExtras().getBoolean(Usb.USB_CONNECTED);
+ if (!connected) {
// It was disconnected from the plug, so finish
finish();
}
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index c5505d1139a0..f38748b44e83 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -48,6 +48,7 @@ import com.android.server.connectivity.Tethering;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.GregorianCalendar;
import java.util.List;
/**
@@ -109,6 +110,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private boolean mSystemReady;
private Intent mInitialBroadcast;
+ // used in DBG mode to track inet condition reports
+ private static final int INET_CONDITION_LOG_MAX_SIZE = 15;
+ private ArrayList mInetLog;
+
private static class NetworkAttributes {
/**
* Class for holding settings read from resources.
@@ -329,6 +334,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mTethering.getTetherableWifiRegexs().length != 0) &&
mTethering.getUpstreamIfaceRegexs().length != 0);
+ if (DBG) {
+ mInetLog = new ArrayList();
+ }
}
@@ -912,11 +920,19 @@ public class ConnectivityService extends IConnectivityManager.Stub {
newNet = tryFailover(prevNetType);
if (newNet != null) {
NetworkInfo switchTo = newNet.getNetworkInfo();
+ if (!switchTo.isConnected()) {
+ // if the other net is connected they've already reset this and perhaps even gotten
+ // a positive report we don't want to overwrite, but if not we need to clear this now
+ // to turn our cellular sig strength white
+ mDefaultInetConditionPublished = 0;
+ }
intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
} else {
+ mDefaultInetConditionPublished = 0; // we're not connected anymore
intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
}
}
+ intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
// do this before we broadcast the change
handleConnectivityChange(prevNetType);
@@ -1075,12 +1091,20 @@ public class ConnectivityService extends IConnectivityManager.Stub {
newNet = tryFailover(info.getType());
if (newNet != null) {
NetworkInfo switchTo = newNet.getNetworkInfo();
+ if (!switchTo.isConnected()) {
+ // if the other net is connected they've already reset this and perhaps even gotten
+ // a positive report we don't want to overwrite, but if not we need to clear this now
+ // to turn our cellular sig strength white
+ mDefaultInetConditionPublished = 0;
+ }
intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO, switchTo);
} else {
+ mDefaultInetConditionPublished = 0;
intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
}
}
+ intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION, mDefaultInetConditionPublished);
sendStickyBroadcast(intent);
/*
* If the failover network is already connected, then immediately send
@@ -1365,6 +1389,14 @@ public class ConnectivityService extends IConnectivityManager.Stub {
pw.println();
mTethering.dump(fd, pw, args);
+
+ if (mInetLog != null) {
+ pw.println();
+ pw.println("Inet condition reports:");
+ for(int i = 0; i < mInetLog.size(); i++) {
+ pw.println(mInetLog.get(i));
+ }
+ }
}
// must be stateless - things change under us.
@@ -1613,6 +1645,17 @@ public class ConnectivityService extends IConnectivityManager.Stub {
android.Manifest.permission.STATUS_BAR,
"ConnectivityService");
+ if (DBG) {
+ int pid = getCallingPid();
+ int uid = getCallingUid();
+ String s = pid + "(" + uid + ") reports inet is " +
+ (percentage > 50 ? "connected" : "disconnected") + " (" + percentage + ") on " +
+ "network Type " + networkType + " at " + GregorianCalendar.getInstance().getTime();
+ mInetLog.add(s);
+ while(mInetLog.size() > INET_CONDITION_LOG_MAX_SIZE) {
+ mInetLog.remove(0);
+ }
+ }
mHandler.sendMessage(mHandler.obtainMessage(
NetworkStateTracker.EVENT_INET_CONDITION_CHANGE, networkType, percentage));
}
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index f3ce8baaf785..643b2f52ff73 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -1959,7 +1959,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
// Geocoder
- public boolean geocoderIsImplemented() {
+ public boolean geocoderIsPresent() {
return mGeocodeProvider != null;
}
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 72784d50c423..4c15c940eff7 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -222,6 +222,9 @@ class PackageManagerService extends IPackageManager.Stub {
// This is the object monitoring the system app dir.
final FileObserver mSystemInstallObserver;
+ // This is the object monitoring the system app dir.
+ final FileObserver mVendorInstallObserver;
+
// This is the object monitoring mAppInstallDir.
final FileObserver mAppInstallObserver;
@@ -234,6 +237,7 @@ class PackageManagerService extends IPackageManager.Stub {
final File mFrameworkDir;
final File mSystemAppDir;
+ final File mVendorAppDir;
final File mAppInstallDir;
final File mDalvikCacheDir;
@@ -927,6 +931,14 @@ class PackageManagerService extends IPackageManager.Stub {
scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode);
+ // Collect all vendor packages.
+ mVendorAppDir = new File("/vendor/app");
+ mVendorInstallObserver = new AppDirObserver(
+ mVendorAppDir.getPath(), OBSERVER_EVENTS, true);
+ mVendorInstallObserver.startWatching();
+ scanDirLI(mVendorAppDir, PackageParser.PARSE_IS_SYSTEM
+ | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode);
+
if (mInstaller != null) {
if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
mInstaller.moveFiles();
@@ -2493,9 +2505,13 @@ class PackageManagerService extends IPackageManager.Stub {
}
private void scanDirLI(File dir, int flags, int scanMode) {
- Log.d(TAG, "Scanning app dir " + dir);
-
String[] files = dir.list();
+ if (files == null) {
+ Log.d(TAG, "No files in app dir " + dir);
+ return;
+ }
+
+ Log.d(TAG, "Scanning app dir " + dir);
int i;
for (i=0; i<files.length; i++) {
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 371f22ee085e..c047e1052962 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -145,7 +145,7 @@ public class WifiService extends IWifiManager.Stub {
*/
private static final long DEFAULT_IDLE_MILLIS = 15 * 60 * 1000; /* 15 minutes */
- private static final String WAKELOCK_TAG = "WifiService";
+ private static final String WAKELOCK_TAG = "*wifi*";
/**
* The maximum amount of time to hold the wake lock after a disconnect
@@ -173,6 +173,7 @@ public class WifiService extends IWifiManager.Stub {
private static final int MESSAGE_STOP_ACCESS_POINT = 7;
private static final int MESSAGE_SET_CHANNELS = 8;
private static final int MESSAGE_ENABLE_NETWORKS = 9;
+ private static final int MESSAGE_START_SCAN = 10;
private final WifiHandler mWifiHandler;
@@ -385,23 +386,12 @@ public class WifiService extends IWifiManager.Stub {
/**
* see {@link android.net.wifi.WifiManager#startScan()}
- * @return {@code true} if the operation succeeds
*/
- public boolean startScan(boolean forceActive) {
+ public void startScan(boolean forceActive) {
enforceChangePermission();
+ if (mWifiHandler == null) return;
- switch (mWifiStateTracker.getSupplicantState()) {
- case DISCONNECTED:
- case INACTIVE:
- case SCANNING:
- case DORMANT:
- break;
- default:
- mWifiStateTracker.setScanResultHandling(
- WifiStateTracker.SUPPL_SCAN_HANDLING_LIST_ONLY);
- break;
- }
- return mWifiStateTracker.scan(forceActive);
+ Message.obtain(mWifiHandler, MESSAGE_START_SCAN, forceActive ? 1 : 0, 0).sendToTarget();
}
/**
@@ -1825,6 +1815,7 @@ public class WifiService extends IWifiManager.Stub {
}
}
mWifiStateTracker.updateBatteryWorkSourceLocked(mTmpWorkSource);
+ sWakeLock.setWorkSource(mTmpWorkSource);
}
}
@@ -2000,6 +1991,21 @@ public class WifiService extends IWifiManager.Stub {
mWifiStateTracker.enableAllNetworks(getConfiguredNetworks());
break;
+ case MESSAGE_START_SCAN:
+ boolean forceActive = (msg.arg1 == 1);
+ switch (mWifiStateTracker.getSupplicantState()) {
+ case DISCONNECTED:
+ case INACTIVE:
+ case SCANNING:
+ case DORMANT:
+ break;
+ default:
+ mWifiStateTracker.setScanResultHandling(
+ WifiStateTracker.SUPPL_SCAN_HANDLING_LIST_ONLY);
+ break;
+ }
+ mWifiStateTracker.scan(forceActive);
+ break;
}
}
}
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 9835098baa78..d7a1ac25223a 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -8316,6 +8316,11 @@ public class WindowManagerService extends IWindowManager.Stub
return;
}
+ if (mDisplay == null) {
+ // Not yet initialized, nothing to do.
+ return;
+ }
+
boolean recoveringMemory = false;
if (mForceRemoves != null) {
recoveringMemory = true;
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index cf767ca878cf..4f0d2d56499b 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -561,6 +561,11 @@ public final class ActivityManagerService extends ActivityManagerNative
BroadcastRecord mPendingBroadcast = null;
/**
+ * The receiver index that is pending, to restart the broadcast if needed.
+ */
+ int mPendingBroadcastRecvIndex;
+
+ /**
* Keeps track of all IIntentReceivers that have been registered for
* broadcasts. Hash keys are the receiver IBinder, hash value is
* a ReceiverList.
@@ -747,6 +752,7 @@ public final class ActivityManagerService extends ActivityManagerNative
ComponentName mTopComponent;
String mTopAction;
String mTopData;
+ boolean mProcessesReady = false;
boolean mSystemReady = false;
boolean mBooting = false;
boolean mWaitingUpdate = false;
@@ -964,7 +970,11 @@ public final class ActivityManagerService extends ActivityManagerNative
return;
}
- broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
+ Intent intent = new Intent("android.intent.action.ANR");
+ if (!mProcessesReady) {
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ }
+ broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
false, false, MY_PID, Process.SYSTEM_UID);
@@ -1051,7 +1061,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// Only process broadcast timeouts if the system is ready. That way
// PRE_BOOT_COMPLETED broadcasts can't timeout as they are intended
// to do heavy lifting for system up
- if (mSystemReady) {
+ if (mProcessesReady) {
broadcastTimeout();
}
} break;
@@ -1383,7 +1393,7 @@ public final class ActivityManagerService extends ActivityManagerNative
mBatteryStatsService = new BatteryStatsService(new File(
systemDir, "batterystats.bin").toString());
mBatteryStatsService.getActiveStatistics().readLocked();
- mBatteryStatsService.getActiveStatistics().writeLocked();
+ mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
mOnBattery = mBatteryStatsService.getActiveStatistics().getIsOnBattery();
mBatteryStatsService.getActiveStatistics().setCallback(this);
@@ -1536,7 +1546,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
mLastWriteTime = now;
- mBatteryStatsService.getActiveStatistics().writeLocked();
+ mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
}
}
}
@@ -1717,10 +1727,12 @@ public final class ActivityManagerService extends ActivityManagerNative
if (!knownToBeDead || app.thread == null) {
// We already have the app running, or are waiting for it to
// come up (we have a pid but not yet its thread), so keep it.
+ if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);
return app;
} else {
// An application record is attached to a previous process,
// clean it up now.
+ if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);
handleAppDiedLocked(app, true);
}
}
@@ -1732,6 +1744,8 @@ public final class ActivityManagerService extends ActivityManagerNative
// If we are in the background, then check to see if this process
// is bad. If so, we will just silently fail.
if (mBadProcesses.get(info.processName, info.uid) != null) {
+ if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
+ + "/" + info.processName);
return null;
}
} else {
@@ -1739,6 +1753,8 @@ public final class ActivityManagerService extends ActivityManagerNative
// crash count so that we won't make it bad until they see at
// least one crash dialog again, and make the process good again
// if it had been bad.
+ if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
+ + "/" + info.processName);
mProcessCrashTimes.remove(info.processName, info.uid);
if (mBadProcesses.get(info.processName, info.uid) != null) {
EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,
@@ -1760,12 +1776,13 @@ public final class ActivityManagerService extends ActivityManagerNative
// If the system is not ready yet, then hold off on starting this
// process until it is.
- if (!mSystemReady
+ if (!mProcessesReady
&& !isAllowedWhileBooting(info)
&& !allowWhileBooting) {
if (!mProcessesOnHold.contains(app)) {
mProcessesOnHold.add(app);
}
+ if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);
return app;
}
@@ -1787,6 +1804,8 @@ public final class ActivityManagerService extends ActivityManagerNative
app.pid = 0;
}
+ if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
+ "startProcessLocked removing on hold: " + app);
mProcessesOnHold.remove(app);
updateCpuStats();
@@ -3040,11 +3059,8 @@ public final class ActivityManagerService extends ActivityManagerNative
Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
Uri.fromParts("package", packageName, null));
intent.putExtra(Intent.EXTRA_UID, pkgUid);
- synchronized (this) {
- broadcastIntentLocked(null, null, intent,
- null, null, 0, null, null, null,
- false, false, MY_PID, Process.SYSTEM_UID);
- }
+ broadcastIntentInPackage("android", Process.SYSTEM_UID, intent,
+ null, null, 0, null, null, null, false, false);
} catch (RemoteException e) {
}
} finally {
@@ -3148,6 +3164,7 @@ public final class ActivityManagerService extends ActivityManagerNative
public void closeSystemDialogs(String reason) {
Intent intent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
if (reason != null) {
intent.putExtra("reason", reason);
}
@@ -3225,6 +3242,9 @@ public final class ActivityManagerService extends ActivityManagerNative
forceStopPackageLocked(packageName, uid, false, false, true);
Intent intent = new Intent(Intent.ACTION_PACKAGE_RESTARTED,
Uri.fromParts("package", packageName, null));
+ if (!mProcessesReady) {
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ }
intent.putExtra(Intent.EXTRA_UID, uid);
broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null,
@@ -3427,6 +3447,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (mPendingBroadcast != null && mPendingBroadcast.curApp.pid == pid) {
Slog.w(TAG, "Unattached app died before broadcast acknowledged, skipping");
+ mPendingBroadcast.state = BroadcastRecord.IDLE;
+ mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
mPendingBroadcast = null;
scheduleBroadcastsLocked();
}
@@ -3502,7 +3524,7 @@ public final class ActivityManagerService extends ActivityManagerNative
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
- boolean normalMode = mSystemReady || isAllowedWhileBooting(app.info);
+ boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
if (!normalMode) {
@@ -3561,6 +3583,8 @@ public final class ActivityManagerService extends ActivityManagerNative
// Remove this record from the list of starting applications.
mPersistentStartingProcesses.remove(app);
+ if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
+ "Attach application locked removing on hold: " + app);
mProcessesOnHold.remove(app);
boolean badApp = false;
@@ -3702,7 +3726,9 @@ public final class ActivityManagerService extends ActivityManagerNative
ArrayList<ProcessRecord> procs =
new ArrayList<ProcessRecord>(mProcessesOnHold);
for (int ip=0; ip<NP; ip++) {
- this.startProcessLocked(procs.get(ip), "on-hold", null);
+ if (DEBUG_PROCESSES) Slog.v(TAG, "Starting process on hold: "
+ + procs.get(ip));
+ startProcessLocked(procs.get(ip), "on-hold", null);
}
}
@@ -5253,7 +5279,7 @@ public final class ActivityManagerService extends ActivityManagerNative
throw new SecurityException(msg);
}
- if (!mSystemReady && !mDidUpdate && !mWaitingUpdate
+ if (!mProcessesReady && !mDidUpdate && !mWaitingUpdate
&& !cpi.processName.equals("system")) {
// If this content provider does not run in the system
// process, and the system is not yet ready to run other
@@ -6040,6 +6066,11 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.i(TAG, "Removing system update proc: " + proc);
removeProcessLocked(proc, true);
}
+
+ // Now that we have cleaned up any update processes, we
+ // are ready to start launching real processes and know that
+ // we won't trample on them any more.
+ mProcessesReady = true;
}
}
@@ -7283,8 +7314,9 @@ public final class ActivityManagerService extends ActivityManagerNative
if (dumpAll) {
pw.println(" Total persistent processes: " + numPers);
pw.println(" mStartRunning=" + mStartRunning
- + " mSystemReady=" + mSystemReady
- + " mBooting=" + mBooting
+ + " mProcessesReady=" + mProcessesReady
+ + " mSystemReady=" + mSystemReady);
+ pw.println(" mBooting=" + mBooting
+ " mBooted=" + mBooted
+ " mFactoryTest=" + mFactoryTest);
pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
@@ -8098,6 +8130,8 @@ public final class ActivityManagerService extends ActivityManagerNative
restart = true;
}
}
+ if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,
+ "Clean-up removing on hold: " + app);
mProcessesOnHold.remove(app);
if (app == mHomeProcess) {
@@ -10118,7 +10152,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
boolean replaced = false;
if (replacePending) {
- for (int i=mOrderedBroadcasts.size()-1; i>=0; i--) {
+ for (int i=mOrderedBroadcasts.size()-1; i>0; i--) {
if (intent.filterEquals(mOrderedBroadcasts.get(i).intent)) {
if (DEBUG_BROADCAST) Slog.v(TAG,
"***** DROPPING ORDERED: " + intent);
@@ -10137,35 +10171,41 @@ public final class ActivityManagerService extends ActivityManagerNative
return BROADCAST_SUCCESS;
}
- public final int broadcastIntent(IApplicationThread caller,
- Intent intent, String resolvedType, IIntentReceiver resultTo,
- int resultCode, String resultData, Bundle map,
- String requiredPermission, boolean serialized, boolean sticky) {
+ final Intent verifyBroadcastLocked(Intent intent) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
- synchronized(this) {
- int flags = intent.getFlags();
-
- if (!mSystemReady) {
- // if the caller really truly claims to know what they're doing, go
- // ahead and allow the broadcast without launching any receivers
- if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
- intent = new Intent(intent);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0){
- Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
- + " before boot completion");
- throw new IllegalStateException("Cannot broadcast before boot completed");
- }
- }
-
- if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
- throw new IllegalArgumentException(
- "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
+ int flags = intent.getFlags();
+
+ if (!mProcessesReady) {
+ // if the caller really truly claims to know what they're doing, go
+ // ahead and allow the broadcast without launching any receivers
+ if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT) != 0) {
+ intent = new Intent(intent);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ } else if ((flags&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
+ Slog.e(TAG, "Attempt to launch receivers of broadcast intent " + intent
+ + " before boot completion");
+ throw new IllegalStateException("Cannot broadcast before boot completed");
}
+ }
+
+ if ((flags&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0) {
+ throw new IllegalArgumentException(
+ "Can't use FLAG_RECEIVER_BOOT_UPGRADE here");
+ }
+
+ return intent;
+ }
+
+ public final int broadcastIntent(IApplicationThread caller,
+ Intent intent, String resolvedType, IIntentReceiver resultTo,
+ int resultCode, String resultData, Bundle map,
+ String requiredPermission, boolean serialized, boolean sticky) {
+ synchronized(this) {
+ intent = verifyBroadcastLocked(intent);
final ProcessRecord callerApp = getRecordForAppLocked(caller);
final int callingPid = Binder.getCallingPid();
@@ -10186,6 +10226,8 @@ public final class ActivityManagerService extends ActivityManagerNative
int resultCode, String resultData, Bundle map,
String requiredPermission, boolean serialized, boolean sticky) {
synchronized(this) {
+ intent = verifyBroadcastLocked(intent);
+
final long origId = Binder.clearCallingIdentity();
int res = broadcastIntentLocked(null, packageName, intent, resolvedType,
resultTo, resultCode, resultData, map, requiredPermission,
@@ -10399,6 +10441,8 @@ public final class ActivityManagerService extends ActivityManagerNative
private final void processCurBroadcastLocked(BroadcastRecord r,
ProcessRecord app) throws RemoteException {
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Process cur broadcast " + r + " for app " + app);
if (app.thread == null) {
throw new RemoteException();
}
@@ -10418,9 +10462,13 @@ public final class ActivityManagerService extends ActivityManagerNative
ensurePackageDexOpt(r.intent.getComponent().getPackageName());
app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
r.resultCode, r.resultData, r.resultExtras, r.ordered);
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Process cur broadcast " + r + " DELIVERED for app " + app);
started = true;
} finally {
if (!started) {
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Process cur broadcast " + r + ": NOT STARTED!");
r.receiver = null;
r.curApp = null;
app.curReceiver = null;
@@ -10585,6 +10633,8 @@ public final class ActivityManagerService extends ActivityManagerNative
} else {
Slog.w(TAG, "pending app " + mPendingBroadcast.curApp
+ " died before responding to broadcast");
+ mPendingBroadcast.state = BroadcastRecord.IDLE;
+ mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
mPendingBroadcast = null;
}
}
@@ -10615,7 +10665,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// one time heavy lifting after system upgrades and can take
// significant amounts of time.
int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
- if (mSystemReady && r.dispatchTime > 0) {
+ if (mProcessesReady && r.dispatchTime > 0) {
long now = SystemClock.uptimeMillis();
if ((numReceivers > 0) &&
(now > r.dispatchTime + (2*BROADCAST_TIMEOUT*numReceivers))) {
@@ -10686,7 +10736,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast "
+ r);
if (DEBUG_BROADCAST) Slog.v(TAG,
- "Submitting BROADCAST_TIMEOUT_MSG for "
+ "Submitting BROADCAST_TIMEOUT_MSG for " + r + " at "
+ (r.receiverTime + BROADCAST_TIMEOUT));
Message msg = mHandler.obtainMessage(BROADCAST_TIMEOUT_MSG);
mHandler.sendMessageAtTime(msg, r.receiverTime+BROADCAST_TIMEOUT);
@@ -10754,10 +10804,15 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (r.curApp != null && r.curApp.crashing) {
// If the target process is crashing, just skip it.
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Skipping deliver ordered " + r + " to " + r.curApp
+ + ": process crashing");
skip = true;
}
if (skip) {
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Skipping delivery of ordered " + r + " for whatever reason");
r.receiver = null;
r.curFilter = null;
r.state = BroadcastRecord.IDLE;
@@ -10789,6 +10844,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
// Not running -- get it started, to be executed when the app comes up.
+ if (DEBUG_BROADCAST) Slog.v(TAG,
+ "Need to start app " + targetProcess + " for broadcast " + r);
if ((r.curApp=startProcessLocked(targetProcess,
info.activityInfo.applicationInfo, true,
r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND,
@@ -10810,6 +10867,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
mPendingBroadcast = r;
+ mPendingBroadcastRecvIndex = recIdx;
}
}
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 4fc802003312..a4497d64e28a 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1104,26 +1104,30 @@ public class ActivityStack {
// Okay we are now going to start a switch, to 'next'. We may first
// have to pause the current activity, but this is an important point
// where we have decided to go to 'next' so keep track of that.
- if (mLastStartedActivity != null && !mLastStartedActivity.finishing) {
- long now = SystemClock.uptimeMillis();
- final boolean inTime = mLastStartedActivity.startTime != 0
- && (mLastStartedActivity.startTime + START_WARN_TIME) >= now;
- final int lastUid = mLastStartedActivity.info.applicationInfo.uid;
- final int nextUid = next.info.applicationInfo.uid;
- if (inTime && lastUid != nextUid
- && lastUid != next.launchedFromUid
- && mService.checkPermission(
- android.Manifest.permission.STOP_APP_SWITCHES,
- -1, next.launchedFromUid)
- != PackageManager.PERMISSION_GRANTED) {
- mService.showLaunchWarningLocked(mLastStartedActivity, next);
+ // XXX "App Redirected" dialog is getting too many false positives
+ // at this point, so turn off for now.
+ if (false) {
+ if (mLastStartedActivity != null && !mLastStartedActivity.finishing) {
+ long now = SystemClock.uptimeMillis();
+ final boolean inTime = mLastStartedActivity.startTime != 0
+ && (mLastStartedActivity.startTime + START_WARN_TIME) >= now;
+ final int lastUid = mLastStartedActivity.info.applicationInfo.uid;
+ final int nextUid = next.info.applicationInfo.uid;
+ if (inTime && lastUid != nextUid
+ && lastUid != next.launchedFromUid
+ && mService.checkPermission(
+ android.Manifest.permission.STOP_APP_SWITCHES,
+ -1, next.launchedFromUid)
+ != PackageManager.PERMISSION_GRANTED) {
+ mService.showLaunchWarningLocked(mLastStartedActivity, next);
+ } else {
+ next.startTime = now;
+ mLastStartedActivity = next;
+ }
} else {
- next.startTime = now;
+ next.startTime = SystemClock.uptimeMillis();
mLastStartedActivity = next;
}
- } else {
- next.startTime = SystemClock.uptimeMillis();
- mLastStartedActivity = next;
}
// We need to start pausing the current activity so the top one
diff --git a/telephony/java/com/android/internal/telephony/CallManager.java b/telephony/java/com/android/internal/telephony/CallManager.java
index 4d8cbf037ab5..23cb42a3cc49 100644
--- a/telephony/java/com/android/internal/telephony/CallManager.java
+++ b/telephony/java/com/android/internal/telephony/CallManager.java
@@ -82,7 +82,7 @@ public final class CallManager {
// Singleton instance
private static final CallManager INSTANCE = new CallManager();
- // list of registered phones
+ // list of registered phones, which are PhoneBase objs
private final ArrayList<Phone> mPhones;
// list of supported ringing calls
@@ -97,7 +97,7 @@ public final class CallManager {
// empty connection list
private final ArrayList<Connection> emptyConnections = new ArrayList<Connection>();
- // default phone as the first phone registered
+ // default phone as the first phone registered, which is PhoneBase obj
private Phone mDefaultPhone;
// state registrants
@@ -181,6 +181,46 @@ public final class CallManager {
}
/**
+ * Get the corresponding PhoneBase obj
+ *
+ * @param phone a Phone object
+ * @return the corresponding PhoneBase obj in Phone if Phone
+ * is a PhoneProxy obj
+ * or the Phone itself if Phone is not a PhoneProxy obj
+ */
+ private static Phone getPhoneBase(Phone phone) {
+ if (phone instanceof PhoneProxy) {
+ return phone.getForegroundCall().getPhone();
+ }
+ return phone;
+ }
+
+ /**
+ * Check if two phones refer to the same PhoneBase obj
+ *
+ * Note: PhoneBase, not PhoneProxy, is to be used inside of CallManager
+ *
+ * Both PhoneBase and PhoneProxy implement Phone interface, so
+ * they have same phone APIs, such as dial(). The real implementation, for
+ * example in GSM, is in GSMPhone as extend from PhoneBase, so that
+ * foregroundCall.getPhone() returns GSMPhone obj. On the other hand,
+ * PhoneFactory.getDefaultPhone() returns PhoneProxy obj, which has a class
+ * member of GSMPhone.
+ *
+ * So for phone returned by PhoneFacotry, which is used by PhoneApp,
+ * phone.getForegroundCall().getPhone() != phone
+ * but
+ * isSamePhone(phone, phone.getForegroundCall().getPhone()) == true
+ *
+ * @param p1 is the first Phone obj
+ * @param p2 is the second Phone obj
+ * @return true if p1 and p2 refer to the same phone
+ */
+ public static boolean isSamePhone(Phone p1, Phone p2) {
+ return (getPhoneBase(p1) == getPhoneBase(p2));
+ }
+
+ /**
* Returns all the registered phone objects.
* @return all the registered phone objects.
*/
@@ -198,9 +238,7 @@ public final class CallManager {
Phone.State s = Phone.State.IDLE;
for (Phone phone : mPhones) {
- if (phone.getState() == Phone.State.ANSWERING) {
- return Phone.State.ANSWERING;
- } else if (phone.getState() == Phone.State.RINGING) {
+ if (phone.getState() == Phone.State.RINGING) {
s = Phone.State.RINGING;
} else if (phone.getState() == Phone.State.OFFHOOK) {
if (s == Phone.State.IDLE) s = Phone.State.OFFHOOK;
@@ -246,25 +284,50 @@ public final class CallManager {
/**
* Register phone to CallManager
- * @param phone
+ * @param phone to be registered
* @return true if register successfully
*/
public boolean registerPhone(Phone phone) {
- if (phone != null && !mPhones.contains(phone)) {
+ Phone basePhone = getPhoneBase(phone);
+
+ if (basePhone != null && !mPhones.contains(basePhone)) {
if (mPhones.isEmpty()) {
- mDefaultPhone = phone;
+ mDefaultPhone = basePhone;
}
- mPhones.add(phone);
- mRingingCalls.add(phone.getRingingCall());
- mBackgroundCalls.add(phone.getBackgroundCall());
- mForegroundCalls.add(phone.getForegroundCall());
- registerForPhoneStates(phone);
+ mPhones.add(basePhone);
+ mRingingCalls.add(basePhone.getRingingCall());
+ mBackgroundCalls.add(basePhone.getBackgroundCall());
+ mForegroundCalls.add(basePhone.getForegroundCall());
+ registerForPhoneStates(basePhone);
return true;
}
return false;
}
/**
+ * unregister phone from CallManager
+ * @param phone to be unregistered
+ */
+ public void unregisterPhone(Phone phone) {
+ Phone basePhone = getPhoneBase(phone);
+
+ if (basePhone != null && mPhones.contains(basePhone)) {
+ mPhones.remove(basePhone);
+ mRingingCalls.remove(basePhone.getRingingCall());
+ mBackgroundCalls.remove(basePhone.getBackgroundCall());
+ mForegroundCalls.remove(basePhone.getForegroundCall());
+ unregisterForPhoneStates(basePhone);
+ if (basePhone == mDefaultPhone) {
+ if (mPhones.isEmpty()) {
+ mDefaultPhone = null;
+ } else {
+ mDefaultPhone = mPhones.get(0);
+ }
+ }
+ }
+ }
+
+ /**
* return the default phone or null if no phone available
*/
public Phone getDefaultPhone() {
@@ -292,39 +355,6 @@ public final class CallManager {
return getFirstActiveRingingCall().getPhone();
}
- /**
- * @return the first answering call
- */
- public Call getFirstAnsweringCall() {
- for (Phone phone : mPhones) {
- if (phone.getState() == Phone.State.ANSWERING) {
- return phone.getForegroundCall();
- }
- }
- return null;
- }
-
- /**
- * unregister phone from CallManager
- * @param phone
- */
- public void unregisterPhone(Phone phone) {
- if (phone != null && mPhones.contains(phone)) {
- mPhones.remove(phone);
- mRingingCalls.remove(phone.getRingingCall());
- mBackgroundCalls.remove(phone.getBackgroundCall());
- mForegroundCalls.remove(phone.getForegroundCall());
- unregisterForPhoneStates(phone);
- if (phone == mDefaultPhone) {
- if (mPhones.isEmpty()) {
- mDefaultPhone = null;
- } else {
- mDefaultPhone = mPhones.get(0);
- }
- }
- }
- }
-
public void setAudioMode() {
Context context = getContext();
if (context == null) return;
@@ -592,8 +622,9 @@ public final class CallManager {
* handled asynchronously.
*/
public Connection dial(Phone phone, String dialString) throws CallStateException {
+ Phone basePhone = getPhoneBase(phone);
if (VDBG) {
- Log.d(LOG_TAG, "CallManager.dial( phone=" + phone + ", dialString="+ dialString + ")");
+ Log.d(LOG_TAG, "CallManager.dial( phone=" + basePhone + ", dialString="+ dialString + ")");
Log.d(LOG_TAG, this.toString());
}
if ( hasActiveFgCall() ) {
@@ -601,10 +632,10 @@ public final class CallManager {
boolean hasBgCall = !(activePhone.getBackgroundCall().isIdle());
if (DBG) {
- Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + " sameChannel:" + (activePhone == phone));
+ Log.d(LOG_TAG, "hasBgCall: "+ hasBgCall + " sameChannel:" + (activePhone == basePhone));
}
- if (activePhone != phone) {
+ if (activePhone != basePhone) {
if (hasBgCall) {
Log.d(LOG_TAG, "Hangup");
getActiveFgCall().hangup();
@@ -614,7 +645,7 @@ public final class CallManager {
}
}
}
- return phone.dial(dialString);
+ return basePhone.dial(dialString);
}
/**
@@ -1312,7 +1343,7 @@ public final class CallManager {
*/
public Call getFirstActiveBgCall() {
for (Call call : mBackgroundCalls) {
- if (!call.isIdle()) {
+ if (call.getState() != Call.State.IDLE) {
return call;
}
}
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index 7464cc74ac3b..9afade33b006 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -55,12 +55,10 @@ public interface Phone {
* <li>OFFHOOK = The phone is off hook. At least one call
* exists that is dialing, active or holding and no calls are
* ringing or waiting.</li>
- * <li>ANSWERING = The incoming call is picked up but the
- * call is not established yet.</li>
* </ul>
*/
enum State {
- IDLE, RINGING, OFFHOOK, ANSWERING;
+ IDLE, RINGING, OFFHOOK;
};
/**
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
index 0a87ddbc3bac..35aa3b383a58 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
@@ -143,23 +143,15 @@ public class SipPhone extends SipPhoneBase {
// in case the active/holding call disappeared and this
// is no longer call waiting
- if (ringingCall.getState() == Call.State.INCOMING) {
+ if ((ringingCall.getState() == Call.State.INCOMING) ||
+ (ringingCall.getState() == Call.State.WAITING)) {
Log.v(LOG_TAG, "acceptCall");
// Always unmute when answering a new call
setMute(false);
- // make ringingCall foreground
- foregroundCall.switchWith(ringingCall);
- foregroundCall.acceptCall();
- } else if (ringingCall.getState() == Call.State.WAITING) {
- setMute(false);
- switchHoldingAndActive();
- // make ringingCall foreground
- foregroundCall.switchWith(ringingCall);
- foregroundCall.acceptCall();
+ ringingCall.acceptCall();
} else {
throw new CallStateException("phone not ringing");
}
- updatePhoneState();
}
}
@@ -482,8 +474,8 @@ public class SipPhone extends SipPhoneBase {
}
void acceptCall() throws CallStateException {
- if (this != foregroundCall) {
- throw new CallStateException("acceptCall() in a non-fg call");
+ if (this != ringingCall) {
+ throw new CallStateException("acceptCall() in a non-ringing call");
}
if (connections.size() != 1) {
throw new CallStateException("acceptCall() in a conf call");
@@ -646,6 +638,18 @@ public class SipPhone extends SipPhoneBase {
if (newState == Call.State.INCOMING) {
setState(mOwner.getState()); // INCOMING or WAITING
} else {
+ if (mOwner == ringingCall) {
+ if (ringingCall.getState() == Call.State.WAITING) {
+ try {
+ switchHoldingAndActive();
+ } catch (CallStateException e) {
+ // disconnect the call.
+ onCallEnded(DisconnectCause.LOCAL);
+ return;
+ }
+ }
+ foregroundCall.switchWith(ringingCall);
+ }
if (newState == Call.State.ACTIVE) call.startAudio();
setState(newState);
}
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
index 2efbd175bc0e..9098e6ffb154 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhoneBase.java
@@ -538,8 +538,6 @@ abstract class SipPhoneBase extends PhoneBase {
if (getRingingCall().isRinging()) {
state = State.RINGING;
- } else if (getForegroundCall().isRinging()) {
- state = State.ANSWERING;
} else if (getForegroundCall().isIdle()
&& getBackgroundCall().isIdle()) {
state = State.IDLE;
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 0ee559e7c228..198b1e6b44d6 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -42,7 +42,7 @@ interface IWifiManager
boolean pingSupplicant();
- boolean startScan(boolean forceActive);
+ void startScan(boolean forceActive);
List<ScanResult> getScanResults();
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index dd162f212cbd..f8835881347a 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -570,7 +570,8 @@ public class WifiManager {
*/
public boolean startScan() {
try {
- return mService.startScan(false);
+ mService.startScan(false);
+ return true;
} catch (RemoteException e) {
return false;
}
@@ -588,7 +589,8 @@ public class WifiManager {
*/
public boolean startScanActive() {
try {
- return mService.startScan(true);
+ mService.startScan(true);
+ return true;
} catch (RemoteException e) {
return false;
}