Merge "Several improvements to RecentActivities:"
diff --git a/api/current.xml b/api/current.xml
index 06eeba7..7e7131b 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -6829,6 +6829,17 @@
visibility="public"
>
</field>
+<field name="listDividerAlertDialog"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843590"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="listPopupWindowStyle"
type="int"
transient="false"
@@ -9876,6 +9887,17 @@
visibility="public"
>
</field>
+<field name="textColorAlertDialogListItem"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843591"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="textColorHighlight"
type="int"
transient="false"
@@ -26663,6 +26685,17 @@
visibility="public"
>
</method>
+<method name="getContext"
+ return="android.content.Context"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="setAdapter"
return="android.app.AlertDialog.Builder"
abstract="false"
@@ -28621,6 +28654,623 @@
>
</field>
</class>
+<class name="DownloadManager"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="enqueue"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="request" type="android.app.DownloadManager.Request">
+</parameter>
+</method>
+<method name="openDownloadedFile"
+ return="android.os.ParcelFileDescriptor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="long">
+</parameter>
+<exception name="FileNotFoundException" type="java.io.FileNotFoundException">
+</exception>
+</method>
+<method name="query"
+ return="android.database.Cursor"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="query" type="android.app.DownloadManager.Query">
+</parameter>
+</method>
+<method name="remove"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="long">
+</parameter>
+</method>
+<field name="ACTION_DOWNLOAD_COMPLETE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.intent.action.DOWNLOAD_COMPLETE""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_NOTIFICATION_CLICKED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ACTION_VIEW_DOWNLOADS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.intent.action.VIEW_DOWNLOADS""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="COLUMN_BYTES_DOWNLOADED_SO_FAR"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""bytes_so_far""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="COLUMN_DESCRIPTION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""description""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="COLUMN_ERROR_CODE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""error_code""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="COLUMN_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""_id""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="COLUMN_LAST_MODIFIED_TIMESTAMP"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""last_modified_timestamp""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="COLUMN_LOCAL_URI"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""local_uri""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="COLUMN_MEDIA_TYPE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""media_type""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="COLUMN_STATUS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""status""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="COLUMN_TITLE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""title""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="COLUMN_TOTAL_SIZE_BYTES"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""total_size""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="COLUMN_URI"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""uri""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_CANNOT_RESUME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1008"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_DEVICE_NOT_FOUND"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1007"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ 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"
+ volatile="false"
+ value="1001"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_HTTP_DATA_ERROR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1004"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_INSUFFICIENT_SPACE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1006"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_TOO_MANY_REDIRECTS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1005"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_UNHANDLED_HTTP_CODE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1002"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ERROR_UNKNOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1000"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_DOWNLOAD_ID"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""extra_download_id""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_FAILED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_PAUSED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_PENDING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_RUNNING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="STATUS_SUCCESSFUL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="DownloadManager.Query"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DownloadManager.Query"
+ type="android.app.DownloadManager.Query"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="setFilterById"
+ return="android.app.DownloadManager.Query"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="id" type="long">
+</parameter>
+</method>
+<method name="setFilterByStatus"
+ return="android.app.DownloadManager.Query"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+</class>
+<class name="DownloadManager.Request"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="DownloadManager.Request"
+ type="android.app.DownloadManager.Request"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</constructor>
+<method name="addRequestHeader"
+ return="android.app.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="header" type="java.lang.String">
+</parameter>
+<parameter name="value" type="java.lang.String">
+</parameter>
+</method>
+<method name="setAllowedNetworkTypes"
+ return="android.app.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<method name="setAllowedOverRoaming"
+ return="android.app.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="allowed" type="boolean">
+</parameter>
+</method>
+<method name="setDescription"
+ return="android.app.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="description" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setDestinationInExternalFilesDir"
+ return="android.app.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="dirType" type="java.lang.String">
+</parameter>
+<parameter name="subPath" type="java.lang.String">
+</parameter>
+</method>
+<method name="setDestinationInExternalPublicDir"
+ return="android.app.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dirType" type="java.lang.String">
+</parameter>
+<parameter name="subPath" type="java.lang.String">
+</parameter>
+</method>
+<method name="setDestinationUri"
+ return="android.app.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+</method>
+<method name="setMimeType"
+ return="android.app.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mimeType" type="java.lang.String">
+</parameter>
+</method>
+<method name="setShowRunningNotification"
+ return="android.app.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.app.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="title" type="java.lang.CharSequence">
+</parameter>
+</method>
+<method name="setVisibleInDownloadsUi"
+ return="android.app.DownloadManager.Request"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="isVisible" type="boolean">
+</parameter>
+</method>
+<field name="NETWORK_MOBILE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NETWORK_WIFI"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
<class name="ExpandableListActivity"
extends="android.app.Activity"
abstract="false"
@@ -59844,6 +60494,118 @@
>
</field>
</class>
+<class name="ObbInfo"
+ 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="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="parcelableFlags" 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>
+<field name="OBB_OVERLAY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="flags"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="packageName"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="version"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="ObbScanner"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getObbInfo"
+ return="android.content.res.ObbInfo"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filePath" type="java.lang.String">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+</class>
<class name="Resources"
extends="java.lang.Object"
abstract="false"
@@ -105874,623 +106636,6 @@
>
</field>
</class>
-<class name="DownloadManager"
- extends="java.lang.Object"
- abstract="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="enqueue"
- return="long"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="request" type="android.net.DownloadManager.Request">
-</parameter>
-</method>
-<method name="openDownloadedFile"
- return="android.os.ParcelFileDescriptor"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="id" type="long">
-</parameter>
-<exception name="FileNotFoundException" type="java.io.FileNotFoundException">
-</exception>
-</method>
-<method name="query"
- return="android.database.Cursor"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="query" type="android.net.DownloadManager.Query">
-</parameter>
-</method>
-<method name="remove"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="id" type="long">
-</parameter>
-</method>
-<field name="ACTION_DOWNLOAD_COMPLETE"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.intent.action.DOWNLOAD_COMPLETE""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ACTION_NOTIFICATION_CLICKED"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ACTION_VIEW_DOWNLOADS"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""android.intent.action.VIEW_DOWNLOADS""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="COLUMN_BYTES_DOWNLOADED_SO_FAR"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""bytes_so_far""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="COLUMN_DESCRIPTION"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""description""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="COLUMN_ERROR_CODE"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""error_code""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="COLUMN_ID"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""_id""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="COLUMN_LAST_MODIFIED_TIMESTAMP"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""last_modified_timestamp""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="COLUMN_LOCAL_URI"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""local_uri""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="COLUMN_MEDIA_TYPE"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""media_type""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="COLUMN_STATUS"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""status""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="COLUMN_TITLE"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""title""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="COLUMN_TOTAL_SIZE_BYTES"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""total_size""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="COLUMN_URI"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""uri""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ERROR_CANNOT_RESUME"
- type="int"
- transient="false"
- volatile="false"
- value="1008"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ERROR_DEVICE_NOT_FOUND"
- type="int"
- transient="false"
- volatile="false"
- value="1007"
- static="true"
- final="true"
- deprecated="not deprecated"
- 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"
- volatile="false"
- value="1001"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ERROR_HTTP_DATA_ERROR"
- type="int"
- transient="false"
- volatile="false"
- value="1004"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ERROR_INSUFFICIENT_SPACE"
- type="int"
- transient="false"
- volatile="false"
- value="1006"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ERROR_TOO_MANY_REDIRECTS"
- type="int"
- transient="false"
- volatile="false"
- value="1005"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ERROR_UNHANDLED_HTTP_CODE"
- type="int"
- transient="false"
- volatile="false"
- value="1002"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="ERROR_UNKNOWN"
- type="int"
- transient="false"
- volatile="false"
- value="1000"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="EXTRA_DOWNLOAD_ID"
- type="java.lang.String"
- transient="false"
- volatile="false"
- value=""extra_download_id""
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="STATUS_FAILED"
- type="int"
- transient="false"
- volatile="false"
- value="16"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="STATUS_PAUSED"
- type="int"
- transient="false"
- volatile="false"
- value="4"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="STATUS_PENDING"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="STATUS_RUNNING"
- type="int"
- transient="false"
- volatile="false"
- value="2"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="STATUS_SUCCESSFUL"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
-<class name="DownloadManager.Query"
- extends="java.lang.Object"
- abstract="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="DownloadManager.Query"
- type="android.net.DownloadManager.Query"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="setFilterById"
- return="android.net.DownloadManager.Query"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="id" type="long">
-</parameter>
-</method>
-<method name="setFilterByStatus"
- return="android.net.DownloadManager.Query"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="flags" type="int">
-</parameter>
-</method>
-</class>
-<class name="DownloadManager.Request"
- extends="java.lang.Object"
- abstract="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<constructor name="DownloadManager.Request"
- type="android.net.DownloadManager.Request"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="uri" type="android.net.Uri">
-</parameter>
-</constructor>
-<method name="addRequestHeader"
- return="android.net.DownloadManager.Request"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="header" type="java.lang.String">
-</parameter>
-<parameter name="value" type="java.lang.String">
-</parameter>
-</method>
-<method name="setAllowedNetworkTypes"
- return="android.net.DownloadManager.Request"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="flags" type="int">
-</parameter>
-</method>
-<method name="setAllowedOverRoaming"
- return="android.net.DownloadManager.Request"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="allowed" type="boolean">
-</parameter>
-</method>
-<method name="setDescription"
- return="android.net.DownloadManager.Request"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="description" type="java.lang.CharSequence">
-</parameter>
-</method>
-<method name="setDestinationInExternalFilesDir"
- return="android.net.DownloadManager.Request"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="context" type="android.content.Context">
-</parameter>
-<parameter name="dirType" type="java.lang.String">
-</parameter>
-<parameter name="subPath" type="java.lang.String">
-</parameter>
-</method>
-<method name="setDestinationInExternalPublicDir"
- return="android.net.DownloadManager.Request"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="dirType" type="java.lang.String">
-</parameter>
-<parameter name="subPath" type="java.lang.String">
-</parameter>
-</method>
-<method name="setDestinationUri"
- return="android.net.DownloadManager.Request"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="uri" type="android.net.Uri">
-</parameter>
-</method>
-<method name="setMimeType"
- return="android.net.DownloadManager.Request"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="mimeType" 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"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="title" type="java.lang.CharSequence">
-</parameter>
-</method>
-<method name="setVisibleInDownloadsUi"
- return="android.net.DownloadManager.Request"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="isVisible" type="boolean">
-</parameter>
-</method>
-<field name="NETWORK_MOBILE"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="NETWORK_WIFI"
- type="int"
- transient="false"
- volatile="false"
- value="2"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-</class>
<class name="LocalServerSocket"
extends="java.lang.Object"
abstract="false"
@@ -139637,6 +139782,38 @@
</package>
<package name="android.os.storage"
>
+<class name="OnObbStateChangeListener"
+ extends="java.lang.Object"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="OnObbStateChangeListener"
+ type="android.os.storage.OnObbStateChangeListener"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="onObbStateChange"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="java.lang.String">
+</parameter>
+<parameter name="state" type="java.lang.String">
+</parameter>
+</method>
+</class>
<class name="StorageEventListener"
extends="java.lang.Object"
abstract="true"
@@ -139778,6 +139955,8 @@
</parameter>
<parameter name="key" type="java.lang.String">
</parameter>
+<parameter name="listener" type="android.os.storage.OnObbStateChangeListener">
+</parameter>
</method>
<method name="registerListener"
return="void"
@@ -139806,6 +139985,8 @@
</parameter>
<parameter name="force" type="boolean">
</parameter>
+<parameter name="listener" type="android.os.storage.OnObbStateChangeListener">
+</parameter>
<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
</exception>
</method>
@@ -155577,6 +155758,17 @@
visibility="public"
>
</field>
+<field name="ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="ACTION_MANAGE_APPLICATIONS_SETTINGS"
type="java.lang.String"
transient="false"
@@ -240953,7 +241145,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="t" type="T">
+<parameter name="arg0" type="T">
</parameter>
</method>
</interface>
@@ -305857,7 +306049,7 @@
>
<parameter name="parameterName" type="java.lang.String">
</parameter>
-<parameter name="x" type="java.sql.Blob">
+<parameter name="blob" type="java.sql.Blob">
</parameter>
<exception name="SQLException" type="java.sql.SQLException">
</exception>
@@ -306016,7 +306208,7 @@
>
<parameter name="parameterName" type="java.lang.String">
</parameter>
-<parameter name="x" type="java.sql.Clob">
+<parameter name="clob" type="java.sql.Clob">
</parameter>
<exception name="SQLException" type="java.sql.SQLException">
</exception>
@@ -306154,7 +306346,7 @@
>
<parameter name="parameterName" type="java.lang.String">
</parameter>
-<parameter name="value" type="java.io.Reader">
+<parameter name="reader" type="java.io.Reader">
</parameter>
<parameter name="length" type="long">
</parameter>
@@ -306190,7 +306382,7 @@
>
<parameter name="parameterName" type="java.lang.String">
</parameter>
-<parameter name="value" type="java.sql.NClob">
+<parameter name="nclob" type="java.sql.NClob">
</parameter>
<exception name="SQLException" type="java.sql.SQLException">
</exception>
@@ -306243,7 +306435,7 @@
>
<parameter name="parameterName" type="java.lang.String">
</parameter>
-<parameter name="value" type="java.lang.String">
+<parameter name="string" type="java.lang.String">
</parameter>
<exception name="SQLException" type="java.sql.SQLException">
</exception>
@@ -306353,7 +306545,7 @@
>
<parameter name="parameterName" type="java.lang.String">
</parameter>
-<parameter name="x" type="java.sql.RowId">
+<parameter name="rowId" type="java.sql.RowId">
</parameter>
<exception name="SQLException" type="java.sql.SQLException">
</exception>
@@ -306370,7 +306562,7 @@
>
<parameter name="parameterName" type="java.lang.String">
</parameter>
-<parameter name="xmlObject" type="java.sql.SQLXML">
+<parameter name="sqlXml" type="java.sql.SQLXML">
</parameter>
<exception name="SQLException" type="java.sql.SQLException">
</exception>
@@ -311506,7 +311698,7 @@
>
<parameter name="parameterIndex" type="int">
</parameter>
-<parameter name="x" type="java.io.InputStream">
+<parameter name="inputStream" type="java.io.InputStream">
</parameter>
<parameter name="length" type="long">
</parameter>
@@ -311525,7 +311717,7 @@
>
<parameter name="parameterIndex" type="int">
</parameter>
-<parameter name="x" type="java.io.InputStream">
+<parameter name="inputStream" type="java.io.InputStream">
</parameter>
<exception name="SQLException" type="java.sql.SQLException">
</exception>
@@ -311578,7 +311770,7 @@
>
<parameter name="parameterIndex" type="int">
</parameter>
-<parameter name="x" type="java.io.InputStream">
+<parameter name="inputStream" type="java.io.InputStream">
</parameter>
<parameter name="length" type="long">
</parameter>
@@ -311597,7 +311789,7 @@
>
<parameter name="parameterIndex" type="int">
</parameter>
-<parameter name="x" type="java.io.InputStream">
+<parameter name="inputStream" type="java.io.InputStream">
</parameter>
<exception name="SQLException" type="java.sql.SQLException">
</exception>
@@ -311930,7 +312122,7 @@
>
<parameter name="parameterIndex" type="int">
</parameter>
-<parameter name="value" type="java.io.Reader">
+<parameter name="reader" type="java.io.Reader">
</parameter>
<parameter name="length" type="long">
</parameter>
@@ -311949,7 +312141,7 @@
>
<parameter name="parameterIndex" type="int">
</parameter>
-<parameter name="value" type="java.io.Reader">
+<parameter name="reader" type="java.io.Reader">
</parameter>
<exception name="SQLException" type="java.sql.SQLException">
</exception>
@@ -312019,7 +312211,7 @@
>
<parameter name="parameterIndex" type="int">
</parameter>
-<parameter name="value" type="java.lang.String">
+<parameter name="theString" type="java.lang.String">
</parameter>
<exception name="SQLException" type="java.sql.SQLException">
</exception>
@@ -312146,7 +312338,7 @@
>
<parameter name="parameterIndex" type="int">
</parameter>
-<parameter name="x" type="java.sql.RowId">
+<parameter name="theRowId" type="java.sql.RowId">
</parameter>
<exception name="SQLException" type="java.sql.SQLException">
</exception>
@@ -315140,7 +315332,7 @@
>
<parameter name="columnIndex" type="int">
</parameter>
-<parameter name="x" type="java.sql.RowId">
+<parameter name="value" type="java.sql.RowId">
</parameter>
<exception name="SQLException" type="java.sql.SQLException">
</exception>
@@ -315157,7 +315349,7 @@
>
<parameter name="columnLabel" type="java.lang.String">
</parameter>
-<parameter name="x" type="java.sql.RowId">
+<parameter name="value" type="java.sql.RowId">
</parameter>
<exception name="SQLException" type="java.sql.SQLException">
</exception>
@@ -317489,7 +317681,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="x" type="java.sql.NClob">
+<parameter name="theNClob" type="java.sql.NClob">
</parameter>
<exception name="SQLException" type="java.sql.SQLException">
</exception>
@@ -317504,7 +317696,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="x" type="java.lang.String">
+<parameter name="theString" type="java.lang.String">
</parameter>
<exception name="SQLException" type="java.sql.SQLException">
</exception>
@@ -317549,7 +317741,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="x" type="java.sql.RowId">
+<parameter name="theRowId" type="java.sql.RowId">
</parameter>
<exception name="SQLException" type="java.sql.SQLException">
</exception>
@@ -317564,7 +317756,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="x" type="java.sql.SQLXML">
+<parameter name="theXml" type="java.sql.SQLXML">
</parameter>
<exception name="SQLException" type="java.sql.SQLException">
</exception>
diff --git a/cmds/servicemanager/service_manager.c b/cmds/servicemanager/service_manager.c
index a57a72f..d380a27 100644
--- a/cmds/servicemanager/service_manager.c
+++ b/cmds/servicemanager/service_manager.c
@@ -42,6 +42,7 @@
{ AID_RADIO, "radio.simphonebook" },
/* TODO: remove after phone services are updated: */
{ AID_RADIO, "phone" },
+ { AID_RADIO, "sip" },
{ AID_RADIO, "isms" },
{ AID_RADIO, "iphonesubinfo" },
{ AID_RADIO, "simphonebook" },
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 8b54871..f55b746 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -46,6 +46,7 @@
#include <media/mediametadataretriever.h>
#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/MPEG2TSWriter.h>
#include <media/stagefright/MPEG4Writer.h>
#include <fcntl.h>
@@ -366,8 +367,13 @@
static void writeSourcesToMP4(
Vector<sp<MediaSource> > &sources, bool syncInfoPresent) {
+#if 0
sp<MPEG4Writer> writer =
new MPEG4Writer(gWriteMP4Filename.string());
+#else
+ sp<MPEG2TSWriter> writer =
+ new MPEG2TSWriter(gWriteMP4Filename.string());
+#endif
// at most one minute.
writer->setMaxFileDuration(60000000ll);
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 73e8d31..b558318 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1297,7 +1297,16 @@
reply.writeNoException();
return true;
}
-
+
+ case GET_PROVIDER_MIME_TYPE_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ Uri uri = Uri.CREATOR.createFromParcel(data);
+ String type = getProviderMimeType(uri);
+ reply.writeNoException();
+ reply.writeString(type);
+ return true;
+ }
+
case NEW_URI_PERMISSION_OWNER_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
String name = data.readString();
@@ -2926,6 +2935,20 @@
reply.recycle();
}
+ public String getProviderMimeType(Uri uri)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ uri.writeToParcel(data, 0);
+ mRemote.transact(GET_PROVIDER_MIME_TYPE_TRANSACTION, data, reply, 0);
+ reply.readException();
+ String res = reply.readString();
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
+
public IBinder newUriPermissionOwner(String name)
throws RemoteException {
Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 2ff88da..b8bbc88 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3377,12 +3377,20 @@
}
}
- private final IContentProvider getProvider(Context context, String name) {
+ private final IContentProvider getExistingProvider(Context context, String name) {
synchronized(mProviderMap) {
final ProviderClientRecord pr = mProviderMap.get(name);
if (pr != null) {
return pr.mProvider;
}
+ return null;
+ }
+ }
+
+ private final IContentProvider getProvider(Context context, String name) {
+ IContentProvider existing = getExistingProvider(context, name);
+ if (existing != null) {
+ return existing;
}
IActivityManager.ContentProviderHolder holder = null;
@@ -3427,6 +3435,22 @@
return provider;
}
+ public final IContentProvider acquireExistingProvider(Context c, String name) {
+ IContentProvider provider = getExistingProvider(c, name);
+ if(provider == null)
+ return null;
+ IBinder jBinder = provider.asBinder();
+ synchronized(mProviderMap) {
+ ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
+ if(prc == null) {
+ mProviderRefCountMap.put(jBinder, new ProviderRefCount(1));
+ } else {
+ prc.count++;
+ } //end else
+ } //end synchronized
+ return provider;
+ }
+
public final boolean releaseProvider(IContentProvider provider) {
if(provider == null) {
return false;
@@ -3435,7 +3459,7 @@
synchronized(mProviderMap) {
ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
if(prc == null) {
- if(localLOGV) Slog.v(TAG, "releaseProvider::Weird shouldnt be here");
+ if(localLOGV) Slog.v(TAG, "releaseProvider::Weird shouldn't be here");
return false;
} else {
prc.count--;
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index 61a8fc3..f0477e5 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -16,12 +16,16 @@
package android.app;
+import com.android.internal.app.AlertController;
+
import android.content.Context;
import android.content.DialogInterface;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.os.Bundle;
import android.os.Message;
+import android.view.ContextThemeWrapper;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
@@ -30,8 +34,6 @@
import android.widget.ListAdapter;
import android.widget.ListView;
-import com.android.internal.app.AlertController;
-
/**
* A subclass of Dialog that can display one, two or three buttons. If you only want to
* display a String in this dialog box, use the setMessage() method. If you
@@ -56,7 +58,10 @@
private AlertController mAlert;
protected AlertDialog(Context context) {
- this(context, com.android.internal.R.style.Theme_Dialog_Alert);
+ this(context,
+ context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB
+ ? com.android.internal.R.style.Theme_Holo_Dialog_Alert
+ : com.android.internal.R.style.Theme_Dialog_Alert);
}
protected AlertDialog(Context context, int theme) {
@@ -65,7 +70,10 @@
}
protected AlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
- super(context, com.android.internal.R.style.Theme_Dialog_Alert);
+ super(context,
+ context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB
+ ? com.android.internal.R.style.Theme_Holo_Dialog_Alert
+ : com.android.internal.R.style.Theme_Dialog_Alert);
setCancelable(cancelable);
setOnCancelListener(cancelListener);
mAlert = new AlertController(context, this, getWindow());
@@ -266,12 +274,16 @@
public static class Builder {
private final AlertController.AlertParams P;
private int mTheme;
+ private Context mWrappedContext;
/**
* Constructor using a context for this builder and the {@link AlertDialog} it creates.
*/
public Builder(Context context) {
- this(context, com.android.internal.R.style.Theme_Dialog_Alert);
+ this(context,
+ context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB
+ ? com.android.internal.R.style.Theme_Holo_Dialog_Alert
+ : com.android.internal.R.style.Theme_Dialog_Alert);
}
/**
@@ -284,6 +296,21 @@
}
/**
+ * Returns a {@link Context} with the appropriate theme for dialogs created by this Builder.
+ * Applications should use this Context for obtaining LayoutInflaters for inflating views
+ * that will be used in the resulting dialogs, as it will cause views to be inflated with
+ * the correct theme.
+ *
+ * @return A Context for built Dialogs.
+ */
+ public Context getContext() {
+ if (mWrappedContext == null) {
+ mWrappedContext = new ContextThemeWrapper(P.mContext, mTheme);
+ }
+ return mWrappedContext;
+ }
+
+ /**
* Set the title using the given resource id.
*
* @return This Builder object to allow for chaining of calls to set methods
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 7497136..3174f55 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -69,13 +69,13 @@
import android.media.AudioManager;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
-import android.net.DownloadManager;
import android.net.ThrottleManager;
import android.net.IThrottleManager;
import android.net.Uri;
import android.net.wifi.IWifiManager;
import android.net.wifi.WifiManager;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.DropBoxManager;
import android.os.Environment;
@@ -1063,8 +1063,13 @@
private NotificationManager getNotificationManager() {
synchronized (mSync) {
if (mNotificationManager == null) {
+ final Context outerContext = getOuterContext();
mNotificationManager = new NotificationManager(
- new ContextThemeWrapper(getOuterContext(), com.android.internal.R.style.Theme_Dialog),
+ new ContextThemeWrapper(outerContext,
+ outerContext.getApplicationInfo().targetSdkVersion >=
+ Build.VERSION_CODES.HONEYCOMB
+ ? com.android.internal.R.style.Theme_Holo_Dialog
+ : com.android.internal.R.style.Theme_Dialog),
mMainThread.getHandler());
}
}
@@ -1632,22 +1637,23 @@
// ----------------------------------------------------------------------
private static final class ApplicationContentResolver extends ContentResolver {
- public ApplicationContentResolver(Context context,
- ActivityThread mainThread)
- {
+ public ApplicationContentResolver(Context context, ActivityThread mainThread) {
super(context);
mMainThread = mainThread;
}
@Override
- protected IContentProvider acquireProvider(Context context, String name)
- {
+ protected IContentProvider acquireProvider(Context context, String name) {
return mMainThread.acquireProvider(context, name);
}
@Override
- public boolean releaseProvider(IContentProvider provider)
- {
+ protected IContentProvider acquireExistingProvider(Context context, String name) {
+ return mMainThread.acquireExistingProvider(context, name);
+ }
+
+ @Override
+ public boolean releaseProvider(IContentProvider provider) {
return mMainThread.releaseProvider(provider);
}
diff --git a/core/java/android/app/DatePickerDialog.java b/core/java/android/app/DatePickerDialog.java
index 8ba480d..37f8738 100644
--- a/core/java/android/app/DatePickerDialog.java
+++ b/core/java/android/app/DatePickerDialog.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
+import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils.TruncateAt;
import android.view.LayoutInflater;
@@ -82,7 +83,9 @@
int year,
int monthOfYear,
int dayOfMonth) {
- this(context, com.android.internal.R.style.Theme_Dialog_Alert,
+ this(context, context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB
+ ? com.android.internal.R.style.Theme_Holo_Dialog_Alert
+ : com.android.internal.R.style.Theme_Dialog_Alert,
callBack, year, monthOfYear, dayOfMonth);
}
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index a0be0cd..a178c04 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -25,6 +25,7 @@
import android.content.DialogInterface;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -140,7 +141,10 @@
*/
public Dialog(Context context, int theme) {
mContext = new ContextThemeWrapper(
- context, theme == 0 ? com.android.internal.R.style.Theme_Dialog : theme);
+ context, theme == 0 ?
+ (context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB
+ ? com.android.internal.R.style.Theme_Holo_Dialog
+ : com.android.internal.R.style.Theme_Dialog) : theme);
mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
Window w = PolicyManager.makeNewWindow(mContext);
mWindow = w;
@@ -173,7 +177,7 @@
/**
* Retrieve the Context this Dialog is running in.
*
- * @return Context The Context that was supplied to the constructor.
+ * @return Context The Context used by the Dialog.
*/
public final Context getContext() {
return mContext;
diff --git a/core/java/android/app/DialogFragment.java b/core/java/android/app/DialogFragment.java
index e8dfac9..8e2389b 100644
--- a/core/java/android/app/DialogFragment.java
+++ b/core/java/android/app/DialogFragment.java
@@ -199,7 +199,7 @@
public void setStyle(int style, int theme) {
mStyle = style;
if (mStyle == STYLE_NO_FRAME || mStyle == STYLE_NO_INPUT) {
- mTheme = android.R.style.Theme_Dialog_NoFrame;
+ mTheme = com.android.internal.R.style.Theme_Holo_Dialog_NoFrame;
}
if (theme != 0) {
mTheme = theme;
diff --git a/core/java/android/net/DownloadManager.java b/core/java/android/app/DownloadManager.java
similarity index 99%
rename from core/java/android/net/DownloadManager.java
rename to core/java/android/app/DownloadManager.java
index 3279e8f..69c99cc 100644
--- a/core/java/android/net/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.net;
+package android.app;
import android.content.ContentResolver;
import android.content.ContentUris;
@@ -22,6 +22,8 @@
import android.content.Context;
import android.database.Cursor;
import android.database.CursorWrapper;
+import android.net.ConnectivityManager;
+import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.provider.BaseColumns;
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 901f117..4d73817 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -317,6 +317,8 @@
public void crashApplication(int uid, int initialPid, String packageName,
String message) throws RemoteException;
+
+ public String getProviderMimeType(Uri uri) throws RemoteException;
public IBinder newUriPermissionOwner(String name) throws RemoteException;
public void grantUriPermissionFromOwner(IBinder owner, int fromUid, String targetPkg,
@@ -534,8 +536,9 @@
int SET_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+111;
int IS_TOP_ACTIVITY_IMMERSIVE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+112;
int CRASH_APPLICATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+113;
- int NEW_URI_PERMISSION_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+114;
- int GRANT_URI_PERMISSION_FROM_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+115;
- int REVOKE_URI_PERMISSION_FROM_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+116;
- int DUMP_HEAP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+117;
+ int GET_PROVIDER_MIME_TYPE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+114;
+ int NEW_URI_PERMISSION_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+115;
+ int GRANT_URI_PERMISSION_FROM_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+116;
+ int REVOKE_URI_PERMISSION_FROM_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+117;
+ int DUMP_HEAP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+118;
}
diff --git a/core/java/android/app/ProgressDialog.java b/core/java/android/app/ProgressDialog.java
index bdea069..07a5a22 100644
--- a/core/java/android/app/ProgressDialog.java
+++ b/core/java/android/app/ProgressDialog.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.graphics.drawable.Drawable;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -73,7 +74,10 @@
private Handler mViewUpdateHandler;
public ProgressDialog(Context context) {
- this(context, com.android.internal.R.style.Theme_Dialog_Alert);
+ this(context,
+ context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB
+ ? com.android.internal.R.style.Theme_Holo_Dialog_Alert
+ : com.android.internal.R.style.Theme_Dialog_Alert);
}
public ProgressDialog(Context context, int theme) {
diff --git a/core/java/android/app/TimePickerDialog.java b/core/java/android/app/TimePickerDialog.java
index 521d41c..381143c 100644
--- a/core/java/android/app/TimePickerDialog.java
+++ b/core/java/android/app/TimePickerDialog.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
+import android.os.Build;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.view.LayoutInflater;
@@ -76,7 +77,10 @@
public TimePickerDialog(Context context,
OnTimeSetListener callBack,
int hourOfDay, int minute, boolean is24HourView) {
- this(context, com.android.internal.R.style.Theme_Dialog_Alert,
+ this(context,
+ context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB
+ ? com.android.internal.R.style.Theme_Holo_Dialog_Alert
+ : com.android.internal.R.style.Theme_Dialog_Alert,
callBack, hourOfDay, minute, is24HourView);
}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index d3c1b4e..6bb32c1 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -561,6 +561,12 @@
* <a href="{@docRoot}guide/topics/fundamentals.html#procthread">Application Fundamentals:
* Processes and Threads</a>.
*
+ * <p>Note that there are no permissions needed for an application to
+ * access this information; if your content provider requires read and/or
+ * write permissions, or is not exported, all applications can still call
+ * this method regardless of their access permissions. This allows them
+ * to retrieve the MIME type for a URI when dispatching intents.
+ *
* @param uri the URI to query.
* @return a MIME type string, or null if there is no type.
*/
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 22feb9a..3289120 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -17,6 +17,7 @@
package android.content;
import android.accounts.Account;
+import android.app.ActivityManagerNative;
import android.app.ActivityThread;
import android.app.AppGlobals;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -176,6 +177,12 @@
/** @hide */
protected abstract IContentProvider acquireProvider(Context c, String name);
+ /** Providing a default implementation of this, to avoid having to change
+ * a lot of other things, but implementations of ContentResolver should
+ * implement it. @hide */
+ protected IContentProvider acquireExistingProvider(Context c, String name) {
+ return acquireProvider(c, name);
+ }
/** @hide */
public abstract boolean releaseProvider(IContentProvider icp);
@@ -187,18 +194,28 @@
* @return A MIME type for the content, or null if the URL is invalid or the type is unknown
*/
public final String getType(Uri url) {
- IContentProvider provider = acquireProvider(url);
- if (provider == null) {
+ IContentProvider provider = acquireExistingProvider(url);
+ if (provider != null) {
+ try {
+ return provider.getType(url);
+ } catch (RemoteException e) {
+ return null;
+ } catch (java.lang.Exception e) {
+ return null;
+ } finally {
+ releaseProvider(provider);
+ }
+ }
+
+ if (!SCHEME_CONTENT.equals(url.getScheme())) {
return null;
}
+
try {
- return provider.getType(url);
+ String type = ActivityManagerNative.getDefault().getProviderMimeType(url);
+ return type;
} catch (RemoteException e) {
return null;
- } catch (java.lang.Exception e) {
- return null;
- } finally {
- releaseProvider(provider);
}
}
@@ -224,15 +241,14 @@
if (provider == null) {
return null;
}
+
try {
return provider.getStreamTypes(url, mimeTypeFilter);
} catch (RemoteException e) {
return null;
- } catch (java.lang.Exception e) {
- return null;
} finally {
- releaseProvider(provider);
- }
+ releaseProvider(provider);
+ }
}
/**
@@ -821,14 +837,13 @@
}
/**
- * Returns the content provider for the given content URI..
+ * Returns the content provider for the given content URI.
*
* @param uri The URI to a content provider
* @return The ContentProvider for the given URI, or null if no content provider is found.
* @hide
*/
- public final IContentProvider acquireProvider(Uri uri)
- {
+ public final IContentProvider acquireProvider(Uri uri) {
if (!SCHEME_CONTENT.equals(uri.getScheme())) {
return null;
}
@@ -840,6 +855,25 @@
}
/**
+ * Returns the content provider for the given content URI if the process
+ * already has a reference on it.
+ *
+ * @param uri The URI to a content provider
+ * @return The ContentProvider for the given URI, or null if no content provider is found.
+ * @hide
+ */
+ public final IContentProvider acquireExistingProvider(Uri uri) {
+ if (!SCHEME_CONTENT.equals(uri.getScheme())) {
+ return null;
+ }
+ String auth = uri.getAuthority();
+ if (auth != null) {
+ return acquireExistingProvider(mContext, uri.getAuthority());
+ }
+ return null;
+ }
+
+ /**
* @hide
*/
public final IContentProvider acquireProvider(String name) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 3d29379..3a56afb 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1235,7 +1235,7 @@
* <dt> {@link #UI_MODE_SERVICE} ("uimode")
* <dd> An {@link android.app.UiModeManager} for controlling UI modes.
* <dt> {@link #DOWNLOAD_SERVICE} ("download")
- * <dd> A {@link android.net.DownloadManager} for requesting HTTP downloads
+ * <dd> A {@link android.app.DownloadManager} for requesting HTTP downloads
* </dl>
*
* <p>Note: System services obtained via this API may be closely associated with
@@ -1284,7 +1284,7 @@
* @see #UI_MODE_SERVICE
* @see android.app.UiModeManager
* @see #DOWNLOAD_SERVICE
- * @see android.net.DownloadManager
+ * @see android.app.DownloadManager
*/
public abstract Object getSystemService(String name);
@@ -1576,7 +1576,7 @@
/**
* Use with {@link #getSystemService} to retrieve a
- * {@link android.net.DownloadManager} for requesting HTTP downloads.
+ * {@link android.app.DownloadManager} for requesting HTTP downloads.
*
* @see #getSystemService
*/
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 92a8a99..8ef639b 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -36,6 +36,7 @@
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -332,7 +333,7 @@
try {
// We must read the stream for the JarEntry to retrieve
// its certificates.
- InputStream is = jarFile.getInputStream(je);
+ InputStream is = new BufferedInputStream(jarFile.getInputStream(je));
while (is.read(readBuffer, 0, readBuffer.length) != -1) {
// not using
}
diff --git a/core/java/android/content/res/ObbInfo.java b/core/java/android/content/res/ObbInfo.java
index 838c5ff..7b962e5 100644
--- a/core/java/android/content/res/ObbInfo.java
+++ b/core/java/android/content/res/ObbInfo.java
@@ -20,9 +20,9 @@
import android.os.Parcelable;
/**
- * Basic information about a Opaque Binary Blob (OBB) that reflects
- * the info from the footer on the OBB file.
- * @hide
+ * Basic information about a Opaque Binary Blob (OBB) that reflects the info
+ * from the footer on the OBB file. This information may be manipulated by a
+ * developer with the <code>obbtool</code> program in the Android SDK.
*/
public class ObbInfo implements Parcelable {
/** Flag noting that this OBB is an overlay patch for a base OBB. */
@@ -43,7 +43,8 @@
*/
public int flags;
- public ObbInfo() {
+ // Only allow things in this package to instantiate.
+ /* package */ ObbInfo() {
}
public String toString() {
diff --git a/core/java/android/content/res/ObbScanner.java b/core/java/android/content/res/ObbScanner.java
index eb383c3..a3f141e 100644
--- a/core/java/android/content/res/ObbScanner.java
+++ b/core/java/android/content/res/ObbScanner.java
@@ -16,25 +16,43 @@
package android.content.res;
+import java.io.File;
+import java.io.IOException;
+
/**
- * Class to scan Opaque Binary Blob (OBB) files.
- * @hide
+ * Class to scan Opaque Binary Blob (OBB) files. Use this to get information
+ * about an OBB file for use in a program via {@link ObbInfo}.
*/
public class ObbScanner {
// Don't allow others to instantiate this class
private ObbScanner() {}
- public static ObbInfo getObbInfo(String filePath) {
+ /**
+ * Scan a file for OBB information.
+ *
+ * @param filePath path to the OBB file to be scanned.
+ * @return ObbInfo object information corresponding to the file path
+ * @throws IllegalArgumentException if the OBB file couldn't be found
+ * @throws IOException if the OBB file couldn't be read
+ */
+ public static ObbInfo getObbInfo(String filePath) throws IOException {
if (filePath == null) {
- return null;
+ throw new IllegalArgumentException("file path cannot be null");
}
- ObbInfo obbInfo = new ObbInfo();
- if (!getObbInfo_native(filePath, obbInfo)) {
- throw new IllegalArgumentException("Could not read OBB file: " + filePath);
+ final File obbFile = new File(filePath);
+ if (!obbFile.exists()) {
+ throw new IllegalArgumentException("OBB file does nto exist: " + filePath);
}
+
+ final String canonicalFilePath = obbFile.getCanonicalPath();
+
+ ObbInfo obbInfo = new ObbInfo();
+ getObbInfo_native(canonicalFilePath, obbInfo);
+
return obbInfo;
}
- private native static boolean getObbInfo_native(String filePath, ObbInfo obbInfo);
+ private native static void getObbInfo_native(String filePath, ObbInfo obbInfo)
+ throws IOException;
}
diff --git a/core/java/android/database/sqlite/DatabaseConnectionPool.java b/core/java/android/database/sqlite/DatabaseConnectionPool.java
index 8adc9c5..39a9d23 100644
--- a/core/java/android/database/sqlite/DatabaseConnectionPool.java
+++ b/core/java/android/database/sqlite/DatabaseConnectionPool.java
@@ -93,7 +93,7 @@
poolObj = mPool.get(0);
} else {
for (int i = 0; i < mMaxPoolSize; i++) {
- if (mPool.get(i).mDb.isSqlInStatementCache(sql)) {
+ if (mPool.get(i).mDb.isInStatementCache(sql)) {
poolObj = mPool.get(i);
break;
}
@@ -119,7 +119,7 @@
// there are free connections available. pick one
// preferably a connection caching the pre-compiled statement of the given SQL
for (int i = 0; i < poolSize; i++) {
- if (mPool.get(i).isFree() && mPool.get(i).mDb.isSqlInStatementCache(sql)) {
+ if (mPool.get(i).isFree() && mPool.get(i).mDb.isInStatementCache(sql)) {
poolObj = mPool.get(i);
break;
}
diff --git a/core/java/android/database/sqlite/SQLiteCompiledSql.java b/core/java/android/database/sqlite/SQLiteCompiledSql.java
index 588384b..6ed1a90 100644
--- a/core/java/android/database/sqlite/SQLiteCompiledSql.java
+++ b/core/java/android/database/sqlite/SQLiteCompiledSql.java
@@ -88,13 +88,9 @@
mInUse = false;
}
- /* package */ synchronized boolean isInUse() {
- return mInUse;
- }
-
/* package */ synchronized void releaseIfNotInUse() {
// if it is not in use, release its memory from the database
- if (!isInUse()) {
+ if (!mInUse) {
releaseSqlStatement();
}
}
@@ -110,7 +106,7 @@
// but if the database itself is not closed and is GC'ed, then
// all sub-objects attached to the database could end up getting GC'ed too.
// in that case, don't print any warning.
- if (!mInUse) {
+ if (mInUse) {
int len = mSqlStmt.length();
Log.w(TAG, "Releasing statement in a finalizer. Please ensure " +
"that you explicitly call close() on your cursor: " +
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 6882ea2..f0d0fb4 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -276,6 +276,7 @@
*/
// default statement-cache size per database connection ( = instance of this class)
private int mMaxSqlCacheSize = 25;
+ // guarded by itself
/* package */ final Map<String, SQLiteCompiledSql> mCompiledQueries =
new LinkedHashMap<String, SQLiteCompiledSql>(mMaxSqlCacheSize + 1, 0.75f, true) {
@Override
@@ -306,8 +307,9 @@
public static final int MAX_SQL_CACHE_SIZE = 100;
private boolean mCacheFullWarning;
- /** maintain stats about number of cache hits and misses */
+ /** Number of cache hits on this database connection. guarded by {@link #mCompiledQueries}. */
private int mNumCacheHits;
+ /** Number of cache misses on this database connection. guarded by {@link #mCompiledQueries}. */
private int mNumCacheMisses;
/** Used to find out where this object was created in case it never got closed. */
@@ -344,6 +346,9 @@
private static final String MEMORY_DB_PATH = ":memory:";
+ /** set to true if the database has attached databases */
+ private volatile boolean mHasAttachedDbs = false;
+
/** stores reference to all databases opened in the current process. */
private static ArrayList<WeakReference<SQLiteDatabase>> mActiveDatabases =
new ArrayList<WeakReference<SQLiteDatabase>>();
@@ -1048,6 +1053,9 @@
* Close the database.
*/
public void close() {
+ if (!isOpen()) {
+ return;
+ }
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.i(TAG, "closing db: " + mPath + " (connection # " + mConnectionNum);
}
@@ -1833,6 +1841,9 @@
logTimeStat(mLastSqlStatement, timeStart, GET_LOCK_LOG_PREFIX);
executeSql(sql, null);
+ if (stmtType == DatabaseUtils.STATEMENT_ATTACH) {
+ mHasAttachedDbs = true;
+ }
// Log commit statements along with the most recently executed
// SQL statement for disambiguation.
if (stmtType == DatabaseUtils.STATEMENT_COMMIT) {
@@ -2174,22 +2185,40 @@
}
}
- /* package */ boolean isSqlInStatementCache(String sql) {
+ /* package */ boolean isInStatementCache(String sql) {
synchronized (mCompiledQueries) {
return mCompiledQueries.containsKey(sql);
}
}
- private synchronized int getCacheHitNum() {
- return mNumCacheHits;
+ /* package */ void releaseCompiledSqlObj(SQLiteCompiledSql compiledSql) {
+ synchronized (mCompiledQueries) {
+ if (mCompiledQueries.containsValue(compiledSql)) {
+ // it is in cache - reset its inUse flag
+ compiledSql.release();
+ } else {
+ // it is NOT in cache. finalize it.
+ compiledSql.releaseSqlStatement();
+ }
+ }
}
- private synchronized int getCacheMissNum() {
- return mNumCacheMisses;
+ private int getCacheHitNum() {
+ synchronized(mCompiledQueries) {
+ return mNumCacheHits;
+ }
}
- private synchronized int getCachesize() {
- return mCompiledQueries.size();
+ private int getCacheMissNum() {
+ synchronized(mCompiledQueries) {
+ return mNumCacheMisses;
+ }
+ }
+
+ private int getCachesize() {
+ synchronized(mCompiledQueries) {
+ return mCompiledQueries.size();
+ }
}
/* package */ void finalizeStatementLater(int id) {
@@ -2276,7 +2305,13 @@
* @return true if write-ahead-logging is set. false otherwise
*/
public boolean enableWriteAheadLogging() {
- synchronized(this) {
+ // acquire lock - no that no other thread is enabling WAL at the same time
+ lock();
+ try {
+ if (mConnectionPool != null) {
+ // already enabled
+ return true;
+ }
if (mPath.equalsIgnoreCase(MEMORY_DB_PATH)) {
Log.i(TAG, "can't enable WAL for memory databases.");
return false;
@@ -2284,18 +2319,18 @@
// make sure this database has NO attached databases because sqlite's write-ahead-logging
// doesn't work for databases with attached databases
- if (getAttachedDbs().size() > 1) {
+ if (mHasAttachedDbs) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG,
"this database: " + mPath + " has attached databases. can't enable WAL.");
}
return false;
}
- if (mConnectionPool == null) {
- mConnectionPool = new DatabaseConnectionPool(this);
- setJournalMode(mPath, "WAL");
- }
+ mConnectionPool = new DatabaseConnectionPool(this);
+ setJournalMode(mPath, "WAL");
return true;
+ } finally {
+ unlock();
}
}
@@ -2304,13 +2339,18 @@
* @hide
*/
public void disableWriteAheadLogging() {
- synchronized (this) {
+ // grab database lock so that writeAheadLogging is not disabled from 2 different threads
+ // at the same time
+ lock();
+ try {
if (mConnectionPool == null) {
- return;
+ return; // already disabled
}
mConnectionPool.close();
- mConnectionPool = null;
setJournalMode(mPath, "TRUNCATE");
+ mConnectionPool = null;
+ } finally {
+ unlock();
}
}
@@ -2400,73 +2440,74 @@
*/
/* package */ static ArrayList<DbStats> getDbStats() {
ArrayList<DbStats> dbStatsList = new ArrayList<DbStats>();
-// // make a local copy of mActiveDatabases - so that this method is not competing
-// // for synchronization lock on mActiveDatabases
-// ArrayList<WeakReference<SQLiteDatabase>> tempList;
-// synchronized(mActiveDatabases) {
-// tempList = (ArrayList<WeakReference<SQLiteDatabase>>)mActiveDatabases.clone();
-// }
-// for (WeakReference<SQLiteDatabase> w : tempList) {
-// SQLiteDatabase db = w.get();
-// if (db == null || !db.isOpen()) {
-// continue;
-// }
-//
-// synchronized (db) {
-// try {
-// // get SQLITE_DBSTATUS_LOOKASIDE_USED for the db
-// int lookasideUsed = db.native_getDbLookaside();
-//
-// // get the lastnode of the dbname
-// String path = db.getPath();
-// int indx = path.lastIndexOf("/");
-// String lastnode = path.substring((indx != -1) ? ++indx : 0);
-//
-// // get list of attached dbs and for each db, get its size and pagesize
-// ArrayList<Pair<String, String>> attachedDbs = db.getAttachedDbs();
-// if (attachedDbs == null) {
-// continue;
-// }
-// for (int i = 0; i < attachedDbs.size(); i++) {
-// Pair<String, String> p = attachedDbs.get(i);
-// long pageCount = DatabaseUtils.longForQuery(db, "PRAGMA " + p.first
-// + ".page_count;", null);
-//
-// // first entry in the attached db list is always the main database
-// // don't worry about prefixing the dbname with "main"
-// String dbName;
-// if (i == 0) {
-// dbName = lastnode;
-// } else {
-// // lookaside is only relevant for the main db
-// lookasideUsed = 0;
-// dbName = " (attached) " + p.first;
-// // if the attached db has a path, attach the lastnode from the path to above
-// if (p.second.trim().length() > 0) {
-// int idx = p.second.lastIndexOf("/");
-// dbName += " : " + p.second.substring((idx != -1) ? ++idx : 0);
-// }
-// }
-// if (pageCount > 0) {
-// dbStatsList.add(new DbStats(dbName, pageCount, db.getPageSize(),
-// lookasideUsed, db.getCacheHitNum(), db.getCacheMissNum(),
-// db.getCachesize()));
-// }
-// }
-// // if there are pooled connections, return the cache stats for them also.
-// if (db.mConnectionPool != null) {
-// for (SQLiteDatabase pDb : db.mConnectionPool.getConnectionList()) {
-// dbStatsList.add(new DbStats("(pooled # " + pDb.mConnectionNum + ") "
-// + lastnode, 0, 0, 0, pDb.getCacheHitNum(),
-// pDb.getCacheMissNum(), pDb.getCachesize()));
-// }
-// }
-// } catch (SQLiteException e) {
-// // ignore. we don't care about exceptions when we are taking adb
-// // bugreport!
-// }
-// }
-// }
+ // make a local copy of mActiveDatabases - so that this method is not competing
+ // for synchronization lock on mActiveDatabases
+ ArrayList<WeakReference<SQLiteDatabase>> tempList;
+ synchronized(mActiveDatabases) {
+ tempList = (ArrayList<WeakReference<SQLiteDatabase>>)mActiveDatabases.clone();
+ }
+ for (WeakReference<SQLiteDatabase> w : tempList) {
+ SQLiteDatabase db = w.get();
+ if (db == null || !db.isOpen()) {
+ continue;
+ }
+
+ try {
+ // get SQLITE_DBSTATUS_LOOKASIDE_USED for the db
+ int lookasideUsed = db.native_getDbLookaside();
+
+ // get the lastnode of the dbname
+ String path = db.getPath();
+ int indx = path.lastIndexOf("/");
+ String lastnode = path.substring((indx != -1) ? ++indx : 0);
+
+ // get list of attached dbs and for each db, get its size and pagesize
+ ArrayList<Pair<String, String>> attachedDbs = db.getAttachedDbs();
+ if (attachedDbs == null) {
+ continue;
+ }
+ for (int i = 0; i < attachedDbs.size(); i++) {
+ Pair<String, String> p = attachedDbs.get(i);
+ long pageCount = DatabaseUtils.longForQuery(db, "PRAGMA " + p.first
+ + ".page_count;", null);
+
+ // first entry in the attached db list is always the main database
+ // don't worry about prefixing the dbname with "main"
+ String dbName;
+ if (i == 0) {
+ dbName = lastnode;
+ } else {
+ // lookaside is only relevant for the main db
+ lookasideUsed = 0;
+ dbName = " (attached) " + p.first;
+ // if the attached db has a path, attach the lastnode from the path to above
+ if (p.second.trim().length() > 0) {
+ int idx = p.second.lastIndexOf("/");
+ dbName += " : " + p.second.substring((idx != -1) ? ++idx : 0);
+ }
+ }
+ if (pageCount > 0) {
+ dbStatsList.add(new DbStats(dbName, pageCount, db.getPageSize(),
+ lookasideUsed, db.getCacheHitNum(), db.getCacheMissNum(),
+ db.getCachesize()));
+ }
+ }
+ // if there are pooled connections, return the cache stats for them also.
+ // while we are trying to query the pooled connections for stats, some other thread
+ // could be disabling conneciton pool. so, grab a reference to the connection pool.
+ DatabaseConnectionPool connPool = db.mConnectionPool;
+ if (connPool != null) {
+ for (SQLiteDatabase pDb : connPool.getConnectionList()) {
+ dbStatsList.add(new DbStats("(pooled # " + pDb.mConnectionNum + ") "
+ + lastnode, 0, 0, 0, pDb.getCacheHitNum(),
+ pDb.getCacheMissNum(), pDb.getCachesize()));
+ }
+ }
+ } catch (SQLiteException e) {
+ // ignore. we don't care about exceptions when we are taking adb
+ // bugreport!
+ }
+ }
return dbStatsList;
}
@@ -2482,6 +2523,20 @@
return null;
}
ArrayList<Pair<String, String>> attachedDbs = new ArrayList<Pair<String, String>>();
+ if (!mHasAttachedDbs) {
+ // No attached databases.
+ // There is a small window where attached databases exist but this flag is not set yet.
+ // This can occur when this thread is in a race condition with another thread
+ // that is executing the SQL statement: "attach database <blah> as <foo>"
+ // If this thread is NOT ok with such a race condition (and thus possibly not receive
+ // the entire list of attached databases), then the caller should ensure that no thread
+ // is executing any SQL statements while a thread is calling this method.
+ // Typically, this method is called when 'adb bugreport' is done or the caller wants to
+ // collect stats on the database and all its attached databases.
+ attachedDbs.add(new Pair<String, String>("main", mPath));
+ return attachedDbs;
+ }
+ // has attached databases. query sqlite to get the list of attached databases.
Cursor c = null;
try {
c = rawQuery("pragma database_list;", null);
diff --git a/core/java/android/database/sqlite/SQLiteProgram.java b/core/java/android/database/sqlite/SQLiteProgram.java
index 4747a9e..83621f2 100644
--- a/core/java/android/database/sqlite/SQLiteProgram.java
+++ b/core/java/android/database/sqlite/SQLiteProgram.java
@@ -25,7 +25,7 @@
/**
* A base class for compiled SQLite programs.
*<p>
- * SQLiteProgram is not internally synchronized so code using a SQLiteProgram from multiple
+ * SQLiteProgram is NOT internally synchronized so code using a SQLiteProgram from multiple
* threads should perform its own synchronization when using the SQLiteProgram.
*/
public abstract class SQLiteProgram extends SQLiteClosable {
@@ -180,25 +180,11 @@
mDatabase.releaseReference();
}
- /* package */ synchronized void release() {
+ /* package */ void release() {
if (mCompiledSql == null) {
return;
}
- if ((mStatementType & STATEMENT_CACHEABLE) == 0) {
- // this SQL statement was never in cache
- mCompiledSql.releaseSqlStatement();
- } else {
- synchronized(mDatabase.mCompiledQueries) {
- if (!mDatabase.mCompiledQueries.containsValue(mCompiledSql)) {
- // it is NOT in compiled-sql cache. i.e., responsibility of
- // releasing this statement is on me.
- mCompiledSql.releaseSqlStatement();
- } else {
- // it is in compiled-sql cache. reset its CompiledSql#mInUse flag
- mCompiledSql.release();
- }
- }
- }
+ mDatabase.releaseCompiledSqlObj(mCompiledSql);
mCompiledSql = null;
nStatement = 0;
}
@@ -241,34 +227,32 @@
}
private void bind(int type, int index, Object value) {
- synchronized (this) {
- mDatabase.verifyDbIsOpen();
- addToBindArgs(index, (type == Cursor.FIELD_TYPE_NULL) ? null : value);
- if (nStatement > 0) {
- // bind only if the SQL statement is compiled
- acquireReference();
- try {
- switch (type) {
- case Cursor.FIELD_TYPE_NULL:
- native_bind_null(index);
- break;
- case Cursor.FIELD_TYPE_BLOB:
- native_bind_blob(index, (byte[]) value);
- break;
- case Cursor.FIELD_TYPE_FLOAT:
- native_bind_double(index, (Double) value);
- break;
- case Cursor.FIELD_TYPE_INTEGER:
- native_bind_long(index, (Long) value);
- break;
- case Cursor.FIELD_TYPE_STRING:
- default:
- native_bind_string(index, (String) value);
- break;
- }
- } finally {
- releaseReference();
+ mDatabase.verifyDbIsOpen();
+ addToBindArgs(index, (type == Cursor.FIELD_TYPE_NULL) ? null : value);
+ if (nStatement > 0) {
+ // bind only if the SQL statement is compiled
+ acquireReference();
+ try {
+ switch (type) {
+ case Cursor.FIELD_TYPE_NULL:
+ native_bind_null(index);
+ break;
+ case Cursor.FIELD_TYPE_BLOB:
+ native_bind_blob(index, (byte[]) value);
+ break;
+ case Cursor.FIELD_TYPE_FLOAT:
+ native_bind_double(index, (Double) value);
+ break;
+ case Cursor.FIELD_TYPE_INTEGER:
+ native_bind_long(index, (Long) value);
+ break;
+ case Cursor.FIELD_TYPE_STRING:
+ default:
+ native_bind_string(index, (String) value);
+ break;
}
+ } finally {
+ releaseReference();
}
}
}
@@ -337,18 +321,16 @@
* Clears all existing bindings. Unset bindings are treated as NULL.
*/
public void clearBindings() {
- synchronized (this) {
- mBindArgs = null;
- if (this.nStatement == 0) {
- return;
- }
- mDatabase.verifyDbIsOpen();
- acquireReference();
- try {
- native_clear_bindings();
- } finally {
- releaseReference();
- }
+ mBindArgs = null;
+ if (this.nStatement == 0) {
+ return;
+ }
+ mDatabase.verifyDbIsOpen();
+ acquireReference();
+ try {
+ native_clear_bindings();
+ } finally {
+ releaseReference();
}
}
@@ -356,23 +338,21 @@
* Release this program's resources, making it invalid.
*/
public void close() {
- synchronized (this) {
- mBindArgs = null;
- if (nHandle == 0 || !mDatabase.isOpen()) {
- return;
- }
- releaseReference();
+ mBindArgs = null;
+ if (nHandle == 0 || !mDatabase.isOpen()) {
+ return;
}
+ releaseReference();
}
- private synchronized void addToBindArgs(int index, Object value) {
+ private void addToBindArgs(int index, Object value) {
if (mBindArgs == null) {
mBindArgs = new HashMap<Integer, Object>();
}
mBindArgs.put(index, value);
}
- /* package */ synchronized void compileAndbindAllArgs() {
+ /* package */ void compileAndbindAllArgs() {
if ((mStatementType & STATEMENT_DONT_PREPARE) > 0) {
// no need to prepare this SQL statement
if (SQLiteDebug.DEBUG_SQL_STATEMENTS) {
@@ -424,10 +404,8 @@
return;
}
int size = bindArgs.length;
- synchronized(this) {
- for (int i = 0; i < size; i++) {
- bindString(i + 1, bindArgs[i]);
- }
+ for (int i = 0; i < size; i++) {
+ bindString(i + 1, bindArgs[i]);
}
}
diff --git a/core/java/android/database/sqlite/SQLiteStatement.java b/core/java/android/database/sqlite/SQLiteStatement.java
index bd05e24..5e96928 100644
--- a/core/java/android/database/sqlite/SQLiteStatement.java
+++ b/core/java/android/database/sqlite/SQLiteStatement.java
@@ -31,7 +31,7 @@
* Don't use SQLiteStatement constructor directly, please use
* {@link SQLiteDatabase#compileStatement(String)}
*<p>
- * SQLiteStatement is not internally synchronized so code using a SQLiteStatement from multiple
+ * SQLiteStatement is NOT internally synchronized so code using a SQLiteStatement from multiple
* threads should perform its own synchronization when using the SQLiteStatement.
*/
@SuppressWarnings("deprecation")
@@ -79,23 +79,21 @@
* some reason
*/
public int executeUpdateDelete() {
- synchronized(this) {
- try {
- long timeStart = acquireAndLock(WRITE);
- int numChanges = 0;
- if ((mStatementType & STATEMENT_DONT_PREPARE) > 0) {
- // since the statement doesn't have to be prepared,
- // call the following native method which will not prepare
- // the query plan
- native_executeSql(mSql);
- } else {
- numChanges = native_execute();
- }
- mDatabase.logTimeStat(mSql, timeStart);
- return numChanges;
- } finally {
- releaseAndUnlock();
+ try {
+ long timeStart = acquireAndLock(WRITE);
+ int numChanges = 0;
+ if ((mStatementType & STATEMENT_DONT_PREPARE) > 0) {
+ // since the statement doesn't have to be prepared,
+ // call the following native method which will not prepare
+ // the query plan
+ native_executeSql(mSql);
+ } else {
+ numChanges = native_execute();
}
+ mDatabase.logTimeStat(mSql, timeStart);
+ return numChanges;
+ } finally {
+ releaseAndUnlock();
}
}
@@ -109,15 +107,13 @@
* some reason
*/
public long executeInsert() {
- synchronized(this) {
- try {
- long timeStart = acquireAndLock(WRITE);
- long lastInsertedRowId = native_executeInsert();
- mDatabase.logTimeStat(mSql, timeStart);
- return lastInsertedRowId;
- } finally {
- releaseAndUnlock();
- }
+ try {
+ long timeStart = acquireAndLock(WRITE);
+ long lastInsertedRowId = native_executeInsert();
+ mDatabase.logTimeStat(mSql, timeStart);
+ return lastInsertedRowId;
+ } finally {
+ releaseAndUnlock();
}
}
@@ -130,15 +126,13 @@
* @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
*/
public long simpleQueryForLong() {
- synchronized(this) {
- try {
- long timeStart = acquireAndLock(READ);
- long retValue = native_1x1_long();
- mDatabase.logTimeStat(mSql, timeStart);
- return retValue;
- } finally {
- releaseAndUnlock();
- }
+ try {
+ long timeStart = acquireAndLock(READ);
+ long retValue = native_1x1_long();
+ mDatabase.logTimeStat(mSql, timeStart);
+ return retValue;
+ } finally {
+ releaseAndUnlock();
}
}
@@ -151,15 +145,13 @@
* @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
*/
public String simpleQueryForString() {
- synchronized(this) {
- try {
- long timeStart = acquireAndLock(READ);
- String retValue = native_1x1_string();
- mDatabase.logTimeStat(mSql, timeStart);
- return retValue;
- } finally {
- releaseAndUnlock();
- }
+ try {
+ long timeStart = acquireAndLock(READ);
+ String retValue = native_1x1_string();
+ mDatabase.logTimeStat(mSql, timeStart);
+ return retValue;
+ } finally {
+ releaseAndUnlock();
}
}
@@ -172,18 +164,16 @@
* @throws android.database.sqlite.SQLiteDoneException if the query returns zero rows
*/
public ParcelFileDescriptor simpleQueryForBlobFileDescriptor() {
- synchronized(this) {
- try {
- long timeStart = acquireAndLock(READ);
- ParcelFileDescriptor retValue = native_1x1_blob_ashmem();
- mDatabase.logTimeStat(mSql, timeStart);
- return retValue;
- } catch (IOException ex) {
- Log.e(TAG, "simpleQueryForBlobFileDescriptor() failed", ex);
- return null;
- } finally {
- releaseAndUnlock();
- }
+ try {
+ long timeStart = acquireAndLock(READ);
+ ParcelFileDescriptor retValue = native_1x1_blob_ashmem();
+ mDatabase.logTimeStat(mSql, timeStart);
+ return retValue;
+ } catch (IOException ex) {
+ Log.e(TAG, "simpleQueryForBlobFileDescriptor() failed", ex);
+ return null;
+ } finally {
+ releaseAndUnlock();
}
}
diff --git a/core/java/android/os/storage/OnObbStateChangeListener.java b/core/java/android/os/storage/OnObbStateChangeListener.java
new file mode 100644
index 0000000..a2d0a56
--- /dev/null
+++ b/core/java/android/os/storage/OnObbStateChangeListener.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os.storage;
+
+/**
+ * Used for receiving notifications from {@link StorageManager}.
+ */
+public abstract class OnObbStateChangeListener {
+ /**
+ * Called when an OBB has changed states.
+ *
+ * @param path path to the OBB file the state change has happened on
+ * @param state the current state of the OBB
+ */
+ public void onObbStateChange(String path, String state) {
+ }
+}
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 4a0296b..4268618 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -23,14 +23,28 @@
import android.os.ServiceManager;
import android.util.Log;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
/**
- * StorageManager is the interface to the systems storage service.
+ * StorageManager is the interface to the systems storage service. The storage
+ * manager handles storage-related items such as Opaque Binary Blobs (OBBs).
+ * <p>
+ * OBBs contain a filesystem that maybe be encrypted on disk and mounted
+ * on-demand from an application. OBBs are a good way of providing large amounts
+ * of binary assets without packaging them into APKs as they may be multiple
+ * gigabytes in size. However, due to their size, they're most likely stored in
+ * a shared storage pool accessible from all programs. The system does not
+ * guarantee the security of the OBB file itself: if any program modifies the
+ * OBB, there is no guarantee that a read from that OBB will produce the
+ * expected output.
+ * <p>
* Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String)} with an argument
- * of {@link android.content.Context#STORAGE_SERVICE}.
- *
+ * {@link android.content.Context#getSystemService(java.lang.String)} with an
+ * argument of {@link android.content.Context#STORAGE_SERVICE}.
*/
public class StorageManager
@@ -76,11 +90,113 @@
/**
* Binder listener for OBB action results.
*/
- private final ObbActionBinderListener mObbActionListener = new ObbActionBinderListener();
- private class ObbActionBinderListener extends IObbActionListener.Stub {
+ private final ObbActionListener mObbActionListener = new ObbActionListener();
+
+ private class ObbActionListener extends IObbActionListener.Stub {
+ private List<WeakReference<ObbListenerDelegate>> mListeners = new LinkedList<WeakReference<ObbListenerDelegate>>();
+
@Override
public void onObbResult(String filename, String status) throws RemoteException {
- Log.i(TAG, "filename = " + filename + ", result = " + status);
+ synchronized (mListeners) {
+ final Iterator<WeakReference<ObbListenerDelegate>> iter = mListeners.iterator();
+ while (iter.hasNext()) {
+ final WeakReference<ObbListenerDelegate> ref = iter.next();
+
+ final ObbListenerDelegate delegate = (ref == null) ? null : ref.get();
+ if (delegate == null) {
+ iter.remove();
+ continue;
+ }
+
+ delegate.sendObbStateChanged(filename, status);
+ }
+ }
+ }
+
+ public void addListener(OnObbStateChangeListener listener) {
+ if (listener == null) {
+ return;
+ }
+
+ synchronized (mListeners) {
+ final Iterator<WeakReference<ObbListenerDelegate>> iter = mListeners.iterator();
+ while (iter.hasNext()) {
+ final WeakReference<ObbListenerDelegate> ref = iter.next();
+
+ final ObbListenerDelegate delegate = (ref == null) ? null : ref.get();
+ if (delegate == null) {
+ iter.remove();
+ continue;
+ }
+
+ /*
+ * If we're already in the listeners, we don't need to be in
+ * there again.
+ */
+ if (listener.equals(delegate.getListener())) {
+ return;
+ }
+ }
+
+ final ObbListenerDelegate delegate = new ObbListenerDelegate(listener);
+ mListeners.add(new WeakReference<ObbListenerDelegate>(delegate));
+ }
+ }
+ }
+
+ /**
+ * Private class containing sender and receiver code for StorageEvents.
+ */
+ private class ObbListenerDelegate {
+ private final WeakReference<OnObbStateChangeListener> mObbEventListenerRef;
+ private final Handler mHandler;
+
+ ObbListenerDelegate(OnObbStateChangeListener listener) {
+ mObbEventListenerRef = new WeakReference<OnObbStateChangeListener>(listener);
+ mHandler = new Handler(mTgtLooper) {
+ @Override
+ public void handleMessage(Message msg) {
+ final OnObbStateChangeListener listener = getListener();
+ if (listener == null) {
+ return;
+ }
+
+ StorageEvent e = (StorageEvent) msg.obj;
+
+ if (msg.what == StorageEvent.EVENT_OBB_STATE_CHANGED) {
+ ObbStateChangedStorageEvent ev = (ObbStateChangedStorageEvent) e;
+ listener.onObbStateChange(ev.path, ev.state);
+ } else {
+ Log.e(TAG, "Unsupported event " + msg.what);
+ }
+ }
+ };
+ }
+
+ OnObbStateChangeListener getListener() {
+ if (mObbEventListenerRef == null) {
+ return null;
+ }
+ return mObbEventListenerRef.get();
+ }
+
+ void sendObbStateChanged(String path, String state) {
+ ObbStateChangedStorageEvent e = new ObbStateChangedStorageEvent(path, state);
+ mHandler.sendMessage(e.getMessage());
+ }
+ }
+
+ /**
+ * Message sent during an OBB status change event.
+ */
+ private class ObbStateChangedStorageEvent extends StorageEvent {
+ public final String path;
+ public final String state;
+
+ public ObbStateChangedStorageEvent(String path, String state) {
+ super(EVENT_OBB_STATE_CHANGED);
+ this.path = path;
+ this.state = state;
}
}
@@ -89,8 +205,9 @@
* and the target looper handler.
*/
private class StorageEvent {
- public static final int EVENT_UMS_CONNECTION_CHANGED = 1;
- public static final int EVENT_STORAGE_STATE_CHANGED = 2;
+ static final int EVENT_UMS_CONNECTION_CHANGED = 1;
+ static final int EVENT_STORAGE_STATE_CHANGED = 2;
+ static final int EVENT_OBB_STATE_CHANGED = 3;
private Message mMessage;
@@ -291,19 +408,27 @@
* specified, it is supplied to the mounting process to be used in any
* encryption used in the OBB.
* <p>
+ * The OBB will remain mounted for as long as the StorageManager reference
+ * is held by the application. As soon as this reference is lost, the OBBs
+ * in use will be unmounted. The {@link OnObbStateChangeListener} registered with
+ * this call will receive all further OBB-related events until it goes out
+ * of scope. If the caller is not interested in whether the call succeeds,
+ * the <code>listener</code> may be specified as <code>null</code>.
+ * <p>
* <em>Note:</em> you can only mount OBB files for which the OBB tag on the
* file matches a package ID that is owned by the calling program's UID.
- * That is, shared UID applications can obtain access to any other
+ * That is, shared UID applications can attempt to mount any other
* application's OBB that shares its UID.
- * <p>
- * STOPSHIP document more; discuss lack of guarantees of security
*
* @param filename the path to the OBB file
- * @param key decryption key
+ * @param key secret used to encrypt the OBB; may be <code>null</code> if no
+ * encryption was used on the OBB.
* @return whether the mount call was successfully queued or not
+ * @throws IllegalArgumentException when the OBB is already mounted
*/
- public boolean mountObb(String filename, String key) {
+ public boolean mountObb(String filename, String key, OnObbStateChangeListener listener) {
try {
+ mObbActionListener.addListener(listener);
mMountService.mountObb(filename, key, mObbActionListener);
return true;
} catch (RemoteException e) {
@@ -314,15 +439,20 @@
}
/**
- * Unmount an Opaque Binary Blob (OBB) file. If the <code>force</code> flag
- * is true, it will kill any application needed to unmount the given OBB.
+ * Unmount an Opaque Binary Blob (OBB) file asynchronously. If the
+ * <code>force</code> flag is true, it will kill any application needed to
+ * unmount the given OBB (even the calling application).
+ * <p>
+ * The {@link OnObbStateChangeListener} registered with this call will receive all
+ * further OBB-related events until it goes out of scope. If the caller is
+ * not interested in whether the call succeeded, the listener may be
+ * specified as <code>null</code>.
* <p>
* <em>Note:</em> you can only mount OBB files for which the OBB tag on the
* file matches a package ID that is owned by the calling program's UID.
* That is, shared UID applications can obtain access to any other
* application's OBB that shares its UID.
* <p>
- * STOPSHIP document more; discuss lack of guarantees of security
*
* @param filename path to the OBB file
* @param force whether to kill any programs using this in order to unmount
@@ -330,8 +460,10 @@
* @return whether the unmount call was successfully queued or not
* @throws IllegalArgumentException when OBB is not already mounted
*/
- public boolean unmountObb(String filename, boolean force) throws IllegalArgumentException {
+ public boolean unmountObb(String filename, boolean force, OnObbStateChangeListener listener)
+ throws IllegalArgumentException {
try {
+ mObbActionListener.addListener(listener);
mMountService.unmountObb(filename, force, mObbActionListener);
return true;
} catch (RemoteException e) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e98fa26..d8fb658 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -350,6 +350,20 @@
"android.settings.MANAGE_APPLICATIONS_SETTINGS";
/**
+ * Activity Action: Show settings to manage all applications.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS =
+ "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
+
+ /**
* Activity Action: Show screen of details about a particular application.
* <p>
* In some cases, a matching Activity may not exist, so ensure you
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 35cfbcb..efe4b9d 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -74,7 +74,8 @@
// queue has been cleared,they are ignored.
private boolean mBlockMessages = false;
- private static String sDataDirectory = "";
+ private static String sDatabaseDirectory;
+ private static String sCacheDirectory;
// Is this frame the main frame?
private boolean mIsMainFrame;
@@ -228,9 +229,11 @@
AssetManager am = context.getAssets();
nativeCreateFrame(w, am, proxy.getBackForwardList());
- if (sDataDirectory.length() == 0) {
- String dir = appContext.getFilesDir().getAbsolutePath();
- sDataDirectory = dir.substring(0, dir.lastIndexOf('/'));
+ if (sDatabaseDirectory == null) {
+ sDatabaseDirectory = appContext.getDatabasePath("dummy").getParent();
+ }
+ if (sCacheDirectory == null) {
+ sCacheDirectory = appContext.getCacheDir().getAbsolutePath();
}
if (DebugFlags.BROWSER_FRAME) {
@@ -652,11 +655,19 @@
}
/**
- * Called by JNI. Gets the applications data directory
- * @return String The applications data directory
+ * Called by JNI. Gets the application's database directory, excluding the trailing slash.
+ * @return String The application's database directory
*/
- private static String getDataDirectory() {
- return sDataDirectory;
+ private static String getDatabaseDirectory() {
+ return sDatabaseDirectory;
+ }
+
+ /**
+ * Called by JNI. Gets the application's cache directory, excluding the trailing slash.
+ * @return String The application's cache directory
+ */
+ private static String getCacheDirectory() {
+ return sCacheDirectory;
}
/**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 73fd8ed..7944807 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -607,7 +607,7 @@
static final int HIDE_FULLSCREEN = 121;
static final int DOM_FOCUS_CHANGED = 122;
static final int REPLACE_BASE_CONTENT = 123;
- // 124;
+ static final int FORM_DID_BLUR = 124;
static final int RETURN_LABEL = 125;
static final int FIND_AGAIN = 126;
static final int CENTER_FIT_RECT = 127;
@@ -659,7 +659,7 @@
"HIDE_FULLSCREEN", // = 121;
"DOM_FOCUS_CHANGED", // = 122;
"REPLACE_BASE_CONTENT", // = 123;
- "124", // = 124;
+ "FORM_DID_BLUR", // = 124;
"RETURN_LABEL", // = 125;
"FIND_AGAIN", // = 126;
"CENTER_FIT_RECT", // = 127;
@@ -1875,10 +1875,18 @@
* @hide pending API council approval.
*/
public static boolean cleanupPrivateBrowsingFiles(Context context) {
- return nativeCleanupPrivateBrowsingFiles(context.getFilesDir().getParent());
+ // It seems wrong that we have to pass the storage locations here, given
+ // that the storage files are created native-side in WebRequestContext
+ // (albeit using a dumb getter on BrowserFrame to get the paths from
+ // Java). It looks like this is required because we may need to call
+ // this method before the BrowserFrame has been set up.
+ // TODO: Investigate whether this can be avoided.
+ return nativeCleanupPrivateBrowsingFiles(context.getDatabasePath("dummy").getParent(),
+ context.getCacheDir().getAbsolutePath());
}
- private static native boolean nativeCleanupPrivateBrowsingFiles(String dataDirectory);
+ private static native boolean nativeCleanupPrivateBrowsingFiles(String databaseDirectory,
+ String cacheDirectory);
private boolean extendScroll(int y) {
int finalY = mScroller.getFinalY();
@@ -3846,10 +3854,9 @@
// Called by WebKit to instruct the UI to hide the keyboard
private void hideSoftKeyboard() {
- InputMethodManager imm = (InputMethodManager)
- getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- if (imm.isActive(this)
- || (inEditingMode() && imm.isActive(mWebTextView))) {
+ InputMethodManager imm = InputMethodManager.peekInstance();
+ if (imm != null && (imm.isActive(this)
+ || (inEditingMode() && imm.isActive(mWebTextView)))) {
imm.hideSoftInputFromWindow(this.getWindowToken(), 0);
}
}
@@ -4941,7 +4948,7 @@
@Override
public boolean onTouchEvent(MotionEvent ev) {
- if (mNativeClass == 0 || !isClickable() || !isLongClickable()) {
+ if (mNativeClass == 0 || (!isClickable() && !isLongClickable())) {
return false;
}
@@ -6680,6 +6687,12 @@
updateTextSelectionFromMessage(msg.arg1, msg.arg2,
(WebViewCore.TextSelectionData) msg.obj);
break;
+ case FORM_DID_BLUR:
+ if (inEditingMode()
+ && mWebTextView.isSameTextField(msg.arg1)) {
+ hideSoftKeyboard();
+ }
+ break;
case RETURN_LABEL:
if (inEditingMode()
&& mWebTextView.isSameTextField(msg.arg1)) {
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index a0c6974..7462668 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -273,6 +273,16 @@
mCallbackProxy.onJsAlert(url, message);
}
+ /**
+ * Called by JNI. Send a message to the UI thread to hide the soft keyboard
+ * if the node pointed to by nodePointer is still in focus.
+ * @param nodePointer The node which just blurred.
+ */
+ private void formDidBlur(int nodePointer) {
+ if (mWebView == null) return;
+ Message.obtain(mWebView.mPrivateHandler, WebView.FORM_DID_BLUR,
+ nodePointer, 0).sendToTarget();
+ }
/**
* Called by JNI. Open a file chooser to upload a file.
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index d7b4452..8f89678 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -67,6 +67,9 @@
private final Object mFormLock = new Object();
private final Object mHttpAuthLock = new Object();
+ // TODO: The Chromium HTTP stack handles cookies independently.
+ // We should consider removing the cookies table if and when we switch to
+ // the Chromium HTTP stack for good.
private static final String mTableNames[] = {
"cookies", "password", "formurl", "formdata", "httpauth"
};
diff --git a/core/java/android/widget/Adapters.java b/core/java/android/widget/Adapters.java
index 7fd7fb5..80d8ec1 100644
--- a/core/java/android/widget/Adapters.java
+++ b/core/java/android/widget/Adapters.java
@@ -545,7 +545,8 @@
String name = parser.getName();
if (assertName != null && !assertName.equals(name)) {
throw new IllegalArgumentException("The adapter defined in " +
- c.getResources().getResourceEntryName(id) + " must be a <" + name + " />");
+ c.getResources().getResourceEntryName(id) + " must be a <" +
+ assertName + " />");
}
if (ADAPTER_CURSOR.equals(name)) {
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index afb56fc..27f5ad4 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -122,7 +122,7 @@
// Post a runnable to call back to the view to notify it that we have
// connected
- adapter. mMainQueue.post(new Runnable() {
+ adapter.mMainQueue.post(new Runnable() {
@Override
public void run() {
final RemoteAdapterConnectionCallback callback =
@@ -148,7 +148,7 @@
adapter.mMainQueue.removeMessages(0);
adapter.mWorkerQueue.removeMessages(0);
- // Clear the cache
+ // Clear the cache (the meta data will be re-requested on service re-connection)
synchronized (adapter.mCache) {
adapter.mCache.reset();
}
@@ -183,9 +183,13 @@
* successfully.
*/
public void onRemoteViewsLoaded(RemoteViews view) {
- // Remove all the children of this layout first
- removeAllViews();
- addView(view.apply(getContext(), this));
+ try {
+ // Remove all the children of this layout first
+ removeAllViews();
+ addView(view.apply(getContext(), this));
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to apply RemoteViews.");
+ }
}
}
@@ -224,6 +228,8 @@
* the associated RemoteViews has loaded.
*/
public void notifyOnRemoteViewsLoaded(int position, RemoteViews view, int typeId) {
+ if (view == null) return;
+
final Integer pos = position;
if (mReferences.containsKey(pos)) {
// Notify all the references for that position of the newly loaded RemoteViews
@@ -555,11 +561,14 @@
}
public void reset() {
+ // Note: We do not try and reset the meta data, since that information is still used by
+ // collection views to validate it's own contents (and will be re-requested if the data
+ // is invalidated through the notifyDataSetChanged() flow).
+
mPreloadLowerBound = 0;
mPreloadUpperBound = -1;
mIndexRemoteViews.clear();
mIndexMetaData.clear();
- mMetaData.reset();
synchronized (mLoadIndices) {
mRequestedIndices.clear();
mLoadIndices.clear();
@@ -834,11 +843,6 @@
}
public void notifyDataSetChanged() {
- synchronized (mCache) {
- // Flush the cache so that we can reload new items from the service
- mCache.reset();
- }
-
final RemoteViewsMetaData metaData = mCache.getMetaData();
synchronized (metaData) {
// Set flag to calls the remote factory's onDataSetChanged() on the next worker loop
@@ -864,6 +868,11 @@
}
}
+ // Flush the cache so that we can reload new items from the service
+ synchronized (mCache) {
+ mCache.reset();
+ }
+
// Re-request the new metadata (only after the notification to the factory)
updateMetaData();
diff --git a/core/java/android/widget/RemoteViewsService.java b/core/java/android/widget/RemoteViewsService.java
index b9ded190..16126aa 100644
--- a/core/java/android/widget/RemoteViewsService.java
+++ b/core/java/android/widget/RemoteViewsService.java
@@ -82,27 +82,27 @@
public RemoteViewsFactoryAdapter(RemoteViewsFactory factory) {
mFactory = factory;
}
- public void onDataSetChanged() {
+ public synchronized void onDataSetChanged() {
mFactory.onDataSetChanged();
}
- public int getCount() {
+ public synchronized int getCount() {
return mFactory.getCount();
}
- public RemoteViews getViewAt(int position) {
+ public synchronized RemoteViews getViewAt(int position) {
RemoteViews rv = mFactory.getViewAt(position);
rv.setIsWidgetCollectionChild(true);
return rv;
}
- public RemoteViews getLoadingView() {
+ public synchronized RemoteViews getLoadingView() {
return mFactory.getLoadingView();
}
- public int getViewTypeCount() {
+ public synchronized int getViewTypeCount() {
return mFactory.getViewTypeCount();
}
- public long getItemId(int position) {
+ public synchronized long getItemId(int position) {
return mFactory.getItemId(position);
}
- public boolean hasStableIds() {
+ public synchronized boolean hasStableIds() {
return mFactory.hasStableIds();
}
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 09217af..dd67197 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -26,6 +26,7 @@
import android.content.Intent;
import android.content.res.TypedArray;
import android.database.Cursor;
+import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.Editable;
@@ -348,15 +349,19 @@
}
private void setImeVisibility(boolean visible) {
- // We made sure the IME was displayed, so also make sure it is closed
- // when we go away.
- InputMethodManager imm = (InputMethodManager)
- getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
- if (imm != null) {
- if (visible) {
- imm.showSoftInputUnchecked(0, null);
- } else {
- imm.hideSoftInputFromWindow(getWindowToken(), 0);
+ // don't mess with the soft input if we're not iconified by default
+ if (mIconifiedByDefault) {
+ InputMethodManager imm = (InputMethodManager)
+ getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+
+ // We made sure the IME was displayed, so also make sure it is closed
+ // when we go away.
+ if (imm != null) {
+ if (visible) {
+ imm.showSoftInputUnchecked(0, null);
+ } else {
+ imm.hideSoftInputFromWindow(getWindowToken(), 0);
+ }
}
}
}
@@ -717,4 +722,13 @@
public void afterTextChanged(Editable s) {
}
};
-}
+
+ /*
+ * Avoid getting focus when searching for something to focus on.
+ * The user will have to touch the text view to get focus.
+ */
+ protected boolean onRequestFocusInDescendants(int direction,
+ Rect previouslyFocusedRect) {
+ return false;
+ }
+ }
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index 8311c80..d517d4c 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -84,7 +84,7 @@
static final int THEME_RES_FOR_TYPE[] = new int[] {
com.android.internal.R.style.Theme_IconMenu,
com.android.internal.R.style.Theme_ExpandedMenu,
- 0,
+ com.android.internal.R.style.Theme_Light,
-1,
-1,
};
diff --git a/core/jni/android_content_res_ObbScanner.cpp b/core/jni/android_content_res_ObbScanner.cpp
index 62c89fc..2a9eacf 100644
--- a/core/jni/android_content_res_ObbScanner.cpp
+++ b/core/jni/android_content_res_ObbScanner.cpp
@@ -34,7 +34,17 @@
jfieldID flags;
} gObbInfoClassInfo;
-static jboolean android_content_res_ObbScanner_getObbInfo(JNIEnv* env, jobject clazz, jstring file,
+static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL)
+{
+ jclass npeClazz;
+
+ npeClazz = env->FindClass(exc);
+ LOG_FATAL_IF(npeClazz == NULL, "Unable to find class %s", exc);
+
+ env->ThrowNew(npeClazz, msg);
+}
+
+static void android_content_res_ObbScanner_getObbInfo(JNIEnv* env, jobject clazz, jstring file,
jobject obbInfo)
{
const char* filePath = env->GetStringUTFChars(file, JNI_FALSE);
@@ -42,7 +52,8 @@
sp<ObbFile> obb = new ObbFile();
if (!obb->readFrom(filePath)) {
env->ReleaseStringUTFChars(file, filePath);
- return JNI_FALSE;
+ doThrow(env, "java/io/IOException", "Could not read OBB file");
+ return;
}
env->ReleaseStringUTFChars(file, filePath);
@@ -51,13 +62,13 @@
jstring packageName = env->NewStringUTF(packageNameStr);
if (packageName == NULL) {
- return JNI_FALSE;
+ doThrow(env, "java/io/IOException", "Could not read OBB file");
+ return;
}
env->SetObjectField(obbInfo, gObbInfoClassInfo.packageName, packageName);
env->SetIntField(obbInfo, gObbInfoClassInfo.version, obb->getVersion());
-
- return JNI_TRUE;
+ env->SetIntField(obbInfo, gObbInfoClassInfo.flags, obb->getFlags());
}
/*
@@ -65,7 +76,7 @@
*/
static JNINativeMethod gMethods[] = {
/* name, signature, funcPtr */
- { "getObbInfo_native", "(Ljava/lang/String;Landroid/content/res/ObbInfo;)Z",
+ { "getObbInfo_native", "(Ljava/lang/String;Landroid/content/res/ObbInfo;)V",
(void*) android_content_res_ObbScanner_getObbInfo },
};
diff --git a/core/res/res/color/primary_text_disable_only_holo_dark.xml b/core/res/res/color/primary_text_disable_only_holo_dark.xml
new file mode 100644
index 0000000..6de4583
--- /dev/null
+++ b/core/res/res/color/primary_text_disable_only_holo_dark.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false" android:color="@android:color/bright_foreground_dark_disabled"/>
+ <item android:color="@android:color/bright_foreground_dark"/>
+</selector>
+
diff --git a/core/res/res/color/primary_text_disable_only_holo_light.xml b/core/res/res/color/primary_text_disable_only_holo_light.xml
new file mode 100644
index 0000000..87a92c8
--- /dev/null
+++ b/core/res/res/color/primary_text_disable_only_holo_light.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false" android:color="@android:color/bright_foreground_light_disabled"/>
+ <item android:color="@android:color/bright_foreground_light"/>
+</selector>
+
diff --git a/core/res/res/color/primary_text_focused_holo_dark.xml b/core/res/res/color/primary_text_focused_holo_dark.xml
new file mode 100644
index 0000000..80c68a4
--- /dev/null
+++ b/core/res/res/color/primary_text_focused_holo_dark.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_selected="true" android:color="@android:color/bright_foreground_dark_inverse" />
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse" />
+ <item android:state_focused="true" android:color="@android:color/bright_foreground_dark_inverse" />
+ <item android:state_pressed="true" android:color="@android:color/bright_foreground_dark_inverse" />
+ <item android:color="@android:color/bright_foreground_dark" />
+</selector>
+
diff --git a/core/res/res/color/primary_text_holo_dark.xml b/core/res/res/color/primary_text_holo_dark.xml
new file mode 100644
index 0000000..69ee309
--- /dev/null
+++ b/core/res/res/color/primary_text_holo_dark.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false" android:color="@android:color/bright_foreground_dark_disabled"/>
+ <item android:state_window_focused="false" android:color="@android:color/bright_foreground_dark"/>
+ <item android:state_pressed="true" android:color="@android:color/bright_foreground_dark"/>
+ <item android:state_selected="true" android:color="@android:color/bright_foreground_dark"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_dark"/>
+ <item android:color="@android:color/bright_foreground_dark"/> <!-- not selected -->
+</selector>
diff --git a/core/res/res/color/primary_text_holo_light.xml b/core/res/res/color/primary_text_holo_light.xml
new file mode 100644
index 0000000..a8d31ce
--- /dev/null
+++ b/core/res/res/color/primary_text_holo_light.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false" android:color="@android:color/bright_foreground_light_disabled"/>
+ <item android:state_window_focused="false" android:color="@android:color/bright_foreground_light"/>
+ <item android:state_pressed="true" android:color="@android:color/bright_foreground_light"/>
+ <item android:state_selected="true" android:color="@android:color/bright_foreground_light"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_light"/>
+ <item android:color="@android:color/bright_foreground_light"/> <!-- not selected -->
+
+</selector>
+
diff --git a/core/res/res/color/primary_text_nodisable_holo_dark.xml b/core/res/res/color/primary_text_nodisable_holo_dark.xml
new file mode 100644
index 0000000..f45088f
--- /dev/null
+++ b/core/res/res/color/primary_text_nodisable_holo_dark.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_selected="true" android:color="@android:color/bright_foreground_dark_inverse"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse"/>
+ <item android:color="@android:color/bright_foreground_dark"/> <!-- not selected -->
+</selector>
+
diff --git a/core/res/res/color/primary_text_nodisable_holo_light.xml b/core/res/res/color/primary_text_nodisable_holo_light.xml
new file mode 100644
index 0000000..331e8c3
--- /dev/null
+++ b/core/res/res/color/primary_text_nodisable_holo_light.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_selected="true" android:color="@android:color/bright_foreground_light"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_light"/>
+ <item android:color="@android:color/bright_foreground_light"/> <!-- not selected -->
+</selector>
+
diff --git a/core/res/res/color/search_url_text_holo.xml b/core/res/res/color/search_url_text_holo.xml
new file mode 100644
index 0000000..78093ba
--- /dev/null
+++ b/core/res/res/color/search_url_text_holo.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true" android:color="@android:color/search_url_text_pressed"/>
+ <item android:state_selected="true" android:color="@android:color/search_url_text_selected"/>
+ <item android:color="@android:color/search_url_text_normal"/> <!-- not selected -->
+</selector>
diff --git a/core/res/res/color/secondary_text_holo_dark.xml b/core/res/res/color/secondary_text_holo_dark.xml
new file mode 100644
index 0000000..376156e
--- /dev/null
+++ b/core/res/res/color/secondary_text_holo_dark.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_window_focused="false" android:state_enabled="false" android:color="@android:color/dim_foreground_dark_disabled"/>
+ <item android:state_window_focused="false" android:color="@android:color/dim_foreground_dark"/>
+ <item android:state_selected="true" android:state_enabled="false" android:color="@android:color/dim_foreground_dark_inverse_disabled"/>
+ <item android:state_pressed="true" android:state_enabled="false" android:color="@android:color/dim_foreground_dark_inverse_disabled"/>
+ <item android:state_selected="true" android:color="@android:color/dim_foreground_dark_inverse"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse"/>
+ <item android:state_pressed="true" android:color="@android:color/dim_foreground_dark_inverse"/>
+ <item android:state_enabled="false" android:color="@android:color/dim_foreground_dark_disabled"/>
+ <item android:color="@android:color/dim_foreground_dark"/> <!-- not selected -->
+</selector>
diff --git a/core/res/res/color/secondary_text_holo_light.xml b/core/res/res/color/secondary_text_holo_light.xml
new file mode 100644
index 0000000..b791aeb
--- /dev/null
+++ b/core/res/res/color/secondary_text_holo_light.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_window_focused="false" android:state_enabled="false" android:color="@android:color/dim_foreground_light_disabled"/>
+ <item android:state_window_focused="false" android:color="@android:color/dim_foreground_light"/>
+ <!-- Since there is only one selector (for both light and dark), the light's selected state shouldn't be inversed like the dark's. -->
+ <item android:state_pressed="true" android:state_enabled="false" android:color="@android:color/dim_foreground_light_disabled"/>
+ <item android:state_selected="true" android:state_enabled="false" android:color="@android:color/dim_foreground_light_disabled"/>
+ <item android:state_pressed="true" android:color="@android:color/dim_foreground_light"/>
+ <item android:state_selected="true" android:color="@android:color/dim_foreground_light"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_light"/>
+ <item android:state_enabled="false" android:color="@android:color/dim_foreground_light_disabled"/>
+ <item android:color="@android:color/dim_foreground_light"/> <!-- not selected -->
+</selector>
diff --git a/core/res/res/color/secondary_text_nodisable_holo_dark.xml b/core/res/res/color/secondary_text_nodisable_holo_dark.xml
new file mode 100644
index 0000000..8c22241
--- /dev/null
+++ b/core/res/res/color/secondary_text_nodisable_holo_dark.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_selected="true" android:color="@android:color/dim_foreground_dark_inverse"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse"/>
+ <item android:color="@android:color/dim_foreground_dark"/> <!-- not selected -->
+</selector>
diff --git a/core/res/res/color/secondary_text_nodisable_holo_light.xml b/core/res/res/color/secondary_text_nodisable_holo_light.xml
new file mode 100644
index 0000000..8c22241
--- /dev/null
+++ b/core/res/res/color/secondary_text_nodisable_holo_light.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_selected="true" android:color="@android:color/dim_foreground_dark_inverse"/>
+ <item android:state_activated="true" android:color="@android:color/bright_foreground_dark_inverse"/>
+ <item android:color="@android:color/dim_foreground_dark"/> <!-- not selected -->
+</selector>
diff --git a/core/res/res/color/tertiary_text_holo_dark.xml b/core/res/res/color/tertiary_text_holo_dark.xml
new file mode 100644
index 0000000..269ff71
--- /dev/null
+++ b/core/res/res/color/tertiary_text_holo_dark.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false" android:color="#808080"/>
+ <item android:state_window_focused="false" android:color="#808080"/>
+ <item android:state_pressed="true" android:color="#808080"/>
+ <item android:state_selected="true" android:color="@android:color/dim_foreground_light"/>
+ <item android:color="#808080"/> <!-- not selected -->
+</selector>
+
diff --git a/core/res/res/color/tertiary_text_holo_light.xml b/core/res/res/color/tertiary_text_holo_light.xml
new file mode 100644
index 0000000..9e5c2d9
--- /dev/null
+++ b/core/res/res/color/tertiary_text_holo_light.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_enabled="false" android:color="#808080"/>
+ <item android:state_window_focused="false" android:color="#808080"/>
+ <item android:state_pressed="true" android:color="#808080"/>
+ <item android:state_selected="true" android:color="#808080"/>
+ <item android:color="#808080"/> <!-- not selected -->
+</selector>
+
diff --git a/core/res/res/color/widget_edittext_holo_dark.xml b/core/res/res/color/widget_edittext_holo_dark.xml
new file mode 100644
index 0000000..4f3eb62
--- /dev/null
+++ b/core/res/res/color/widget_edittext_holo_dark.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="false" android:color="@android:color/bright_foreground_light"/> <!-- unfocused -->
+ <item android:color="@android:color/bright_foreground_light"/>
+</selector>
diff --git a/core/res/res/color/widget_edittext_holo_light.xml b/core/res/res/color/widget_edittext_holo_light.xml
new file mode 100644
index 0000000..7b950d4
--- /dev/null
+++ b/core/res/res/color/widget_edittext_holo_light.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="false" android:color="@android:color/bright_foreground_dark"/> <!-- unfocused -->
+ <item android:color="@android:color/bright_foreground_dark"/>
+</selector>
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_dark.png
index d72e2b9..d93e580 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_light.png
index 240a044..ffbe776 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disable_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_disable_holo_dark.png
index d72e2b9..d93e580 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_disable_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disable_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_disable_holo_light.png b/core/res/res/drawable-hdpi/btn_check_off_disable_holo_light.png
index 240a044..ffbe776 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_disable_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_disable_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_holo_dark.png
index 911e1aa..4148ac4 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_holo_light.png b/core/res/res/drawable-hdpi/btn_check_off_holo_light.png
index 4ca3c56..2cc946f 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_dark.png
index 08f4181..9f9cb01 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_light.png
index d3754dd..56425d2 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_selected_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_off_selected_holo_dark.png
index 264f102..f819928 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_selected_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_selected_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_off_selected_holo_light.png b/core/res/res/drawable-hdpi/btn_check_off_selected_holo_light.png
index 48506bf..57cb512 100644
--- a/core/res/res/drawable-hdpi/btn_check_off_selected_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_off_selected_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_dark.png
index 7805458..1f7aeee 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_light.png
index 4e268d5..1f740ad 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disable_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_disable_holo_dark.png
index 7805458..1f7aeee 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disable_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disable_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_disable_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_disable_holo_light.png
index 4e268d5..1f740ad 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_disable_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_disable_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png
index 5541c67..d0c4415 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_holo_light.png
index 768c4af..af84d4b 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
index 37e3953..91e5f14 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
index fc29e46..0cf7ed2 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_selected_holo_dark.png b/core/res/res/drawable-hdpi/btn_check_on_selected_holo_dark.png
index a0beac4..e758aab 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_selected_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_selected_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_check_on_selected_holo_light.png b/core/res/res/drawable-hdpi/btn_check_on_selected_holo_light.png
index 5df45c7..2edf656 100644
--- a/core/res/res/drawable-hdpi/btn_check_on_selected_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_check_on_selected_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
new file mode 100644
index 0000000..3deb385
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
new file mode 100644
index 0000000..de378a5
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
new file mode 100644
index 0000000..35f8b3d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
new file mode 100644
index 0000000..3f45375
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
new file mode 100644
index 0000000..ea58bf7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
new file mode 100644
index 0000000..b225aaff
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
new file mode 100644
index 0000000..b5b1533
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
new file mode 100644
index 0000000..81b8a75
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
new file mode 100644
index 0000000..eb8d85a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
new file mode 100644
index 0000000..6777ebf
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_disabled_off_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_disabled_off_holo_dark.png
new file mode 100644
index 0000000..2a7505b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_disabled_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_disabled_off_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_disabled_off_holo_light.png
new file mode 100644
index 0000000..bbb01f0
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_disabled_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_disabled_on_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_disabled_on_holo_dark.png
new file mode 100644
index 0000000..b617a2a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_disabled_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_disabled_on_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_disabled_on_holo_light.png
new file mode 100644
index 0000000..fd59f4a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_disabled_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_focused_off_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_focused_off_holo_dark.png
new file mode 100644
index 0000000..5d17cde
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_focused_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_focused_off_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_focused_off_holo_light.png
new file mode 100644
index 0000000..b6b4bf1
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_focused_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_focused_on_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_focused_on_holo_dark.png
new file mode 100644
index 0000000..eab5039
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_focused_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_focused_on_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_focused_on_holo_light.png
new file mode 100644
index 0000000..b6b4bf1
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_focused_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_normal_off_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_normal_off_holo_dark.png
new file mode 100644
index 0000000..edf2296
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_normal_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_normal_off_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_normal_off_holo_light.png
new file mode 100644
index 0000000..68afa4c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_normal_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_normal_on_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_normal_on_holo_dark.png
new file mode 100644
index 0000000..c7df168
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_normal_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_normal_on_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_normal_on_holo_light.png
new file mode 100644
index 0000000..5a9087b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_normal_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_off_holo_dark.png
index 301c97d..dd18b7a 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_off_holo_light.png
index 657c8e5..66d538f 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_dark.png
index 5e6ef2b..4e777f8 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_light.png
index 342bf11..6062033 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_selected_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_off_selected_holo_dark.png
index d11ae85..683a883 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_selected_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_selected_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_off_selected_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_off_selected_holo_light.png
index 68bd1df..19524ff 100644
--- a/core/res/res/drawable-hdpi/btn_radio_off_selected_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_radio_off_selected_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_on_holo_dark.png
index 5b0dbe8..2e1111b 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_on_holo_light.png
index 45ae36b..90639ec 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_dark.png
index c3a0d48..1907215 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_light.png
index ca22358..b51c7ad 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_selected_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_on_selected_holo_dark.png
index 6c05f47..06d39cc 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_selected_holo_dark.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_selected_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_on_selected_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_on_selected_holo_light.png
index a17fa1e..06a4314 100644
--- a/core/res/res/drawable-hdpi/btn_radio_on_selected_holo_light.png
+++ b/core/res/res/drawable-hdpi/btn_radio_on_selected_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_pressed_off_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_pressed_off_holo_dark.png
new file mode 100644
index 0000000..500490d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_pressed_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_pressed_off_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_pressed_off_holo_light.png
new file mode 100644
index 0000000..f6690c6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_pressed_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_pressed_on_holo_dark.png b/core/res/res/drawable-hdpi/btn_radio_pressed_on_holo_dark.png
new file mode 100644
index 0000000..933d2fe
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_pressed_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_radio_pressed_on_holo_light.png b/core/res/res/drawable-hdpi/btn_radio_pressed_on_holo_light.png
new file mode 100644
index 0000000..c07445a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_radio_pressed_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
new file mode 100755
index 0000000..128a8dd
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_light.9.png
new file mode 100755
index 0000000..da05c23
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_dark.9.png
new file mode 100755
index 0000000..da66a98
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_light.9.png
new file mode 100755
index 0000000..3ac8417
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_dark.9.png
new file mode 100755
index 0000000..fc9d493
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_light.9.png
new file mode 100755
index 0000000..315ae3b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_holo.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_holo.9.png
new file mode 100755
index 0000000..f903bdb
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_dark.9.png
new file mode 100755
index 0000000..ee9590c6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_light.9.png
new file mode 100755
index 0000000..cbc9da2c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_dark.9.png
new file mode 100755
index 0000000..1792063
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_light.9.png
new file mode 100755
index 0000000..097025b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_off_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
new file mode 100755
index 0000000..5b92d7c6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_light.9.png
new file mode 100755
index 0000000..a244f45
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_dark.9.png
new file mode 100755
index 0000000..9218f91
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_light.9.png
new file mode 100755
index 0000000..81802f8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_dark.9.png
new file mode 100755
index 0000000..9dea983
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_light.9.png
new file mode 100755
index 0000000..fc2374b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_holo.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_holo.9.png
new file mode 100755
index 0000000..4c1d89d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_dark.9.png
new file mode 100755
index 0000000..18bb6bd
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_light.9.png
new file mode 100755
index 0000000..de78a9f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_dark.9.png
new file mode 100755
index 0000000..2269326
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_light.9.png
new file mode 100755
index 0000000..ead4ccf
--- /dev/null
+++ b/core/res/res/drawable-hdpi/btn_toggle_on_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_divider_holo_dark.png b/core/res/res/drawable-hdpi/cab_divider_holo_dark.png
new file mode 100755
index 0000000..e6f61fc
--- /dev/null
+++ b/core/res/res/drawable-hdpi/cab_divider_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_divider_holo_light.png b/core/res/res/drawable-hdpi/cab_divider_holo_light.png
new file mode 100755
index 0000000..2f97a29
--- /dev/null
+++ b/core/res/res/drawable-hdpi/cab_divider_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_divider_vertical_dark.png b/core/res/res/drawable-hdpi/cab_divider_vertical_dark.png
new file mode 100755
index 0000000..b1f035c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/cab_divider_vertical_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_divider_vertical_light.png b/core/res/res/drawable-hdpi/cab_divider_vertical_light.png
new file mode 100755
index 0000000..2183b12
--- /dev/null
+++ b/core/res/res/drawable-hdpi/cab_divider_vertical_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_holo_dark.9.png b/core/res/res/drawable-hdpi/cab_holo_dark.9.png
new file mode 100755
index 0000000..662d63c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/cab_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_holo_light.9.png b/core/res/res/drawable-hdpi/cab_holo_light.9.png
new file mode 100755
index 0000000..e8cbde1
--- /dev/null
+++ b/core/res/res/drawable-hdpi/cab_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_ic_close_focused_holo.png b/core/res/res/drawable-hdpi/cab_ic_close_focused_holo.png
new file mode 100755
index 0000000..861e0a1
--- /dev/null
+++ b/core/res/res/drawable-hdpi/cab_ic_close_focused_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_ic_close_normal_holo.png b/core/res/res/drawable-hdpi/cab_ic_close_normal_holo.png
new file mode 100755
index 0000000..036f362
--- /dev/null
+++ b/core/res/res/drawable-hdpi/cab_ic_close_normal_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cab_ic_close_pressed_holo.png b/core/res/res/drawable-hdpi/cab_ic_close_pressed_holo.png
new file mode 100755
index 0000000..be8c2ff
--- /dev/null
+++ b/core/res/res/drawable-hdpi/cab_ic_close_pressed_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_disabled_off_holo_dark.png b/core/res/res/drawable-hdpi/checkbox_disabled_off_holo_dark.png
new file mode 100644
index 0000000..6de74a7
--- /dev/null
+++ b/core/res/res/drawable-hdpi/checkbox_disabled_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_disabled_off_holo_light.png b/core/res/res/drawable-hdpi/checkbox_disabled_off_holo_light.png
new file mode 100644
index 0000000..a0e201d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/checkbox_disabled_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_disabled_on_holo_dark.png b/core/res/res/drawable-hdpi/checkbox_disabled_on_holo_dark.png
new file mode 100644
index 0000000..9bb69c4
--- /dev/null
+++ b/core/res/res/drawable-hdpi/checkbox_disabled_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_disabled_on_holo_light.png b/core/res/res/drawable-hdpi/checkbox_disabled_on_holo_light.png
new file mode 100644
index 0000000..bffc5aa
--- /dev/null
+++ b/core/res/res/drawable-hdpi/checkbox_disabled_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_focused_off_holo_dark.png b/core/res/res/drawable-hdpi/checkbox_focused_off_holo_dark.png
new file mode 100644
index 0000000..bbe04b6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/checkbox_focused_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_focused_off_holo_light.png b/core/res/res/drawable-hdpi/checkbox_focused_off_holo_light.png
new file mode 100644
index 0000000..62f1efa
--- /dev/null
+++ b/core/res/res/drawable-hdpi/checkbox_focused_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_focused_on_holo_dark.png b/core/res/res/drawable-hdpi/checkbox_focused_on_holo_dark.png
new file mode 100644
index 0000000..c4026a8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/checkbox_focused_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_focused_on_holo_light.png b/core/res/res/drawable-hdpi/checkbox_focused_on_holo_light.png
new file mode 100644
index 0000000..409aa3e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/checkbox_focused_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_normal_off_holo_dark.png b/core/res/res/drawable-hdpi/checkbox_normal_off_holo_dark.png
new file mode 100644
index 0000000..10f1bc4
--- /dev/null
+++ b/core/res/res/drawable-hdpi/checkbox_normal_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_normal_off_holo_light.png b/core/res/res/drawable-hdpi/checkbox_normal_off_holo_light.png
new file mode 100644
index 0000000..20a1efa
--- /dev/null
+++ b/core/res/res/drawable-hdpi/checkbox_normal_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_normal_on_holo_dark.png b/core/res/res/drawable-hdpi/checkbox_normal_on_holo_dark.png
new file mode 100644
index 0000000..0a10ec8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/checkbox_normal_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_normal_on_holo_light.png b/core/res/res/drawable-hdpi/checkbox_normal_on_holo_light.png
new file mode 100644
index 0000000..34b53ee
--- /dev/null
+++ b/core/res/res/drawable-hdpi/checkbox_normal_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_pressed_off_holo_dark.png b/core/res/res/drawable-hdpi/checkbox_pressed_off_holo_dark.png
new file mode 100644
index 0000000..7f14620
--- /dev/null
+++ b/core/res/res/drawable-hdpi/checkbox_pressed_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_pressed_off_holo_light.png b/core/res/res/drawable-hdpi/checkbox_pressed_off_holo_light.png
new file mode 100644
index 0000000..cabf936
--- /dev/null
+++ b/core/res/res/drawable-hdpi/checkbox_pressed_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_pressed_on_holo_dark.png b/core/res/res/drawable-hdpi/checkbox_pressed_on_holo_dark.png
new file mode 100644
index 0000000..bcddb31
--- /dev/null
+++ b/core/res/res/drawable-hdpi/checkbox_pressed_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/checkbox_pressed_on_holo_light.png b/core/res/res/drawable-hdpi/checkbox_pressed_on_holo_light.png
new file mode 100644
index 0000000..84160e5
--- /dev/null
+++ b/core/res/res/drawable-hdpi/checkbox_pressed_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_bottom_holo.9.png b/core/res/res/drawable-hdpi/dialog_bottom_holo.9.png
new file mode 100644
index 0000000..3a84de9
--- /dev/null
+++ b/core/res/res/drawable-hdpi/dialog_bottom_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_full_holo.9.png b/core/res/res/drawable-hdpi/dialog_full_holo.9.png
new file mode 100644
index 0000000..5d2e4e1
--- /dev/null
+++ b/core/res/res/drawable-hdpi/dialog_full_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_middle_holo.9.png b/core/res/res/drawable-hdpi/dialog_middle_holo.9.png
new file mode 100644
index 0000000..dc5e79d
--- /dev/null
+++ b/core/res/res/drawable-hdpi/dialog_middle_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/dialog_top_holo.9.png b/core/res/res/drawable-hdpi/dialog_top_holo.9.png
new file mode 100644
index 0000000..0275c18
--- /dev/null
+++ b/core/res/res/drawable-hdpi/dialog_top_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_holo_dark.9.png b/core/res/res/drawable-hdpi/divider_horizontal_holo_dark.9.png
new file mode 100644
index 0000000..e8e1deb
--- /dev/null
+++ b/core/res/res/drawable-hdpi/divider_horizontal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_horizontal_holo_light.9.png b/core/res/res/drawable-hdpi/divider_horizontal_holo_light.9.png
new file mode 100644
index 0000000..9e6cbbe
--- /dev/null
+++ b/core/res/res/drawable-hdpi/divider_horizontal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_vertical_holo_dark.9.png b/core/res/res/drawable-hdpi/divider_vertical_holo_dark.9.png
new file mode 100644
index 0000000..deacb73
--- /dev/null
+++ b/core/res/res/drawable-hdpi/divider_vertical_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/divider_vertical_holo_light.9.png b/core/res/res/drawable-hdpi/divider_vertical_holo_light.9.png
new file mode 100644
index 0000000..cd2c826
--- /dev/null
+++ b/core/res/res/drawable-hdpi/divider_vertical_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_dialog_close_normal_holo.png b/core/res/res/drawable-hdpi/ic_dialog_close_normal_holo.png
new file mode 100644
index 0000000..5ee5bb8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_dialog_close_normal_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_dialog_close_pressed_holo.png b/core/res/res/drawable-hdpi/ic_dialog_close_pressed_holo.png
new file mode 100644
index 0000000..792db06
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_dialog_close_pressed_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_dialog_focused_holo.png b/core/res/res/drawable-hdpi/ic_dialog_focused_holo.png
new file mode 100644
index 0000000..e208575
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_dialog_focused_holo.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_arrow_left_holo_dark.png b/core/res/res/drawable-hdpi/tab_arrow_left_holo_dark.png
new file mode 100644
index 0000000..cfd6f78
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_arrow_left_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_arrow_left_holo_light.png b/core/res/res/drawable-hdpi/tab_arrow_left_holo_light.png
new file mode 100644
index 0000000..036aa8c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_arrow_left_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_arrow_right_holo_dark.png b/core/res/res/drawable-hdpi/tab_arrow_right_holo_dark.png
new file mode 100644
index 0000000..b226038
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_arrow_right_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_arrow_right_holo_light.png b/core/res/res/drawable-hdpi/tab_arrow_right_holo_light.png
new file mode 100644
index 0000000..0e5fbe6
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_arrow_right_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_divider_holo_dark.png b/core/res/res/drawable-hdpi/tab_divider_holo_dark.png
new file mode 100644
index 0000000..112cb04
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_divider_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_divider_holo_light.png b/core/res/res/drawable-hdpi/tab_divider_holo_light.png
new file mode 100644
index 0000000..1bf4d38
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_divider_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_selector_holo_dark.9.png b/core/res/res/drawable-hdpi/tab_selector_holo_dark.9.png
new file mode 100644
index 0000000..f01b9bc
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_selector_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_strip_holo.9.png b/core/res/res/drawable-hdpi/tab_strip_holo.9.png
new file mode 100644
index 0000000..d937f6b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_strip_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_default_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_default_holo_dark.9.png
index c67d04d..7ec2192 100644
--- a/core/res/res/drawable-hdpi/textfield_default_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_default_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_default_holo_light.9.png
index 1292ebf..c03e4f6 100644
--- a/core/res/res/drawable-hdpi/textfield_default_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_disabled_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_disabled_holo_dark.9.png
index a39982a..6642717 100644
--- a/core/res/res/drawable-hdpi/textfield_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_disabled_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_disabled_holo_light.9.png
index 1f224b9..9572752 100644
--- a/core/res/res/drawable-hdpi/textfield_disabled_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_disabled_selected_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_disabled_selected_holo_dark.9.png
index 66f18cc..0ad248c 100644
--- a/core/res/res/drawable-hdpi/textfield_disabled_selected_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_disabled_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_disabled_selected_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_disabled_selected_holo_light.9.png
index 2664384..b7a07c4 100644
--- a/core/res/res/drawable-hdpi/textfield_disabled_selected_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_disabled_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_pressed_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_pressed_holo_dark.9.png
index bbf53c5..a271ac9b 100644
--- a/core/res/res/drawable-hdpi/textfield_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_pressed_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_pressed_holo_light.9.png
index ce49b8d..521722d 100644
--- a/core/res/res/drawable-hdpi/textfield_pressed_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png
new file mode 100644
index 0000000..5b62564
--- /dev/null
+++ b/core/res/res/drawable-hdpi/textfield_search_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png
new file mode 100644
index 0000000..881edeb
--- /dev/null
+++ b/core/res/res/drawable-hdpi/textfield_search_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png
new file mode 100644
index 0000000..cb3f35b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/textfield_search_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png
new file mode 100644
index 0000000..742b137
--- /dev/null
+++ b/core/res/res/drawable-hdpi/textfield_search_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_selected_holo_dark.9.png b/core/res/res/drawable-hdpi/textfield_selected_holo_dark.9.png
index bbf53c5..a271ac9b 100644
--- a/core/res/res/drawable-hdpi/textfield_selected_holo_dark.9.png
+++ b/core/res/res/drawable-hdpi/textfield_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_selected_holo_light.9.png b/core/res/res/drawable-hdpi/textfield_selected_holo_light.9.png
index ce49b8d..521722d 100644
--- a/core/res/res/drawable-hdpi/textfield_selected_holo_light.9.png
+++ b/core/res/res/drawable-hdpi/textfield_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_dark.png
index a603fb1..3fac4aa 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_light.png
index 69e9ff9..3da9a46 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disable_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_disable_holo_dark.png
index a603fb1..3fac4aa 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disable_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disable_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_disable_holo_light.png b/core/res/res/drawable-mdpi/btn_check_off_disable_holo_light.png
index 69e9ff9..3da9a46 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_disable_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_disable_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_holo_dark.png
index 5e44c29..b03f356 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_holo_light.png b/core/res/res/drawable-mdpi/btn_check_off_holo_light.png
index 5b2ec92..9dbbd49 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_dark.png
index 611bb1d..0dcb9de 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_light.png
index 5a0ea441..b25fdc4 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_selected_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_off_selected_holo_dark.png
index aa28df2..89ea3a8 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_selected_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_selected_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_off_selected_holo_light.png b/core/res/res/drawable-mdpi/btn_check_off_selected_holo_light.png
index ade1136..3fa45d9 100644
--- a/core/res/res/drawable-mdpi/btn_check_off_selected_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_off_selected_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_dark.png
index f19972a..48cc017 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_light.png
index 13ef46e..c9ebbca 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disable_focused_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_disable_holo_dark.png
index f19972a..48cc017 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disable_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disable_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_disable_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_disable_holo_light.png
index 13ef46e..c9ebbca 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_disable_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_disable_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png
index 130d562..ca4d509 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_holo_light.png
index 6b7808b..158f3a1 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
index df753f5..0722cda 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png
index 6a4dd2c..4de166e 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_selected_holo_dark.png b/core/res/res/drawable-mdpi/btn_check_on_selected_holo_dark.png
index 7586881..5b93f8b 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_selected_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_selected_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_check_on_selected_holo_light.png b/core/res/res/drawable-mdpi/btn_check_on_selected_holo_light.png
index 24701ce..74ab250 100644
--- a/core/res/res/drawable-mdpi/btn_check_on_selected_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_check_on_selected_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
new file mode 100644
index 0000000..9bc1ee8
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
new file mode 100644
index 0000000..cc643ea
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
new file mode 100644
index 0000000..0586d52
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
new file mode 100644
index 0000000..dd6c1a0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_default_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
new file mode 100644
index 0000000..e8f07cb
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
new file mode 100644
index 0000000..0685f1e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_default_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
new file mode 100644
index 0000000..6b33fa4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
new file mode 100644
index 0000000..eb728ed
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_default_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
new file mode 100644
index 0000000..4a15d9d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
new file mode 100644
index 0000000..6718ff7
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_default_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_disabled_off_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_disabled_off_holo_dark.png
new file mode 100644
index 0000000..f21142e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_disabled_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_disabled_off_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_disabled_off_holo_light.png
new file mode 100644
index 0000000..a1031fc
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_disabled_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_disabled_on_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_disabled_on_holo_dark.png
new file mode 100644
index 0000000..61243c5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_disabled_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_disabled_on_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_disabled_on_holo_light.png
new file mode 100644
index 0000000..faa55e0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_disabled_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_focused_off_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_focused_off_holo_dark.png
new file mode 100644
index 0000000..0c645da
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_focused_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_focused_off_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_focused_off_holo_light.png
new file mode 100644
index 0000000..5efc321
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_focused_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_focused_on_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_focused_on_holo_dark.png
new file mode 100644
index 0000000..96bcdc5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_focused_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_focused_on_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_focused_on_holo_light.png
new file mode 100644
index 0000000..5efc321
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_focused_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_normal_off_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_normal_off_holo_dark.png
new file mode 100644
index 0000000..96413ef
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_normal_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_normal_off_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_normal_off_holo_light.png
new file mode 100644
index 0000000..1cb5432
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_normal_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_normal_on_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_normal_on_holo_dark.png
new file mode 100644
index 0000000..2e8404a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_normal_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_normal_on_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_normal_on_holo_light.png
new file mode 100644
index 0000000..b3e14b1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_normal_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_off_holo_dark.png
index 16c1c6b..a3cef04 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_off_holo_light.png
index e8287f3..e8def55 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_dark.png
index b25217b..1a9310b 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_light.png
index b63b9b0..bc28b5b 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_selected_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_off_selected_holo_dark.png
index bef7572..2b0ddd1 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_selected_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_selected_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_off_selected_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_off_selected_holo_light.png
index af754e1..745cf19 100644
--- a/core/res/res/drawable-mdpi/btn_radio_off_selected_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_radio_off_selected_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_on_holo_dark.png
index 4ed7471..9954500 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_on_holo_light.png
index 62aaa41..fa67a43 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_dark.png
index 7cf91c6..c15c310 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_light.png
index 0d93507..aa07c5a 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_pressed_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_selected_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_on_selected_holo_dark.png
index 56f6f5b..e96a74f 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_selected_holo_dark.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_selected_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_on_selected_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_on_selected_holo_light.png
index 48dd8e9..c51c96c 100644
--- a/core/res/res/drawable-mdpi/btn_radio_on_selected_holo_light.png
+++ b/core/res/res/drawable-mdpi/btn_radio_on_selected_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_pressed_off_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_pressed_off_holo_dark.png
new file mode 100644
index 0000000..5f74c70
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_pressed_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_pressed_off_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_pressed_off_holo_light.png
new file mode 100644
index 0000000..408e50e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_pressed_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_pressed_on_holo_dark.png b/core/res/res/drawable-mdpi/btn_radio_pressed_on_holo_dark.png
new file mode 100644
index 0000000..ff60bc2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_pressed_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_radio_pressed_on_holo_light.png b/core/res/res/drawable-mdpi/btn_radio_pressed_on_holo_light.png
new file mode 100644
index 0000000..2125c24
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_radio_pressed_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
new file mode 100755
index 0000000..7d1e16d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_light.9.png
new file mode 100755
index 0000000..92e86cd
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_dark.9.png
new file mode 100755
index 0000000..1cf473b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_light.9.png
new file mode 100755
index 0000000..d6f2125
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_dark.9.png
new file mode 100755
index 0000000..31f7f8c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_light.9.png
new file mode 100755
index 0000000..82425d5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_holo.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_holo.9.png
new file mode 100755
index 0000000..0ca659e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_dark.9.png
new file mode 100755
index 0000000..16f19fc
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_light.9.png
new file mode 100755
index 0000000..e2c7702
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_dark.9.png
new file mode 100755
index 0000000..d61470c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_light.9.png
new file mode 100755
index 0000000..4019fee
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_off_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
new file mode 100755
index 0000000..ba354e3
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_light.9.png
new file mode 100755
index 0000000..9391b2e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_dark.9.png
new file mode 100755
index 0000000..601ff2c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_light.9.png
new file mode 100755
index 0000000..90c259a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_dark.9.png
new file mode 100755
index 0000000..857c757
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_light.9.png
new file mode 100755
index 0000000..ef16a48
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_focused_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_holo.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_holo.9.png
new file mode 100755
index 0000000..66cbe48
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_dark.9.png
new file mode 100755
index 0000000..d47ec8f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_light.9.png
new file mode 100755
index 0000000..2951caf
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_normal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_dark.9.png
new file mode 100755
index 0000000..141b4dd
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_light.9.png
new file mode 100755
index 0000000..913aed5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/btn_toggle_on_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_divider_holo_dark.png b/core/res/res/drawable-mdpi/cab_divider_holo_dark.png
new file mode 100755
index 0000000..57cc8a4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/cab_divider_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_divider_holo_light.png b/core/res/res/drawable-mdpi/cab_divider_holo_light.png
new file mode 100755
index 0000000..ec85701
--- /dev/null
+++ b/core/res/res/drawable-mdpi/cab_divider_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_divider_vertical_dark.png b/core/res/res/drawable-mdpi/cab_divider_vertical_dark.png
new file mode 100755
index 0000000..f7ed6df
--- /dev/null
+++ b/core/res/res/drawable-mdpi/cab_divider_vertical_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_divider_vertical_light.png b/core/res/res/drawable-mdpi/cab_divider_vertical_light.png
new file mode 100755
index 0000000..73ac0d9
--- /dev/null
+++ b/core/res/res/drawable-mdpi/cab_divider_vertical_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_holo_dark.9.png b/core/res/res/drawable-mdpi/cab_holo_dark.9.png
new file mode 100755
index 0000000..6c85300
--- /dev/null
+++ b/core/res/res/drawable-mdpi/cab_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_holo_light.9.png b/core/res/res/drawable-mdpi/cab_holo_light.9.png
new file mode 100755
index 0000000..c82352a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/cab_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_ic_close_focused_holo.png b/core/res/res/drawable-mdpi/cab_ic_close_focused_holo.png
new file mode 100755
index 0000000..df170c4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/cab_ic_close_focused_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_ic_close_normal_holo.png b/core/res/res/drawable-mdpi/cab_ic_close_normal_holo.png
new file mode 100755
index 0000000..9482ce7
--- /dev/null
+++ b/core/res/res/drawable-mdpi/cab_ic_close_normal_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cab_ic_close_pressed_holo.png b/core/res/res/drawable-mdpi/cab_ic_close_pressed_holo.png
new file mode 100755
index 0000000..d115d20
--- /dev/null
+++ b/core/res/res/drawable-mdpi/cab_ic_close_pressed_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_disabled_off_holo_dark.png b/core/res/res/drawable-mdpi/checkbox_disabled_off_holo_dark.png
new file mode 100644
index 0000000..e1094be
--- /dev/null
+++ b/core/res/res/drawable-mdpi/checkbox_disabled_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_disabled_off_holo_light.png b/core/res/res/drawable-mdpi/checkbox_disabled_off_holo_light.png
new file mode 100644
index 0000000..c17377c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/checkbox_disabled_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_disabled_on_holo_dark.png b/core/res/res/drawable-mdpi/checkbox_disabled_on_holo_dark.png
new file mode 100644
index 0000000..f2c5290
--- /dev/null
+++ b/core/res/res/drawable-mdpi/checkbox_disabled_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_disabled_on_holo_light.png b/core/res/res/drawable-mdpi/checkbox_disabled_on_holo_light.png
new file mode 100644
index 0000000..06bd903
--- /dev/null
+++ b/core/res/res/drawable-mdpi/checkbox_disabled_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_focused_off_holo_dark.png b/core/res/res/drawable-mdpi/checkbox_focused_off_holo_dark.png
new file mode 100644
index 0000000..be624c2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/checkbox_focused_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_focused_off_holo_light.png b/core/res/res/drawable-mdpi/checkbox_focused_off_holo_light.png
new file mode 100644
index 0000000..2493ce2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/checkbox_focused_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_focused_on_holo_dark.png b/core/res/res/drawable-mdpi/checkbox_focused_on_holo_dark.png
new file mode 100644
index 0000000..7cdc1df
--- /dev/null
+++ b/core/res/res/drawable-mdpi/checkbox_focused_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_focused_on_holo_light.png b/core/res/res/drawable-mdpi/checkbox_focused_on_holo_light.png
new file mode 100644
index 0000000..f977e72
--- /dev/null
+++ b/core/res/res/drawable-mdpi/checkbox_focused_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_normal_off_holo_dark.png b/core/res/res/drawable-mdpi/checkbox_normal_off_holo_dark.png
new file mode 100644
index 0000000..f824f76
--- /dev/null
+++ b/core/res/res/drawable-mdpi/checkbox_normal_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_normal_off_holo_light.png b/core/res/res/drawable-mdpi/checkbox_normal_off_holo_light.png
new file mode 100644
index 0000000..a76f68c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/checkbox_normal_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_normal_on_holo_dark.png b/core/res/res/drawable-mdpi/checkbox_normal_on_holo_dark.png
new file mode 100644
index 0000000..e4fd418
--- /dev/null
+++ b/core/res/res/drawable-mdpi/checkbox_normal_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_normal_on_holo_light.png b/core/res/res/drawable-mdpi/checkbox_normal_on_holo_light.png
new file mode 100644
index 0000000..d572ef5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/checkbox_normal_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_pressed_off_holo_dark.png b/core/res/res/drawable-mdpi/checkbox_pressed_off_holo_dark.png
new file mode 100644
index 0000000..686707e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/checkbox_pressed_off_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_pressed_off_holo_light.png b/core/res/res/drawable-mdpi/checkbox_pressed_off_holo_light.png
new file mode 100644
index 0000000..17dd1da
--- /dev/null
+++ b/core/res/res/drawable-mdpi/checkbox_pressed_off_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_pressed_on_holo_dark.png b/core/res/res/drawable-mdpi/checkbox_pressed_on_holo_dark.png
new file mode 100644
index 0000000..8cf2b1b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/checkbox_pressed_on_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/checkbox_pressed_on_holo_light.png b/core/res/res/drawable-mdpi/checkbox_pressed_on_holo_light.png
new file mode 100644
index 0000000..c2df6da
--- /dev/null
+++ b/core/res/res/drawable-mdpi/checkbox_pressed_on_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_bottom_holo.9.png b/core/res/res/drawable-mdpi/dialog_bottom_holo.9.png
new file mode 100644
index 0000000..cb3d0f2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/dialog_bottom_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_full_holo.9.png b/core/res/res/drawable-mdpi/dialog_full_holo.9.png
new file mode 100644
index 0000000..0ec9421
--- /dev/null
+++ b/core/res/res/drawable-mdpi/dialog_full_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_middle_holo.9.png b/core/res/res/drawable-mdpi/dialog_middle_holo.9.png
new file mode 100644
index 0000000..36da5ca
--- /dev/null
+++ b/core/res/res/drawable-mdpi/dialog_middle_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/dialog_top_holo.9.png b/core/res/res/drawable-mdpi/dialog_top_holo.9.png
new file mode 100644
index 0000000..1ed519b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/dialog_top_holo.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_horizontal_holo_dark.9.png b/core/res/res/drawable-mdpi/divider_horizontal_holo_dark.9.png
new file mode 100644
index 0000000..d6548c6
--- /dev/null
+++ b/core/res/res/drawable-mdpi/divider_horizontal_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_horizontal_holo_light.9.png b/core/res/res/drawable-mdpi/divider_horizontal_holo_light.9.png
new file mode 100644
index 0000000..9a42dd2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/divider_horizontal_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_vertical_holo_dark.9.png b/core/res/res/drawable-mdpi/divider_vertical_holo_dark.9.png
new file mode 100644
index 0000000..4c6968c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/divider_vertical_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/divider_vertical_holo_light.9.png b/core/res/res/drawable-mdpi/divider_vertical_holo_light.9.png
new file mode 100644
index 0000000..7ddf1b6
--- /dev/null
+++ b/core/res/res/drawable-mdpi/divider_vertical_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_close_normal_holo.png b/core/res/res/drawable-mdpi/ic_dialog_close_normal_holo.png
new file mode 100644
index 0000000..7f2a029
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_dialog_close_normal_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_close_pressed_holo.png b/core/res/res/drawable-mdpi/ic_dialog_close_pressed_holo.png
new file mode 100644
index 0000000..daa8e18
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_dialog_close_pressed_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_dialog_focused_holo.png b/core/res/res/drawable-mdpi/ic_dialog_focused_holo.png
new file mode 100644
index 0000000..179f2de
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_dialog_focused_holo.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_arrow_left_holo_dark.png b/core/res/res/drawable-mdpi/tab_arrow_left_holo_dark.png
new file mode 100644
index 0000000..4f8bafe
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_arrow_left_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_arrow_left_holo_light.png b/core/res/res/drawable-mdpi/tab_arrow_left_holo_light.png
new file mode 100644
index 0000000..8e225fc
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_arrow_left_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_arrow_right_holo_dark.png b/core/res/res/drawable-mdpi/tab_arrow_right_holo_dark.png
new file mode 100644
index 0000000..0a8006d
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_arrow_right_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_arrow_right_holo_light.png b/core/res/res/drawable-mdpi/tab_arrow_right_holo_light.png
new file mode 100644
index 0000000..85aae47
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_arrow_right_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_divider_holo_dark.png b/core/res/res/drawable-mdpi/tab_divider_holo_dark.png
new file mode 100644
index 0000000..89d7b8b
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_divider_holo_dark.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_divider_holo_light.png b/core/res/res/drawable-mdpi/tab_divider_holo_light.png
new file mode 100644
index 0000000..878b2b4
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_divider_holo_light.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_selector_holo_dark.9.png b/core/res/res/drawable-mdpi/tab_selector_holo_dark.9.png
new file mode 100644
index 0000000..30d30df
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_selector_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_default_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_default_holo_dark.9.png
index a9a2cc6..3a5f36d 100644
--- a/core/res/res/drawable-mdpi/textfield_default_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_default_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_default_holo_light.9.png
index 36003cf..b8cc76f 100644
--- a/core/res/res/drawable-mdpi/textfield_default_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_disabled_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_disabled_holo_dark.9.png
index cec82dd..a1f0c71 100644
--- a/core/res/res/drawable-mdpi/textfield_disabled_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_disabled_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_disabled_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_disabled_holo_light.9.png
index 8a9b11f..71e3103 100644
--- a/core/res/res/drawable-mdpi/textfield_disabled_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_disabled_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_disabled_selected_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_disabled_selected_holo_dark.9.png
index 545924c..ac6d406 100644
--- a/core/res/res/drawable-mdpi/textfield_disabled_selected_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_disabled_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_disabled_selected_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_disabled_selected_holo_light.9.png
index 53ee26c..bb6e953 100644
--- a/core/res/res/drawable-mdpi/textfield_disabled_selected_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_disabled_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_pressed_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_pressed_holo_dark.9.png
index 0e7c24d..7667d95 100644
--- a/core/res/res/drawable-mdpi/textfield_pressed_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_pressed_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_pressed_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_pressed_holo_light.9.png
index fee09a6..269affd 100644
--- a/core/res/res/drawable-mdpi/textfield_pressed_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_pressed_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png
new file mode 100644
index 0000000..3549948
--- /dev/null
+++ b/core/res/res/drawable-mdpi/textfield_search_default_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png
new file mode 100644
index 0000000..6db03cb
--- /dev/null
+++ b/core/res/res/drawable-mdpi/textfield_search_default_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png
new file mode 100644
index 0000000..670439a
--- /dev/null
+++ b/core/res/res/drawable-mdpi/textfield_search_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png
new file mode 100644
index 0000000..90e26e2
--- /dev/null
+++ b/core/res/res/drawable-mdpi/textfield_search_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_selected_holo_dark.9.png b/core/res/res/drawable-mdpi/textfield_selected_holo_dark.9.png
index 0e7c24d..7667d95 100644
--- a/core/res/res/drawable-mdpi/textfield_selected_holo_dark.9.png
+++ b/core/res/res/drawable-mdpi/textfield_selected_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_selected_holo_light.9.png b/core/res/res/drawable-mdpi/textfield_selected_holo_light.9.png
index fee09a6..269affd 100644
--- a/core/res/res/drawable-mdpi/textfield_selected_holo_light.9.png
+++ b/core/res/res/drawable-mdpi/textfield_selected_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable/btn_default_holo_dark.xml b/core/res/res/drawable/btn_default_holo_dark.xml
new file mode 100644
index 0000000..c250070
--- /dev/null
+++ b/core/res/res/drawable/btn_default_holo_dark.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_window_focused="false" android:state_enabled="true"
+ android:drawable="@drawable/btn_default_normal_holo_dark" />
+ <item android:state_window_focused="false" android:state_enabled="false"
+ android:drawable="@drawable/btn_default_disabled_holo_dark" />
+ <item android:state_pressed="true"
+ android:drawable="@drawable/btn_default_pressed_holo_dark" />
+ <item android:state_focused="true" android:state_enabled="true"
+ android:drawable="@drawable/btn_default_focused_holo_dark" />
+ <item android:state_enabled="true"
+ android:drawable="@drawable/btn_default_normal_holo_dark" />
+ <item android:state_focused="true"
+ android:drawable="@drawable/btn_default_disabled_focused_holo_dark" />
+ <item
+ android:drawable="@drawable/btn_default_disabled_holo_dark" />
+</selector>
diff --git a/core/res/res/drawable/btn_toggle_holo_dark.xml b/core/res/res/drawable/btn_toggle_holo_dark.xml
new file mode 100644
index 0000000..658ca9e
--- /dev/null
+++ b/core/res/res/drawable/btn_toggle_holo_dark.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_checked="true"
+ android:state_window_focused="false" android:state_enabled="true"
+ android:drawable="@drawable/btn_toggle_on_normal_holo_dark" />
+ <item android:state_checked="true"
+ android:state_window_focused="false" android:state_enabled="false"
+ android:drawable="@drawable/btn_toggle_on_disabled_holo_dark" />
+ <item android:state_checked="true" android:state_pressed="true"
+ android:drawable="@drawable/btn_toggle_on_pressed_holo_dark" />
+ <item android:state_checked="true"
+ android:state_focused="true" android:state_enabled="true"
+ android:drawable="@drawable/btn_toggle_on_focused_holo_dark" />
+ <item android:state_checked="true" android:state_enabled="true"
+ android:drawable="@drawable/btn_toggle_on_normal_holo_dark" />
+ <item android:state_checked="true" android:state_focused="true"
+ android:drawable="@drawable/btn_toggle_on_disabled_focused_holo_dark" />
+ <item android:state_checked="true"
+ android:drawable="@drawable/btn_toggle_on_disabled_holo_dark" />
+
+ <item android:state_window_focused="false" android:state_enabled="true"
+ android:drawable="@drawable/btn_toggle_off_normal_holo_dark" />
+ <item android:state_window_focused="false" android:state_enabled="false"
+ android:drawable="@drawable/btn_toggle_off_disabled_holo_dark" />
+ <item android:state_pressed="true"
+ android:drawable="@drawable/btn_toggle_off_pressed_holo_dark" />
+ <item android:state_focused="true" android:state_enabled="true"
+ android:drawable="@drawable/btn_toggle_off_focused_holo_dark" />
+ <item android:state_enabled="true"
+ android:drawable="@drawable/btn_toggle_off_normal_holo_dark" />
+ <item android:state_focused="true"
+ android:drawable="@drawable/btn_toggle_off_disabled_focused_holo_dark" />
+ <item
+ android:drawable="@drawable/btn_toggle_off_disabled_holo_dark" />
+</selector>
diff --git a/core/res/res/drawable/btn_toggle_holo_light.xml b/core/res/res/drawable/btn_toggle_holo_light.xml
new file mode 100644
index 0000000..d3f1012
--- /dev/null
+++ b/core/res/res/drawable/btn_toggle_holo_light.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_checked="true"
+ android:state_window_focused="false" android:state_enabled="true"
+ android:drawable="@drawable/btn_toggle_on_normal_holo_light" />
+ <item android:state_checked="true"
+ android:state_window_focused="false" android:state_enabled="false"
+ android:drawable="@drawable/btn_toggle_on_disabled_holo_light" />
+ <item android:state_checked="true" android:state_pressed="true"
+ android:drawable="@drawable/btn_toggle_on_pressed_holo_light" />
+ <item android:state_checked="true"
+ android:state_focused="true" android:state_enabled="true"
+ android:drawable="@drawable/btn_toggle_on_focused_holo_light" />
+ <item android:state_checked="true" android:state_enabled="true"
+ android:drawable="@drawable/btn_toggle_on_normal_holo_light" />
+ <item android:state_checked="true" android:state_focused="true"
+ android:drawable="@drawable/btn_toggle_on_disabled_focused_holo_light" />
+ <item android:state_checked="true"
+ android:drawable="@drawable/btn_toggle_on_disabled_holo_light" />
+
+ <item android:state_window_focused="false" android:state_enabled="true"
+ android:drawable="@drawable/btn_toggle_off_normal_holo_light" />
+ <item android:state_window_focused="false" android:state_enabled="false"
+ android:drawable="@drawable/btn_toggle_off_disabled_holo_light" />
+ <item android:state_pressed="true"
+ android:drawable="@drawable/btn_toggle_off_pressed_holo_light" />
+ <item android:state_focused="true" android:state_enabled="true"
+ android:drawable="@drawable/btn_toggle_off_focused_holo_light" />
+ <item android:state_enabled="true"
+ android:drawable="@drawable/btn_toggle_off_normal_holo_light" />
+ <item android:state_focused="true"
+ android:drawable="@drawable/btn_toggle_off_disabled_focused_holo_light" />
+ <item
+ android:drawable="@drawable/btn_toggle_off_disabled_holo_light" />
+</selector>
diff --git a/core/res/res/drawable/cab_ic_close_holo.xml b/core/res/res/drawable/cab_ic_close_holo.xml
new file mode 100644
index 0000000..1baf7cc
--- /dev/null
+++ b/core/res/res/drawable/cab_ic_close_holo.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_pressed="true"
+ android:drawable="@drawable/cab_ic_close_pressed_holo" />
+ <item android:state_focused="true"
+ android:drawable="@drawable/cab_ic_close_focused_holo" />
+ <item android:drawable="@drawable/cab_ic_close_normal_holo" />
+</selector>
diff --git a/core/res/res/layout/select_dialog.xml b/core/res/res/layout/select_dialog.xml
index c665f7a..94dcb6a 100644
--- a/core/res/res/layout/select_dialog.xml
+++ b/core/res/res/layout/select_dialog.xml
@@ -30,5 +30,5 @@
android:layout_height="match_parent"
android:layout_marginTop="5px"
android:cacheColorHint="@null"
- android:divider="@android:drawable/divider_horizontal_bright"
+ android:divider="?android:attr/listDividerAlertDialog"
android:scrollbars="vertical" />
diff --git a/core/res/res/layout/select_dialog_item.xml b/core/res/res/layout/select_dialog_item.xml
index 30fe02e..96fdcc6 100644
--- a/core/res/res/layout/select_dialog_item.xml
+++ b/core/res/res/layout/select_dialog_item.xml
@@ -29,7 +29,7 @@
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:textAppearance="?android:attr/textAppearanceLarge"
- android:textColor="@android:color/primary_text_light_disable_only"
+ android:textColor="?android:attr/textColorAlertDialogListItem"
android:gravity="center_vertical"
android:paddingLeft="14dip"
android:paddingRight="15dip"
diff --git a/core/res/res/layout/select_dialog_multichoice.xml b/core/res/res/layout/select_dialog_multichoice.xml
index b646a4c..a9be014 100644
--- a/core/res/res/layout/select_dialog_multichoice.xml
+++ b/core/res/res/layout/select_dialog_multichoice.xml
@@ -20,7 +20,7 @@
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:textAppearance="?android:attr/textAppearanceLarge"
- android:textColor="@android:color/primary_text_light_disable_only"
+ android:textColor="?android:attr/textColorAlertDialogListItem"
android:gravity="center_vertical"
android:paddingLeft="12dip"
android:paddingRight="7dip"
diff --git a/core/res/res/layout/select_dialog_singlechoice.xml b/core/res/res/layout/select_dialog_singlechoice.xml
index c3c2073..1b9c973 100644
--- a/core/res/res/layout/select_dialog_singlechoice.xml
+++ b/core/res/res/layout/select_dialog_singlechoice.xml
@@ -20,7 +20,7 @@
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:textAppearance="?android:attr/textAppearanceLarge"
- android:textColor="@android:color/primary_text_light_disable_only"
+ android:textColor="?android:attr/textColorAlertDialogListItem"
android:gravity="center_vertical"
android:paddingLeft="12dip"
android:paddingRight="7dip"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 19b76ab..317b3f3 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -101,6 +101,9 @@
<attr name="textColorHighlightInverse" format="reference|color" />
<!-- Color of link text (URLs), when used in a light theme. @hide -->
<attr name="textColorLinkInverse" format="reference|color" />
+
+ <!-- Color of list item text in alert dialogs. -->
+ <attr name="textColorAlertDialogListItem" format="reference|color" />
<!-- Search widget more corpus result item background. -->
<attr name="searchWidgetCorpusItemBackground" format="reference|color" />
@@ -197,6 +200,8 @@
<!-- The list item height for search results. @hide -->
<attr name="searchResultListItemHeight" format="dimension" />
<attr name="listDivider" format="reference" />
+ <!-- The list divider used in alert dialogs. -->
+ <attr name="listDividerAlertDialog" format="reference" />
<!-- TextView style for list separators. -->
<attr name="listSeparatorTextViewStyle" format="reference" />
<!-- The preferred left padding for an expandable list item (for child-specific layouts,
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index e9a4ca3..623368d 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -18,8 +18,8 @@
*/
-->
<resources>
- <drawable name="screen_background_light">#ffefefef</drawable>
- <drawable name="screen_background_dark">#ff101010</drawable>
+ <drawable name="screen_background_light">#fff3f3f3</drawable>
+ <drawable name="screen_background_dark">#ff000000</drawable>
<drawable name="status_bar_closed_default_background">#ff000000</drawable>
<drawable name="status_bar_opened_default_background">#ff000000</drawable>
<drawable name="search_bar_default_color">#ff000000</drawable>
@@ -36,8 +36,8 @@
<color name="white">#ffffffff</color>
<color name="black">#ff000000</color>
<color name="transparent">#00000000</color>
- <color name="background_dark">#ff101010</color>
- <color name="background_light">#ffefefef</color>
+ <color name="background_dark">#ff000000</color>
+ <color name="background_light">#fff3f3f3</color>
<color name="bright_foreground_dark">@android:color/background_light</color>
<color name="bright_foreground_light">@android:color/background_dark</color>
<color name="bright_foreground_dark_disabled">#80ffffff</color>
@@ -103,5 +103,32 @@
<color name="keyguard_text_color_soundon">#e69310</color>
<color name="keyguard_text_color_decline">#fe0a5a</color>
+ <!-- For holo theme -->
+ <drawable name="screen_background_holo_light">#fff3f3f3</drawable>
+ <drawable name="screen_background_holo_dark">#ff000000</drawable>
+ <color name="background_holo_dark">#ff000000</color>
+ <color name="background_holo_light">#fff3f3f3</color>
+ <color name="bright_foreground_holo_dark">@android:color/background_holo_light</color>
+ <color name="bright_foreground_holo_light">@android:color/background_holo_dark</color>
+ <color name="bright_foreground_disabled_holo_dark">#80ffffff</color>
+ <color name="bright_foreground_disabled_holo_light">#80000000</color>
+ <color name="bright_foreground_inverse_holo_dark">@android:color/bright_foreground_holo_light</color>
+ <color name="bright_foreground_inverse_holo_light">@android:color/bright_foreground_holo_dark</color>
+ <color name="dim_foreground_holo_dark">#bebebe</color>
+ <color name="dim_foreground_disabled_holo_dark">#80bebebe</color>
+ <color name="dim_foreground_inverse_holo_dark">#323232</color>
+ <color name="dim_foreground_inverse_disabled_holo_dark">#80323232</color>
+ <color name="hint_foreground_holo_dark">#808080</color>
+ <color name="dim_foreground_holo_light">#323232</color>
+ <color name="dim_foreground_disabled_holo_light">#80323232</color>
+ <color name="dim_foreground_inverse_holo_light">#bebebe</color>
+ <color name="dim_foreground_inverse_disabled_holo_light">#80bebebe</color>
+ <color name="hint_foreground_holo_light">#808080</color>
+ <color name="highlight_background_holo">#cc475925</color>
+ <color name="highlight_background_inverse_holo">#ccd2e461</color>
+ <color name="highlighted_text_holo_dark">#cc475925</color>
+ <color name="highlighted_text_holo_light">#ccd2e461</color>
+ <color name="link_text_holo_dark">#5c5cff</color>
+ <color name="link_text_holo_light">#0000ee</color>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index cdeb899..adcbb10 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1358,6 +1358,8 @@
<public type="attr" name="textAppearanceSmallPopupMenu" />
<public type="attr" name="breadCrumbTitle" />
<public type="attr" name="breadCrumbShortTitle" />
+ <public type="attr" name="listDividerAlertDialog" />
+ <public type="attr" name="textColorAlertDialogListItem" />
<public type="anim" name="animator_fade_in" />
<public type="anim" name="animator_fade_out" />
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index ebaaada..6e9530c 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -984,4 +984,706 @@
<item name="android:textColor">@android:color/secondary_text_light</item>
</style>
+ <!-- Begin Holo theme styles -->
+
+ <!-- Text Styles -->
+ <style name="TextAppearance.Holo" parent="TextAppearance">
+ </style>
+
+ <style name="TextAppearance.Holo.Inverse" parent="TextAppearance.Inverse">
+ <item name="android:textColor">?textColorPrimaryInverse</item>
+ <item name="android:textColorHint">?textColorHintInverse</item>
+ <item name="android:textColorHighlight">?textColorHighlightInverse</item>
+ <item name="android:textColorLink">?textColorLinkInverse</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Large" parent="TextAppearance.Large">
+ </style>
+
+ <style name="TextAppearance.Holo.Medium" parent="TextAppearance.Medium">
+ </style>
+
+ <style name="TextAppearance.Holo.Small" parent="TextAppearance.Small">
+ </style>
+
+ <style name="TextAppearance.Holo.Large.Inverse">
+ <item name="android:textColor">?textColorPrimaryInverse</item>
+ <item name="android:textColorHint">?textColorHintInverse</item>
+ <item name="android:textColorHighlight">?textColorHighlightInverse</item>
+ <item name="android:textColorLink">?textColorLinkInverse</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Medium.Inverse">
+ <item name="android:textColor">?textColorPrimaryInverse</item>
+ <item name="android:textColorHint">?textColorHintInverse</item>
+ <item name="android:textColorHighlight">?textColorHighlightInverse</item>
+ <item name="android:textColorLink">?textColorLinkInverse</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Small.Inverse">
+ <item name="android:textColor">?textColorPrimaryInverse</item>
+ <item name="android:textColorHint">?textColorHintInverse</item>
+ <item name="android:textColorHighlight">?textColorHighlightInverse</item>
+ <item name="android:textColorLink">?textColorLinkInverse</item>
+ </style>
+
+ <style name="TextAppearance.Holo.SearchResult">
+ </style>
+
+ <style name="TextAppearance.Holo.SearchResult.Title">
+ </style>
+
+ <style name="TextAppearance.Holo.SearchResult.Subtitle">
+ </style>
+
+ <style name="TextAppearance.Holo.Widget" parent="TextAppearance.Widget">
+ </style>
+
+ <style name="TextAppearance.Holo.Widget.Button" parent="TextAppearance.Holo.Small.Inverse">
+ <item name="android:textColor">@android:color/primary_text_light_nodisable</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Widget.IconMenu.Item" parent="TextAppearance.Holo.Small">
+ <item name="android:textColor">?textColorPrimary</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Widget.TabWidget">
+ <item name="android:textSize">14sp</item>
+ <item name="android:textStyle">normal</item>
+ <item name="android:textColor">@android:color/tab_indicator_text</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Widget.TextView">
+ <item name="android:textColor">?textColorPrimaryDisableOnly</item>
+ <item name="android:textColorHint">?textColorHint</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Widget.TextView.PopupMenu">
+ <item name="android:textSize">18sp</item>
+ <item name="android:textColor">?textColorPrimaryDisableOnly</item>
+ <item name="android:textColorHint">?textColorHint</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Widget.DropDownHint">
+ <item name="android:textColor">?textColorPrimaryInverse</item>
+ <item name="android:textSize">14sp</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Widget.DropDownItem">
+ <item name="android:textColor">@android:color/primary_text_light_disable_only</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Widget.TextView.SpinnerItem">
+ <item name="android:textColor">@android:color/primary_text_light_disable_only</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Widget.EditText">
+ <item name="android:textColor">@color/widget_edittext_holo_dark</item>
+ <item name="android:textColorHint">@android:color/hint_foreground_holo_light</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Widget.PopupMenu" parent="TextAppearance.Widget.PopupMenu">
+ </style>
+
+ <style name="TextAppearance.Holo.Widget.PopupMenu.Large" parent="TextAppearance.Widget.PopupMenu.Large">
+ </style>
+
+ <style name="TextAppearance.Holo.Widget.PopupMenu.Small" parent="TextAppearance.Widget.PopupMenu.Small">
+ </style>
+
+ <style name="TextAppearance.Holo.Widget.ActionBar.Title"
+ parent="TextAppearance.Holo.Medium">
+ </style>
+
+ <style name="TextAppearance.Holo.Widget.ActionBar.Subtitle"
+ parent="TextAppearance.Holo.Small">
+ </style>
+
+ <style name="TextAppearance.Holo.Widget.ActionMode">
+ </style>
+
+ <style name="TextAppearance.Holo.Widget.ActionMode.Title" parent="TextAppearance.Widget.ActionMode.Title">
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Widget.ActionMode.Subtitle" parent="TextAppearance.Widget.ActionMode.Subtitle">
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
+ </style>
+
+ <style name="TextAppearance.Holo.WindowTitle">
+ <item name="android:textColor">#fff</item>
+ <item name="android:textSize">14sp</item>
+ <item name="android:textStyle">bold</item>
+ </style>
+
+ <style name="TextAppearance.Holo.DialogWindowTitle">
+ <item name="android:textSize">18sp</item>
+ </style>
+
+ <!-- Light text styles -->
+ <style name="TextAppearance.Holo.Light" parent="TextAppearance.Holo">
+ </style>
+
+ <style name="TextAppearance.Holo.Light.Inverse">
+ <item name="android:textColor">?textColorPrimaryInverse</item>
+ <item name="android:textColorHint">?textColorHintInverse</item>
+ <item name="android:textColorHighlight">?textColorHighlightInverse</item>
+ <item name="android:textColorLink">?textColorLinkInverse</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Light.Large">
+ </style>
+
+ <style name="TextAppearance.Holo.Light.Medium">
+ </style>
+
+ <style name="TextAppearance.Holo.Light.Small">
+ </style>
+
+ <style name="TextAppearance.Holo.Light.Large.Inverse">
+ <item name="android:textColor">?textColorPrimaryInverse</item>
+ <item name="android:textColorHint">?textColorHintInverse</item>
+ <item name="android:textColorHighlight">?textColorHighlightInverse</item>
+ <item name="android:textColorLink">?textColorLinkInverse</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Light.Medium.Inverse">
+ <item name="android:textColor">?textColorPrimaryInverse</item>
+ <item name="android:textColorHint">?textColorHintInverse</item>
+ <item name="android:textColorHighlight">?textColorHighlightInverse</item>
+ <item name="android:textColorLink">?textColorLinkInverse</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Light.Small.Inverse">
+ <item name="android:textColor">?textColorPrimaryInverse</item>
+ <item name="android:textColorHint">?textColorHintInverse</item>
+ <item name="android:textColorHighlight">?textColorHighlightInverse</item>
+ <item name="android:textColorLink">?textColorLinkInverse</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Light.SearchResult" parent="TextAppearance.Holo.SearchResult">
+ </style>
+
+ <style name="TextAppearance.Holo.Light.SearchResult.Title">
+ </style>
+
+ <style name="TextAppearance.Holo.Light.SearchResult.Subtitle">
+ </style>
+
+ <style name="TextAppearance.Holo.Light.Widget" parent="TextAppearance.Widget">
+ </style>
+
+ <style name="TextAppearance.Holo.Light.Widget.Button">
+ </style>
+
+ <style name="TextAppearance.Holo.Light.Widget.EditText">
+ <item name="android:textColor">@color/widget_edittext_holo_light</item>
+ <item name="android:textColorHint">@android:color/hint_foreground_holo_dark</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Light.Widget.PopupMenu" parent="TextAppearance.Holo.Widget.PopupMenu">
+ </style>
+
+ <style name="TextAppearance.Holo.Light.Widget.PopupMenu.Large" parent="TextAppearance.Holo.Widget.PopupMenu.Large">
+ </style>
+
+ <style name="TextAppearance.Holo.Light.Widget.PopupMenu.Small" parent="TextAppearance.Holo.Widget.PopupMenu.Small">
+ </style>
+
+ <style name="TextAppearance.Holo.Light.Widget.DropDownHint" parent="TextAppearance.Holo.Widget.DropDownHint">
+ </style>
+
+ <style name="TextAppearance.Holo.Light.Widget.ActionMode.Title" parent="TextAppearance.Widget.ActionMode.Title">
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Light.Widget.ActionMode.Subtitle" parent="TextAppearance.Widget.ActionMode.Subtitle">
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Light.WindowTitle">
+ <item name="android:textColor">#fff</item>
+ <item name="android:textSize">14sp</item>
+ <item name="android:textStyle">bold</item>
+ </style>
+
+ <style name="TextAppearance.Holo.Light.DialogWindowTitle">
+ <item name="android:textSize">18sp</item>
+ </style>
+
+ <!-- Widget Styles -->
+
+ <style name="Widget.Holo" parent="Widget">
+ </style>
+
+ <style name="Widget.Holo.Button" parent="Widget.Button">
+ <item name="android:background">@android:drawable/btn_default_holo_dark</item>
+ <item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
+ <item name="android:textColor">@android:color/primary_text_holo_dark</item>
+ <item name="android:minHeight">48dip</item>
+ <item name="android:paddingLeft">32dip</item>
+ <item name="android:paddingRight">32dip</item>
+ </style>
+
+ <style name="Widget.Holo.Button.Small">
+ <item name="android:background">@android:drawable/btn_default_holo_dark</item>
+ <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
+ <item name="android:textColor">@android:color/primary_text_holo_dark</item>
+ <item name="android:minHeight">40dip</item>
+ <item name="android:paddingLeft">24dip</item>
+ <item name="android:paddingRight">24dip</item>
+ </style>
+
+ <style name="Widget.Holo.Button.Inset">
+ <item name="android:background">@android:drawable/button_inset</item>
+ </style>
+
+ <style name="Widget.Holo.Button.Toggle">
+ <item name="android:background">@android:drawable/btn_toggle_holo_dark</item>
+ <item name="android:textOn">@android:string/capital_on</item>
+ <item name="android:textOff">@android:string/capital_off</item>
+ <item name="android:disabledAlpha">?android:attr/disabledAlpha</item>
+ <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
+ <item name="android:minHeight">48dip</item>
+ <item name="android:paddingLeft">24dip</item>
+ <item name="android:paddingRight">24dip</item>
+ </style>
+
+ <style name="Widget.Holo.TextView" parent="Widget.TextView">
+ </style>
+
+ <style name="Widget.Holo.TextView.ListSeparator" parent="Widget.TextView.ListSeparator">
+ </style>
+
+ <style name="Widget.Holo.TextSelectHandle" parent="Widget.TextSelectHandle">
+ </style>
+
+ <style name="Widget.Holo.AbsListView" parent="Widget.AbsListView">
+ </style>
+
+ <style name="Widget.Holo.AutoCompleteTextView" parent="Widget.AutoCompleteTextView">
+ </style>
+
+ <style name="Widget.Holo.CompoundButton.CheckBox" parent="Widget.CompoundButton.CheckBox">
+ </style>
+
+ <style name="Widget.Holo.ListView.DropDown">
+ </style>
+
+ <style name="Widget.Holo.EditText" parent="Widget.EditText">
+ </style>
+
+ <style name="Widget.Holo.ExpandableListView" parent="Widget.ExpandableListView">
+ </style>
+
+ <style name="Widget.Holo.ExpandableListView.White">
+ </style>
+
+ <style name="Widget.Holo.Gallery" parent="Widget.Gallery">
+ </style>
+
+ <style name="Widget.Holo.GestureOverlayView" parent="Widget.GestureOverlayView">
+ </style>
+
+ <style name="Widget.Holo.GridView" parent="Widget.GridView">
+ </style>
+
+ <style name="Widget.Holo.ImageButton" parent="Widget.ImageButton">
+ </style>
+
+ <style name="Widget.Holo.ImageWell" parent="Widget.ImageWell">
+ </style>
+
+ <style name="Widget.Holo.ListView" parent="Widget.ListView">
+ </style>
+
+ <style name="Widget.Holo.ListView.White">
+ </style>
+
+ <style name="Widget.Holo.PopupWindow" parent="Widget.PopupWindow">
+ </style>
+
+ <style name="Widget.Holo.ProgressBar" parent="Widget.ProgressBar">
+ </style>
+
+ <style name="Widget.Holo.ProgressBar.Horizontal" parent="Widget.ProgressBar.Horizontal">
+ </style>
+
+ <style name="Widget.Holo.ProgressBar.Small" parent="Widget.ProgressBar.Horizontal">
+ </style>
+
+ <style name="Widget.Holo.ProgressBar.Small.Title" parent="Widget.ProgressBar.Small.Title">
+ </style>
+
+ <style name="Widget.Holo.ProgressBar.Large" parent="Widget.ProgressBar.Large">
+ </style>
+
+ <style name="Widget.Holo.ProgressBar.Inverse" parent="Widget.ProgressBar.Inverse">
+ </style>
+
+ <style name="Widget.Holo.ProgressBar.Small.Inverse" parent="Widget.ProgressBar.Small.Inverse">
+ </style>
+
+ <style name="Widget.Holo.ProgressBar.Large.Inverse" parent="Widget.ProgressBar.Large.Inverse">
+ </style>
+
+ <style name="Widget.Holo.SeekBar" parent="Widget.SeekBar">
+ </style>
+
+ <style name="Widget.Holo.RatingBar" parent="Widget.RatingBar">
+ </style>
+
+ <style name="Widget.Holo.RatingBar.Indicator" parent="Widget.RatingBar.Indicator">
+ </style>
+
+ <style name="Widget.Holo.RatingBar.Small">
+ </style>
+
+ <style name="Widget.Holo.CompoundButton.RadioButton" parent="Widget.CompoundButton.RadioButton">
+ </style>
+
+ <style name="Widget.Holo.ScrollView" parent="Widget.ScrollView">
+ </style>
+
+ <style name="Widget.Holo.HorizontalScrollView" parent="Widget.HorizontalScrollView">
+ </style>
+
+ <style name="Widget.Holo.Spinner" parent="Widget.Spinner.DropDown">
+ </style>
+
+ <style name="Widget.Holo.Spinner.DropDown">
+ </style>
+
+ <style name="Widget.Holo.CompoundButton.Star" parent="Widget.CompoundButton.Star">
+ </style>
+
+ <style name="Widget.Holo.TabWidget" parent="Widget.TabWidget">
+ </style>
+
+ <style name="Widget.Holo.WebTextView" parent="Widget.WebTextView">
+ </style>
+
+ <style name="Widget.Holo.WebView" parent="Widget.WebView">
+ </style>
+
+ <style name="Widget.Holo.DropDownItem" parent="Widget.DropDownItem">
+ </style>
+
+ <style name="Widget.Holo.DropDownItem.Spinner">
+ </style>
+
+ <style name="Widget.Holo.TextView.SpinnerItem" parent="Widget.TextView.SpinnerItem">
+ </style>
+
+ <style name="Widget.Holo.KeyboardView" parent="Widget.KeyboardView">
+ </style>
+
+ <style name="Widget.Holo.QuickContactBadge.WindowSmall" parent="Widget.QuickContactBadge.WindowSmall">
+ </style>
+
+ <style name="Widget.Holo.QuickContactBadge.WindowMedium" parent="Widget.QuickContactBadge.WindowMedium">
+ </style>
+
+ <style name="Widget.Holo.QuickContactBadge.WindowLarge" parent="Widget.QuickContactBadge.WindowLarge">
+ </style>
+
+ <style name="Widget.Holo.QuickContactBadgeSmall.WindowSmall" parent="Widget.QuickContactBadgeSmall.WindowSmall">
+ </style>
+
+ <style name="Widget.Holo.QuickContactBadgeSmall.WindowMedium" parent="Widget.QuickContactBadgeSmall.WindowMedium">
+ </style>
+
+ <style name="Widget.Holo.QuickContactBadgeSmall.WindowLarge" parent="Widget.QuickContactBadgeSmall.WindowLarge">
+ </style>
+
+ <style name="Widget.Holo.ListPopupWindow" parent="Widget.ListPopupWindow">
+ </style>
+
+ <style name="Widget.Holo.PopupMenu" parent="Widget.PopupMenu">
+ </style>
+
+ <style name="Widget.Holo.ActionButton" parent="Widget.ActionButton">
+ </style>
+
+ <style name="Widget.Holo.ActionButton.Overflow" parent="Widget.ActionButton.Overflow">
+ </style>
+
+ <style name="Widget.Holo.ActionBarView_TabView" parent="Widget.ActionBarView_TabView">
+ </style>
+
+ <style name="Widget.Holo.ActionBarView_TabBar" parent="Widget.ActionBarView_TabBar">
+ </style>
+
+ <style name="Widget.Holo.ActionBarView_TabText" parent="Widget.ActionBarView_TabText">
+ <item name="android:textAppearance">@style/TextAppearance.Holo.Medium</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:textSize">18sp</item>
+ </style>
+
+ <style name="Widget.Holo.ActionMode" parent="Widget.ActionMode">
+ <item name="android:background">@android:drawable/cab_holo_dark</item>
+ <item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionMode.Title</item>
+ <item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionMode.Subtitle</item>
+ </style>
+
+ <style name="Widget.Holo.ActionButton.CloseMode" parent="Widget.ActionButton.CloseMode">
+ <item name="android:src">@drawable/cab_ic_close_holo</item>
+ </style>
+
+ <style name="Widget.Holo.ActionBar" parent="Widget.ActionBar">
+ <item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Title</item>
+ <item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle</item>
+ </style>
+
+ <!-- Light widget styles -->
+
+ <style name="Widget.Holo.Light">
+ </style>
+
+ <style name="Widget.Holo.Light.Button" parent="Widget.Button">
+ </style>
+
+ <style name="Widget.Holo.Light.Button.Small">
+ </style>
+
+ <style name="Widget.Holo.Light.Button.Inset">
+ </style>
+
+ <style name="Widget.Holo.Light.Button.Toggle">
+ <item name="android:background">@android:drawable/btn_toggle_holo_light</item>
+ <item name="android:textOn">@android:string/capital_on</item>
+ <item name="android:textOff">@android:string/capital_off</item>
+ <item name="android:disabledAlpha">?android:attr/disabledAlpha</item>
+ <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
+ <item name="android:minHeight">48dip</item>
+ <item name="android:paddingLeft">24dip</item>
+ <item name="android:paddingRight">24dip</item>
+ </style>
+
+ <style name="Widget.Holo.Light.TextView" parent="Widget.TextView">
+ </style>
+
+ <style name="Widget.Holo.Light.TextView.ListSeparator" parent="Widget.TextView.ListSeparator">
+ </style>
+
+ <style name="Widget.Holo.Light.TextSelectHandle" parent="Widget.TextSelectHandle">
+ </style>
+
+ <style name="Widget.Holo.Light.AbsListView" parent="Widget.AbsListView">
+ </style>
+
+ <style name="Widget.Holo.Light.AutoCompleteTextView" parent="Widget.AutoCompleteTextView">
+ </style>
+
+ <style name="Widget.Holo.Light.CompoundButton.CheckBox" parent="Widget.CompoundButton.CheckBox">
+ </style>
+
+ <style name="Widget.Holo.Light.ListView.DropDown">
+ </style>
+
+ <style name="Widget.Holo.Light.EditText" parent="Widget.EditText">
+ </style>
+
+ <style name="Widget.Holo.Light.ExpandableListView" parent="Widget.ExpandableListView">
+ </style>
+
+ <style name="Widget.Holo.Light.ExpandableListView.White">
+ </style>
+
+ <style name="Widget.Holo.Light.Gallery" parent="Widget.Gallery">
+ </style>
+
+ <style name="Widget.Holo.Light.GestureOverlayView" parent="Widget.GestureOverlayView">
+ </style>
+
+ <style name="Widget.Holo.Light.GridView" parent="Widget.GridView">
+ </style>
+
+ <style name="Widget.Holo.Light.ImageButton" parent="Widget.ImageButton">
+ </style>
+
+ <style name="Widget.Holo.Light.ImageWell" parent="Widget.ImageWell">
+ </style>
+
+ <style name="Widget.Holo.Light.ListView" parent="Widget.ListView">
+ </style>
+
+ <style name="Widget.Holo.Light.ListView.White">
+ </style>
+
+ <style name="Widget.Holo.Light.PopupWindow" parent="Widget.PopupWindow">
+ </style>
+
+ <style name="Widget.Holo.Light.ProgressBar" parent="Widget.ProgressBar">
+ </style>
+
+ <style name="Widget.Holo.Light.ProgressBar.Horizontal" parent="Widget.ProgressBar.Horizontal">
+ </style>
+
+ <style name="Widget.Holo.Light.ProgressBar.Small" parent="Widget.ProgressBar.Small">
+ </style>
+
+ <style name="Widget.Holo.Light.ProgressBar.Small.Title" parent="Widget.ProgressBar.Small.Title">
+ </style>
+
+ <style name="Widget.Holo.Light.ProgressBar.Large" parent="Widget.ProgressBar.Large">
+ </style>
+
+ <style name="Widget.Holo.Light.ProgressBar.Inverse" parent="Widget.ProgressBar.Inverse">
+ </style>
+
+ <style name="Widget.Holo.Light.ProgressBar.Small.Inverse" parent="Widget.ProgressBar.Small.Inverse">
+ </style>
+
+ <style name="Widget.Holo.Light.ProgressBar.Large.Inverse" parent="Widget.ProgressBar.Large.Inverse">
+ </style>
+
+ <style name="Widget.Holo.Light.SeekBar" parent="Widget.SeekBar">
+ </style>
+
+ <style name="Widget.Holo.Light.RatingBar" parent="Widget.RatingBar">
+ </style>
+
+ <style name="Widget.Holo.Light.RatingBar.Indicator" parent="Widget.RatingBar.Indicator">
+ </style>
+
+ <style name="Widget.Holo.Light.RatingBar.Small">
+ </style>
+
+ <style name="Widget.Holo.Light.CompoundButton.RadioButton" parent="Widget.CompoundButton.RadioButton">
+ </style>
+
+ <style name="Widget.Holo.Light.ScrollView" parent="Widget.ScrollView">
+ </style>
+
+ <style name="Widget.Holo.Light.HorizontalScrollView" parent="Widget.HorizontalScrollView">
+ </style>
+
+ <style name="Widget.Holo.Light.Spinner" parent="Widget.Spinner.DropDown">
+ </style>
+
+ <style name="Widget.Holo.Light.Spinner.DropDown">
+ </style>
+
+ <style name="Widget.Holo.Light.CompoundButton.Star" parent="Widget.CompoundButton.Star">
+ </style>
+
+ <style name="Widget.Holo.Light.TabWidget" parent="Widget.TabWidget">
+ </style>
+
+ <style name="Widget.Holo.Light.WebTextView" parent="Widget.WebTextView">
+ </style>
+
+ <style name="Widget.Holo.Light.WebView" parent="Widget.WebView">
+ </style>
+
+ <style name="Widget.Holo.Light.DropDownItem" parent="Widget.DropDownItem">
+ </style>
+
+ <style name="Widget.Holo.Light.DropDownItem.Spinner">
+ </style>
+
+ <style name="Widget.Holo.Light.TextView.SpinnerItem" parent="Widget.TextView.SpinnerItem">
+ </style>
+
+ <style name="Widget.Holo.Light.KeyboardView" parent="Widget.KeyboardView">
+ </style>
+
+ <style name="Widget.Holo.Light.QuickContactBadge.WindowSmall" parent="Widget.QuickContactBadge.WindowSmall">
+ </style>
+
+ <style name="Widget.Holo.Light.QuickContactBadge.WindowMedium" parent="Widget.QuickContactBadge.WindowMedium">
+ </style>
+
+ <style name="Widget.Holo.Light.QuickContactBadge.WindowLarge" parent="Widget.QuickContactBadge.WindowLarge">
+ </style>
+
+ <style name="Widget.Holo.Light.QuickContactBadgeSmall.WindowSmall" parent="Widget.QuickContactBadgeSmall.WindowSmall">
+ </style>
+
+ <style name="Widget.Holo.Light.QuickContactBadgeSmall.WindowMedium" parent="Widget.QuickContactBadgeSmall.WindowMedium">
+ </style>
+
+ <style name="Widget.Holo.Light.QuickContactBadgeSmall.WindowLarge" parent="Widget.QuickContactBadgeSmall.WindowLarge">
+ </style>
+
+ <style name="Widget.Holo.Light.ListPopupWindow" parent="Widget.ListPopupWindow">
+ </style>
+
+ <style name="Widget.Holo.Light.PopupMenu" parent="Widget.PopupMenu">
+ </style>
+
+ <style name="Widget.Holo.Light.ActionButton" parent="Widget.ActionButton">
+ </style>
+
+ <style name="Widget.Holo.Light.ActionButton.Overflow" parent="Widget.ActionButton.Overflow">
+ </style>
+
+ <style name="Widget.Holo.Light.ActionBarView_TabView" parent="Widget.ActionBarView_TabView">
+ </style>
+
+ <style name="Widget.Holo.Light.ActionBarView_TabBar" parent="Widget.ActionBarView_TabBar">
+ </style>
+
+ <style name="Widget.Holo.Light.ActionBarView_TabText" parent="Widget.ActionBarView_TabText">
+ </style>
+
+ <style name="Widget.Holo.Light.ActionMode" parent="Widget.ActionMode">
+ <item name="android:background">@android:drawable/cab_holo_light</item>
+ <item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionMode.Title</item>
+ <item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionMode.Subtitle</item>
+ </style>
+
+ <style name="Widget.Holo.Light.ActionButton.CloseMode" parent="Widget.ActionButton.CloseMode">
+ </style>
+
+ <style name="Widget.Holo.Light.ActionBar" parent="Widget.ActionBar">
+ <item name="android:titleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Title</item>
+ <item name="android:subtitleTextStyle">@android:style/TextAppearance.Holo.Widget.ActionBar.Subtitle</item>
+ </style>
+
+ <!-- Animation Styles -->
+
+ <style name="Animation.Holo" parent="Animation">
+ </style>
+
+ <style name="Animation.Holo.Activity" parent="Animation.Activity">
+ </style>
+
+ <style name="Animation.Holo.Dialog" parent="Animation.Dialog">
+ </style>
+
+ <!-- Dialog styles -->
+
+ <style name="AlertDialog.Holo" parent="AlertDialog">
+ <item name="fullDark">@android:drawable/dialog_full_holo</item>
+ <item name="topDark">@android:drawable/dialog_top_holo</item>
+ <item name="centerDark">@android:drawable/dialog_middle_holo</item>
+ <item name="bottomDark">@android:drawable/dialog_bottom_holo</item>
+ <item name="fullBright">@android:drawable/dialog_full_holo</item>
+ <item name="topBright">@android:drawable/dialog_top_holo</item>
+ <item name="centerBright">@android:drawable/dialog_middle_holo</item>
+ <item name="bottomBright">@android:drawable/dialog_bottom_holo</item>
+ <item name="bottomMedium">@android:drawable/dialog_bottom_holo</item>
+ <item name="centerMedium">@android:drawable/dialog_middle_holo</item>
+ </style>
+
+ <!-- Window title -->
+ <style name="WindowTitleBackground.Holo">
+ <item name="android:background">@android:drawable/title_bar</item>
+ </style>
+
+ <style name="WindowTitle.Holo">
+ <item name="android:singleLine">true</item>
+ <item name="android:textAppearance">@style/TextAppearance.Holo.WindowTitle</item>
+ <item name="android:shadowColor">#BB000000</item>
+ <item name="android:shadowRadius">2.75</item>
+ </style>
+
+ <style name="DialogWindowTitle.Holo">
+ <item name="android:maxLines">1</item>
+ <item name="android:scrollHorizontally">true</item>
+ <item name="android:textAppearance">@style/TextAppearance.Holo.DialogWindowTitle</item>
+ </style>
+
</resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 9425fc4..21d91ba 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -57,6 +57,7 @@
<item name="textColorHighlightInverse">@android:color/highlighted_text_light</item>
<item name="textColorLink">@android:color/link_text_dark</item>
<item name="textColorLinkInverse">@android:color/link_text_light</item>
+ <item name="textColorAlertDialogListItem">@android:color/primary_text_light_disable_only</item>
<item name="textAppearanceLarge">@android:style/TextAppearance.Large</item>
<item name="textAppearanceMedium">@android:style/TextAppearance.Medium</item>
@@ -102,6 +103,8 @@
<item name="activatedBackgroundIndicator">@android:drawable/activated_background</item>
+ <item name="listDividerAlertDialog">@android:drawable/divider_horizontal_bright</item>
+
<item name="expandableListPreferredItemPaddingLeft">40dip</item>
<item name="expandableListPreferredChildPaddingLeft">
?android:attr/expandableListPreferredItemPaddingLeft</item>
@@ -606,14 +609,230 @@
holographic theme are translucent on their brackground, so applications
must ensure that any background they use with this theme is itself
dark; otherwise, it will be difficult to see the widgets. The new
- UI style also includes a full action bar by default. -->
+ UI style also includes a full action bar by default.
+
+ Styles used by the Holo theme are named using the convention Type.Holo.Etc.
+ (For example, Widget.Holo.Button, TextAppearance.Holo.Widget.PopupMenu.Large.)
+ Specific resources used by Holo are named using the convention @type/foo_bar_baz_holo
+ with trailing _dark or _light specifiers if they are not shared between both light and
+ dark versions of the theme. -->
<style name="Theme.Holo">
- <item name="editTextBackground">@android:drawable/edit_text_holo_dark</item>
+ <item name="colorForeground">@android:color/bright_foreground_holo_dark</item>
+ <item name="colorForegroundInverse">@android:color/bright_foreground_inverse_holo_dark</item>
+ <item name="colorBackground">@android:color/background_holo_dark</item>
+ <item name="colorBackgroundCacheHint">?android:attr/colorBackground</item>
+ <item name="disabledAlpha">0.5</item>
+ <item name="backgroundDimAmount">0.6</item>
+
+ <!-- Text styles -->
+ <item name="textAppearance">@android:style/TextAppearance.Holo</item>
+ <item name="textAppearanceInverse">@android:style/TextAppearance.Holo.Inverse</item>
+
+ <item name="textColorPrimary">@android:color/primary_text_holo_dark</item>
+ <item name="textColorSecondary">@android:color/secondary_text_holo_dark</item>
+ <item name="textColorTertiary">@android:color/tertiary_text_holo_dark</item>
+ <item name="textColorPrimaryInverse">@android:color/primary_text_holo_light</item>
+ <item name="textColorSecondaryInverse">@android:color/secondary_text_holo_light</item>
+ <item name="textColorTertiaryInverse">@android:color/tertiary_text_holo_light</item>
+ <item name="textColorPrimaryDisableOnly">@android:color/primary_text_disable_only_holo_dark</item>
+ <item name="textColorPrimaryInverseDisableOnly">@android:color/primary_text_disable_only_holo_light</item>
+ <item name="textColorPrimaryNoDisable">@android:color/primary_text_nodisable_holo_dark</item>
+ <item name="textColorSecondaryNoDisable">@android:color/secondary_text_nodisable_holo_dark</item>
+ <item name="textColorPrimaryInverseNoDisable">@android:color/primary_text_nodisable_holo_light</item>
+ <item name="textColorSecondaryInverseNoDisable">@android:color/secondary_text_nodisable_holo_light</item>
+ <item name="textColorHint">@android:color/hint_foreground_holo_dark</item>
+ <item name="textColorHintInverse">@android:color/hint_foreground_holo_light</item>
+ <item name="textColorSearchUrl">@android:color/search_url_text_holo</item>
+ <item name="textColorHighlight">@android:color/highlighted_text_holo_dark</item>
+ <item name="textColorHighlightInverse">@android:color/highlighted_text_holo_light</item>
+ <item name="textColorLink">@android:color/link_text_holo_dark</item>
+ <item name="textColorLinkInverse">@android:color/link_text_holo_light</item>
+ <item name="textColorAlertDialogListItem">@android:color/primary_text_holo_dark</item>
+
+ <item name="textAppearanceLarge">@android:style/TextAppearance.Holo.Large</item>
+ <item name="textAppearanceMedium">@android:style/TextAppearance.Holo.Medium</item>
+ <item name="textAppearanceSmall">@android:style/TextAppearance.Holo.Small</item>
+ <item name="textAppearanceLargeInverse">@android:style/TextAppearance.Holo.Large.Inverse</item>
+ <item name="textAppearanceMediumInverse">@android:style/TextAppearance.Holo.Medium.Inverse</item>
+ <item name="textAppearanceSmallInverse">@android:style/TextAppearance.Holo.Small.Inverse</item>
+ <item name="textAppearanceSearchResultTitle">@android:style/TextAppearance.Holo.SearchResult.Title</item>
+ <item name="textAppearanceSearchResultSubtitle">@android:style/TextAppearance.Holo.SearchResult.Subtitle</item>
+
+ <item name="textAppearanceButton">@android:style/TextAppearance.Holo.Widget.Button</item>
+
<item name="editTextColor">?android:attr/textColorPrimary</item>
- <item name="android:windowActionBar">true</item>
- <item name="android:spinnerStyle">?android:attr/dropDownSpinnerStyle</item>
+ <item name="editTextBackground">@android:drawable/edit_text_holo_dark</item>
+
+ <item name="candidatesTextStyleSpans">@android:string/candidates_style</item>
+
+ <item name="textCheckMark">@android:drawable/indicator_check_mark_dark</item>
+ <item name="textCheckMarkInverse">@android:drawable/indicator_check_mark_light</item>
+
+ <item name="textAppearanceLargePopupMenu">@android:style/TextAppearance.Holo.Widget.PopupMenu.Large</item>
+ <item name="textAppearanceSmallPopupMenu">@android:style/TextAppearance.Holo.Widget.PopupMenu.Small</item>
+
+ <!-- Button styles -->
+ <item name="buttonStyle">@android:style/Widget.Holo.Button</item>
+
+ <item name="buttonStyleSmall">@android:style/Widget.Holo.Button.Small</item>
+ <item name="buttonStyleInset">@android:style/Widget.Holo.Button.Inset</item>
+
+ <item name="buttonStyleToggle">@android:style/Widget.Holo.Button.Toggle</item>
+
+ <!-- List attributes -->
+ <item name="listPreferredItemHeight">64dip</item>
+ <!-- @hide -->
+ <item name="searchResultListItemHeight">58dip</item>
+ <item name="listDivider">@drawable/divider_horizontal_holo_dark</item>
+ <item name="listSeparatorTextViewStyle">@android:style/Widget.Holo.TextView.ListSeparator</item>
+
<item name="listChoiceIndicatorSingle">@android:drawable/btn_radio_holo_dark</item>
<item name="listChoiceIndicatorMultiple">@android:drawable/btn_check_holo_dark</item>
+
+ <item name="listChoiceBackgroundIndicator">@android:drawable/list_selected_background</item>
+
+ <item name="activatedBackgroundIndicator">@android:drawable/activated_background</item>
+
+ <item name="listDividerAlertDialog">@android:drawable/divider_horizontal_holo_dark</item>
+
+ <item name="expandableListPreferredItemPaddingLeft">40dip</item>
+ <item name="expandableListPreferredChildPaddingLeft">
+ ?android:attr/expandableListPreferredItemPaddingLeft</item>
+
+ <item name="expandableListPreferredItemIndicatorLeft">3dip</item>
+ <item name="expandableListPreferredItemIndicatorRight">33dip</item>
+ <item name="expandableListPreferredChildIndicatorLeft">
+ ?android:attr/expandableListPreferredItemIndicatorLeft</item>
+ <item name="expandableListPreferredChildIndicatorRight">
+ ?android:attr/expandableListPreferredItemIndicatorRight</item>
+
+ <!-- Gallery attributes -->
+ <item name="galleryItemBackground">@android:drawable/gallery_item_background</item>
+
+ <!-- Window attributes -->
+ <item name="windowBackground">@android:drawable/screen_background_holo_dark</item>
+ <item name="windowFrame">@null</item>
+ <item name="windowNoTitle">false</item>
+ <item name="windowFullscreen">false</item>
+ <item name="windowIsFloating">false</item>
+ <item name="windowContentOverlay">@android:drawable/title_bar_shadow</item>
+ <item name="windowShowWallpaper">false</item>
+ <item name="windowTitleStyle">@android:style/WindowTitle.Holo</item>
+ <item name="windowTitleSize">25dip</item>
+ <item name="windowTitleBackgroundStyle">@android:style/WindowTitleBackground.Holo</item>
+ <item name="android:windowAnimationStyle">@android:style/Animation.Holo.Activity</item>
+ <item name="android:windowSoftInputMode">stateUnspecified|adjustUnspecified</item>
+ <item name="windowActionBar">true</item>
+ <item name="windowActionModeOverlay">false</item>
+
+ <!-- Dialog attributes -->
+ <item name="alertDialogStyle">@android:style/AlertDialog.Holo</item>
+
+ <!-- Panel attributes -->
+ <item name="panelBackground">@android:drawable/menu_background</item>
+ <item name="panelFullBackground">@android:drawable/menu_background_fill_parent_width</item>
+ <!-- These three attributes do not seems to be used by the framework. Declared public though -->
+ <item name="panelColorBackground">#000</item>
+ <item name="panelColorForeground">?android:attr/textColorPrimary</item>
+ <item name="panelTextAppearance">?android:attr/textAppearance</item>
+
+ <!-- Scrollbar attributes -->
+ <item name="scrollbarFadeDuration">250</item>
+ <item name="scrollbarDefaultDelayBeforeFade">300</item>
+ <item name="scrollbarSize">10dip</item>
+ <item name="scrollbarThumbHorizontal">@android:drawable/scrollbar_handle_horizontal</item>
+ <item name="scrollbarThumbVertical">@android:drawable/scrollbar_handle_vertical</item>
+ <item name="scrollbarTrackHorizontal">@null</item>
+ <item name="scrollbarTrackVertical">@null</item>
+
+ <!-- Text selection handle attributes -->
+ <item name="textSelectHandleLeft">@android:drawable/text_select_handle_middle</item>
+ <item name="textSelectHandleRight">@android:drawable/text_select_handle_middle</item>
+ <item name="textSelectHandle">@android:drawable/text_select_handle_middle</item>
+ <item name="textSelectHandleWindowStyle">@android:style/Widget.Holo.TextSelectHandle</item>
+
+ <!-- Widget styles -->
+ <item name="absListViewStyle">@android:style/Widget.Holo.AbsListView</item>
+ <item name="autoCompleteTextViewStyle">@android:style/Widget.Holo.AutoCompleteTextView</item>
+ <item name="checkboxStyle">@android:style/Widget.Holo.CompoundButton.CheckBox</item>
+ <item name="dropDownListViewStyle">@android:style/Widget.Holo.ListView.DropDown</item>
+ <item name="editTextStyle">@android:style/Widget.Holo.EditText</item>
+ <item name="expandableListViewStyle">@android:style/Widget.Holo.ExpandableListView</item>
+ <item name="expandableListViewWhiteStyle">@android:style/Widget.Holo.ExpandableListView.White</item>
+ <item name="galleryStyle">@android:style/Widget.Holo.Gallery</item>
+ <item name="gestureOverlayViewStyle">@android:style/Widget.Holo.GestureOverlayView</item>
+ <item name="gridViewStyle">@android:style/Widget.Holo.GridView</item>
+ <item name="imageButtonStyle">@android:style/Widget.Holo.ImageButton</item>
+ <item name="imageWellStyle">@android:style/Widget.Holo.ImageWell</item>
+ <item name="listViewStyle">@android:style/Widget.Holo.ListView</item>
+ <item name="listViewWhiteStyle">@android:style/Widget.Holo.ListView.White</item>
+ <item name="popupWindowStyle">@android:style/Widget.Holo.PopupWindow</item>
+ <item name="progressBarStyle">@android:style/Widget.Holo.ProgressBar</item>
+ <item name="progressBarStyleHorizontal">@android:style/Widget.Holo.ProgressBar.Horizontal</item>
+ <item name="progressBarStyleSmall">@android:style/Widget.Holo.ProgressBar.Small</item>
+ <item name="progressBarStyleSmallTitle">@android:style/Widget.Holo.ProgressBar.Small.Title</item>
+ <item name="progressBarStyleLarge">@android:style/Widget.Holo.ProgressBar.Large</item>
+ <item name="progressBarStyleInverse">@android:style/Widget.Holo.ProgressBar.Inverse</item>
+ <item name="progressBarStyleSmallInverse">@android:style/Widget.Holo.ProgressBar.Small.Inverse</item>
+ <item name="progressBarStyleLargeInverse">@android:style/Widget.Holo.ProgressBar.Large.Inverse</item>
+ <item name="seekBarStyle">@android:style/Widget.Holo.SeekBar</item>
+ <item name="ratingBarStyle">@android:style/Widget.Holo.RatingBar</item>
+ <item name="ratingBarStyleIndicator">@android:style/Widget.Holo.RatingBar.Indicator</item>
+ <item name="ratingBarStyleSmall">@android:style/Widget.Holo.RatingBar.Small</item>
+ <item name="radioButtonStyle">@android:style/Widget.Holo.CompoundButton.RadioButton</item>
+ <item name="scrollViewStyle">@android:style/Widget.Holo.ScrollView</item>
+ <item name="horizontalScrollViewStyle">@android:style/Widget.Holo.HorizontalScrollView</item>
+ <item name="spinnerStyle">?android:attr/dropDownSpinnerStyle</item>
+ <item name="dropDownSpinnerStyle">@android:style/Widget.Holo.Spinner.DropDown</item>
+ <item name="starStyle">@android:style/Widget.Holo.CompoundButton.Star</item>
+ <item name="tabWidgetStyle">@android:style/Widget.Holo.TabWidget</item>
+ <item name="textViewStyle">@android:style/Widget.Holo.TextView</item>
+ <item name="webTextViewStyle">@android:style/Widget.Holo.WebTextView</item>
+ <item name="webViewStyle">@android:style/Widget.Holo.WebView</item>
+ <item name="dropDownItemStyle">@android:style/Widget.Holo.DropDownItem</item>
+ <item name="spinnerDropDownItemStyle">@android:style/Widget.Holo.DropDownItem.Spinner</item>
+ <item name="spinnerItemStyle">@android:style/Widget.Holo.TextView.SpinnerItem</item>
+ <item name="dropDownHintAppearance">@android:style/TextAppearance.Holo.Widget.DropDownHint</item>
+ <item name="keyboardViewStyle">@android:style/Widget.Holo.KeyboardView</item>
+ <item name="quickContactBadgeStyleWindowSmall">@android:style/Widget.Holo.QuickContactBadge.WindowSmall</item>
+ <item name="quickContactBadgeStyleWindowMedium">@android:style/Widget.Holo.QuickContactBadge.WindowMedium</item>
+ <item name="quickContactBadgeStyleWindowLarge">@android:style/Widget.Holo.QuickContactBadge.WindowLarge</item>
+ <item name="quickContactBadgeStyleSmallWindowSmall">@android:style/Widget.Holo.QuickContactBadgeSmall.WindowSmall</item>
+ <item name="quickContactBadgeStyleSmallWindowMedium">@android:style/Widget.Holo.QuickContactBadgeSmall.WindowMedium</item>
+ <item name="quickContactBadgeStyleSmallWindowLarge">@android:style/Widget.Holo.QuickContactBadgeSmall.WindowLarge</item>
+ <item name="listPopupWindowStyle">@android:style/Widget.Holo.ListPopupWindow</item>
+ <item name="popupMenuStyle">@android:style/Widget.Holo.PopupMenu</item>
+
+ <!-- Preference styles -->
+ <item name="preferenceScreenStyle">@android:style/Preference.PreferenceScreen</item>
+ <item name="preferenceCategoryStyle">@android:style/Preference.Category</item>
+ <item name="preferenceStyle">@android:style/Preference</item>
+ <item name="preferenceInformationStyle">@android:style/Preference.Information</item>
+ <item name="checkBoxPreferenceStyle">@android:style/Preference.CheckBoxPreference</item>
+ <item name="yesNoPreferenceStyle">@android:style/Preference.DialogPreference.YesNoPreference</item>
+ <item name="dialogPreferenceStyle">@android:style/Preference.DialogPreference</item>
+ <item name="editTextPreferenceStyle">@android:style/Preference.DialogPreference.EditTextPreference</item>
+ <item name="ringtonePreferenceStyle">@android:style/Preference.RingtonePreference</item>
+ <item name="preferenceLayoutChild">@android:layout/preference_child</item>
+
+ <!-- Search widget styles -->
+ <item name="searchWidgetCorpusItemBackground">@android:color/search_widget_corpus_item_background</item>
+
+ <!-- Action bar styles -->
+ <item name="actionDropDownStyle">@android:style/Widget.Holo.Spinner.DropDown</item>
+ <item name="actionButtonStyle">@android:style/Widget.Holo.ActionButton</item>
+ <item name="actionOverflowButtonStyle">@android:style/Widget.Holo.ActionButton.Overflow</item>
+ <item name="actionButtonPadding">12dip</item>
+ <item name="actionModeBackground">@android:drawable/cab_holo_dark</item>
+ <item name="actionModeCloseDrawable">@android:drawable/cab_ic_close_holo</item>
+ <item name="actionBarTabStyle">@style/Widget.Holo.ActionBarView_TabView</item>
+ <item name="actionBarTabBarStyle">@style/Widget.Holo.ActionBarView_TabBar</item>
+ <item name="actionBarTabTextStyle">@style/Widget.Holo.ActionBarView_TabText</item>
+ <item name="actionModeStyle">@style/Widget.Holo.ActionMode</item>
+ <item name="actionModeCloseButtonStyle">@style/Widget.Holo.ActionButton.CloseMode</item>
+ <item name="actionBarStyle">@android:style/Widget.Holo.ActionBar</item>
+ <item name="actionBarSize">50dip</item>
+
</style>
<!-- New Honeycomb holographic theme. Light version. The widgets in the
@@ -621,14 +840,229 @@
must ensure that any background they use with this theme is itself
light; otherwise, it will be difficult to see the widgets. The new
UI style also includes a full action bar by default. -->
- <style name="Theme.Light.Holo">
- <item name="editTextBackground">@android:drawable/edit_text_holo_light</item>
- <item name="android:windowActionBar">true</item>
- <item name="android:spinnerStyle">?android:attr/dropDownSpinnerStyle</item>
- <item name="listChoiceIndicatorSingle">@android:drawable/btn_radio_holo_light</item>
- <item name="listChoiceIndicatorMultiple">@android:drawable/btn_check_holo_light</item>
- </style>
+ <style name="Theme.Holo.Light" parent="Theme.Light">
+ <item name="colorForeground">@android:color/bright_foreground_holo_light</item>
+ <item name="colorForegroundInverse">@android:color/bright_foreground_inverse_holo_light</item>
+ <item name="colorBackground">@android:color/background_holo_light</item>
+ <item name="colorBackgroundCacheHint">?android:attr/colorBackground</item>
+ <item name="disabledAlpha">0.5</item>
+ <item name="backgroundDimAmount">0.6</item>
+
+ <!-- Text styles -->
+ <item name="textAppearance">@android:style/TextAppearance.Holo.Light</item>
+ <item name="textAppearanceInverse">@android:style/TextAppearance.Holo.Light.Inverse</item>
+
+ <item name="textColorPrimary">@android:color/primary_text_holo_light</item>
+ <item name="textColorSecondary">@android:color/secondary_text_holo_light</item>
+ <item name="textColorTertiary">@android:color/tertiary_text_holo_light</item>
+ <item name="textColorPrimaryInverse">@android:color/primary_text_holo_dark</item>
+ <item name="textColorSecondaryInverse">@android:color/secondary_text_holo_dark</item>
+ <item name="textColorTertiaryInverse">@android:color/tertiary_text_holo_dark</item>
+ <item name="textColorPrimaryDisableOnly">@android:color/primary_text_disable_only_holo_light</item>
+ <item name="textColorPrimaryInverseDisableOnly">@android:color/primary_text_disable_only_holo_dark</item>
+ <item name="textColorPrimaryNoDisable">@android:color/primary_text_nodisable_holo_light</item>
+ <item name="textColorSecondaryNoDisable">@android:color/secondary_text_nodisable_holo_light</item>
+ <item name="textColorPrimaryInverseNoDisable">@android:color/primary_text_nodisable_holo_dark</item>
+ <item name="textColorSecondaryInverseNoDisable">@android:color/secondary_text_nodisable_holo_dark</item>
+ <item name="textColorHint">@android:color/hint_foreground_holo_light</item>
+ <item name="textColorHintInverse">@android:color/hint_foreground_holo_dark</item>
+ <item name="textColorSearchUrl">@android:color/search_url_text_holo</item>
+ <item name="textColorHighlight">@android:color/highlighted_text_holo_light</item>
+ <item name="textColorHighlightInverse">@android:color/highlighted_text_holo_dark</item>
+ <item name="textColorLink">@android:color/link_text_holo_light</item>
+ <item name="textColorLinkInverse">@android:color/link_text_holo_dark</item>
+ <item name="textColorAlertDialogListItem">@android:color/primary_text_holo_dark</item>
+
+ <item name="textAppearanceLarge">@android:style/TextAppearance.Holo.Light.Large</item>
+ <item name="textAppearanceMedium">@android:style/TextAppearance.Holo.Light.Medium</item>
+ <item name="textAppearanceSmall">@android:style/TextAppearance.Holo.Light.Small</item>
+ <item name="textAppearanceLargeInverse">@android:style/TextAppearance.Holo.Light.Large.Inverse</item>
+ <item name="textAppearanceMediumInverse">@android:style/TextAppearance.Holo.Light.Medium.Inverse</item>
+ <item name="textAppearanceSmallInverse">@android:style/TextAppearance.Holo.Light.Small.Inverse</item>
+ <item name="textAppearanceSearchResultTitle">@android:style/TextAppearance.Holo.Light.SearchResult.Title</item>
+ <item name="textAppearanceSearchResultSubtitle">@android:style/TextAppearance.Holo.Light.SearchResult.Subtitle</item>
+ <item name="textAppearanceButton">@android:style/TextAppearance.Holo.Light.Widget.Button</item>
+
+ <item name="editTextColor">?android:attr/textColorPrimary</item>
+ <item name="editTextBackground">@android:drawable/edit_text_holo_light</item>
+
+ <item name="candidatesTextStyleSpans">@android:string/candidates_style</item>
+
+ <item name="textCheckMark">@android:drawable/indicator_check_mark_light</item>
+ <item name="textCheckMarkInverse">@android:drawable/indicator_check_mark_dark</item>
+
+ <item name="textAppearanceLargePopupMenu">@android:style/TextAppearance.Holo.Light.Widget.PopupMenu.Large</item>
+ <item name="textAppearanceSmallPopupMenu">@android:style/TextAppearance.Holo.Light.Widget.PopupMenu.Small</item>
+
+ <!-- Button styles -->
+ <item name="buttonStyle">@android:style/Widget.Holo.Light.Button</item>
+
+ <item name="buttonStyleSmall">@android:style/Widget.Holo.Light.Button.Small</item>
+ <item name="buttonStyleInset">@android:style/Widget.Holo.Light.Button.Inset</item>
+
+ <item name="buttonStyleToggle">@android:style/Widget.Holo.Light.Button.Toggle</item>
+
+ <!-- List attributes -->
+ <item name="listPreferredItemHeight">64dip</item>
+ <!-- @hide -->
+ <item name="searchResultListItemHeight">58dip</item>
+ <item name="listDivider">@drawable/divider_horizontal_holo_dark</item>
+ <item name="listSeparatorTextViewStyle">@android:style/Widget.Holo.Light.TextView.ListSeparator</item>
+
+ <item name="listChoiceIndicatorSingle">@android:drawable/btn_radio</item>
+ <item name="listChoiceIndicatorMultiple">@android:drawable/btn_check</item>
+
+ <item name="listChoiceBackgroundIndicator">@android:drawable/list_selected_background</item>
+
+ <item name="activatedBackgroundIndicator">@android:drawable/activated_background</item>
+
+ <item name="expandableListPreferredItemPaddingLeft">40dip</item>
+ <item name="expandableListPreferredChildPaddingLeft">
+ ?android:attr/expandableListPreferredItemPaddingLeft</item>
+
+ <item name="expandableListPreferredItemIndicatorLeft">3dip</item>
+ <item name="expandableListPreferredItemIndicatorRight">33dip</item>
+ <item name="expandableListPreferredChildIndicatorLeft">
+ ?android:attr/expandableListPreferredItemIndicatorLeft</item>
+ <item name="expandableListPreferredChildIndicatorRight">
+ ?android:attr/expandableListPreferredItemIndicatorRight</item>
+
+ <item name="listDividerAlertDialog">@android:drawable/divider_horizontal_holo_dark</item>
+
+ <!-- Gallery attributes -->
+ <item name="galleryItemBackground">@android:drawable/gallery_item_background</item>
+
+ <!-- Window attributes -->
+ <item name="windowBackground">@android:drawable/screen_background_holo_light</item>
+ <item name="windowFrame">@null</item>
+ <item name="windowNoTitle">false</item>
+ <item name="windowFullscreen">false</item>
+ <item name="windowIsFloating">false</item>
+ <item name="windowContentOverlay">@android:drawable/title_bar_shadow</item>
+ <item name="windowShowWallpaper">false</item>
+ <item name="windowTitleStyle">@android:style/WindowTitle.Holo</item>
+ <item name="windowTitleSize">25dip</item>
+ <item name="windowTitleBackgroundStyle">@android:style/WindowTitleBackground.Holo</item>
+ <item name="android:windowAnimationStyle">@android:style/Animation.Holo.Activity</item>
+ <item name="android:windowSoftInputMode">stateUnspecified|adjustUnspecified</item>
+ <item name="windowActionBar">true</item>
+ <item name="windowActionModeOverlay">false</item>
+
+ <!-- Dialog attributes -->
+ <item name="alertDialogStyle">@android:style/AlertDialog.Holo</item>
+
+ <!-- Panel attributes -->
+ <item name="panelBackground">@android:drawable/menu_background</item>
+ <item name="panelFullBackground">@android:drawable/menu_background_fill_parent_width</item>
+ <!-- These three attributes do not seems to be used by the framework. Declared public though -->
+ <item name="panelColorBackground">#000</item>
+ <item name="panelColorForeground">?android:attr/textColorPrimary</item>
+ <item name="panelTextAppearance">?android:attr/textAppearance</item>
+
+ <!-- Scrollbar attributes -->
+ <item name="scrollbarFadeDuration">250</item>
+ <item name="scrollbarDefaultDelayBeforeFade">300</item>
+ <item name="scrollbarSize">10dip</item>
+ <item name="scrollbarThumbHorizontal">@android:drawable/scrollbar_handle_horizontal</item>
+ <item name="scrollbarThumbVertical">@android:drawable/scrollbar_handle_vertical</item>
+ <item name="scrollbarTrackHorizontal">@null</item>
+ <item name="scrollbarTrackVertical">@null</item>
+
+ <!-- Text selection handle attributes -->
+ <item name="textSelectHandleLeft">@android:drawable/text_select_handle_middle</item>
+ <item name="textSelectHandleRight">@android:drawable/text_select_handle_middle</item>
+ <item name="textSelectHandle">@android:drawable/text_select_handle_middle</item>
+ <item name="textSelectHandleWindowStyle">@android:style/Widget.Holo.TextSelectHandle</item>
+
+ <!-- Widget styles -->
+ <item name="absListViewStyle">@android:style/Widget.Holo.AbsListView</item>
+ <item name="autoCompleteTextViewStyle">@android:style/Widget.Holo.AutoCompleteTextView</item>
+ <item name="checkboxStyle">@android:style/Widget.Holo.CompoundButton.CheckBox</item>
+ <item name="dropDownListViewStyle">@android:style/Widget.Holo.ListView.DropDown</item>
+ <item name="editTextStyle">@android:style/Widget.Holo.EditText</item>
+ <item name="expandableListViewStyle">@android:style/Widget.Holo.ExpandableListView</item>
+ <item name="expandableListViewWhiteStyle">@android:style/Widget.Holo.ExpandableListView.White</item>
+ <item name="galleryStyle">@android:style/Widget.Holo.Gallery</item>
+ <item name="gestureOverlayViewStyle">@android:style/Widget.Holo.GestureOverlayView</item>
+ <item name="gridViewStyle">@android:style/Widget.Holo.GridView</item>
+ <item name="imageButtonStyle">@android:style/Widget.Holo.ImageButton</item>
+ <item name="imageWellStyle">@android:style/Widget.Holo.ImageWell</item>
+ <item name="listViewStyle">@android:style/Widget.Holo.ListView</item>
+ <item name="listViewWhiteStyle">@android:style/Widget.Holo.ListView.White</item>
+ <item name="popupWindowStyle">@android:style/Widget.Holo.PopupWindow</item>
+ <item name="progressBarStyle">@android:style/Widget.Holo.ProgressBar</item>
+ <item name="progressBarStyleHorizontal">@android:style/Widget.Holo.ProgressBar.Horizontal</item>
+ <item name="progressBarStyleSmall">@android:style/Widget.Holo.ProgressBar.Small</item>
+ <item name="progressBarStyleSmallTitle">@android:style/Widget.Holo.ProgressBar.Small.Title</item>
+ <item name="progressBarStyleLarge">@android:style/Widget.Holo.ProgressBar.Large</item>
+ <item name="progressBarStyleInverse">@android:style/Widget.Holo.ProgressBar.Inverse</item>
+ <item name="progressBarStyleSmallInverse">@android:style/Widget.Holo.ProgressBar.Small.Inverse</item>
+ <item name="progressBarStyleLargeInverse">@android:style/Widget.Holo.ProgressBar.Large.Inverse</item>
+ <item name="seekBarStyle">@android:style/Widget.Holo.SeekBar</item>
+ <item name="ratingBarStyle">@android:style/Widget.Holo.RatingBar</item>
+ <item name="ratingBarStyleIndicator">@android:style/Widget.Holo.RatingBar.Indicator</item>
+ <item name="ratingBarStyleSmall">@android:style/Widget.Holo.RatingBar.Small</item>
+ <item name="radioButtonStyle">@android:style/Widget.Holo.CompoundButton.RadioButton</item>
+ <item name="scrollViewStyle">@android:style/Widget.Holo.ScrollView</item>
+ <item name="horizontalScrollViewStyle">@android:style/Widget.Holo.HorizontalScrollView</item>
+ <item name="spinnerStyle">?android:attr/dropDownSpinnerStyle</item>
+ <item name="dropDownSpinnerStyle">@android:style/Widget.Holo.Spinner.DropDown</item>
+ <item name="starStyle">@android:style/Widget.Holo.CompoundButton.Star</item>
+ <item name="tabWidgetStyle">@android:style/Widget.Holo.TabWidget</item>
+ <item name="textViewStyle">@android:style/Widget.Holo.TextView</item>
+ <item name="webTextViewStyle">@android:style/Widget.Holo.WebTextView</item>
+ <item name="webViewStyle">@android:style/Widget.Holo.WebView</item>
+ <item name="dropDownItemStyle">@android:style/Widget.Holo.DropDownItem</item>
+ <item name="spinnerDropDownItemStyle">@android:style/Widget.Holo.DropDownItem.Spinner</item>
+ <item name="spinnerItemStyle">@android:style/Widget.Holo.TextView.SpinnerItem</item>
+ <item name="dropDownHintAppearance">@android:style/TextAppearance.Holo.Widget.DropDownHint</item>
+ <item name="keyboardViewStyle">@android:style/Widget.Holo.KeyboardView</item>
+ <item name="quickContactBadgeStyleWindowSmall">@android:style/Widget.Holo.QuickContactBadge.WindowSmall</item>
+ <item name="quickContactBadgeStyleWindowMedium">@android:style/Widget.Holo.QuickContactBadge.WindowMedium</item>
+ <item name="quickContactBadgeStyleWindowLarge">@android:style/Widget.Holo.QuickContactBadge.WindowLarge</item>
+ <item name="quickContactBadgeStyleSmallWindowSmall">@android:style/Widget.Holo.QuickContactBadgeSmall.WindowSmall</item>
+ <item name="quickContactBadgeStyleSmallWindowMedium">@android:style/Widget.Holo.QuickContactBadgeSmall.WindowMedium</item>
+ <item name="quickContactBadgeStyleSmallWindowLarge">@android:style/Widget.Holo.QuickContactBadgeSmall.WindowLarge</item>
+ <item name="listPopupWindowStyle">@android:style/Widget.Holo.ListPopupWindow</item>
+ <item name="popupMenuStyle">@android:style/Widget.Holo.PopupMenu</item>
+
+ <!-- Preference styles -->
+ <item name="preferenceScreenStyle">@android:style/Preference.PreferenceScreen</item>
+ <item name="preferenceCategoryStyle">@android:style/Preference.Category</item>
+ <item name="preferenceStyle">@android:style/Preference</item>
+ <item name="preferenceInformationStyle">@android:style/Preference.Information</item>
+ <item name="checkBoxPreferenceStyle">@android:style/Preference.CheckBoxPreference</item>
+ <item name="yesNoPreferenceStyle">@android:style/Preference.DialogPreference.YesNoPreference</item>
+ <item name="dialogPreferenceStyle">@android:style/Preference.DialogPreference</item>
+ <item name="editTextPreferenceStyle">@android:style/Preference.DialogPreference.EditTextPreference</item>
+ <item name="ringtonePreferenceStyle">@android:style/Preference.RingtonePreference</item>
+ <item name="preferenceLayoutChild">@android:layout/preference_child</item>
+
+ <!-- Search widget styles -->
+ <item name="searchWidgetCorpusItemBackground">@android:color/search_widget_corpus_item_background</item>
+
+ <!-- Action bar styles -->
+ <item name="actionDropDownStyle">@android:style/Widget.Holo.Spinner.DropDown</item>
+ <item name="actionButtonStyle">@android:style/Widget.Holo.ActionButton</item>
+ <item name="actionOverflowButtonStyle">@android:style/Widget.Holo.ActionButton.Overflow</item>
+ <item name="actionButtonPadding">12dip</item>
+ <item name="actionModeBackground">@android:drawable/cab_holo_light</item>
+ <item name="actionModeCloseDrawable">@android:drawable/cab_ic_close_holo</item>
+ <item name="actionBarTabStyle">@style/Widget.Holo.ActionBarView_TabView</item>
+ <item name="actionBarTabBarStyle">@style/Widget.Holo.ActionBarView_TabBar</item>
+ <item name="actionBarTabTextStyle">@style/Widget.Holo.ActionBarView_TabText</item>
+ <item name="actionModeStyle">@style/Widget.Holo.Light.ActionMode</item>
+ <item name="actionModeCloseButtonStyle">@style/Widget.Holo.ActionButton.CloseMode</item>
+ <item name="actionBarStyle">@android:style/Widget.Holo.ActionBar</item>
+ <item name="actionBarSize">50dip</item>
+
+ </style>
+
+ <!-- Development legacy name; if you're using this, switch. -->
+ <style name="Theme.Light.Holo" parent="Theme.Holo.Light">
+ </style>
+
<!-- Variant of the holographic (dark) theme with no action bar. -->
<style name="Theme.Holo.NoActionBar">
<item name="android:windowActionBar">false</item>
@@ -655,4 +1089,53 @@
<item name="android:windowContentOverlay">@null</item>
</style>
+ <!-- Dialog themes for Holo -->
+
+ <!-- Holo theme for dialog windows and activities, which is used by the
+ {@link android.app.Dialog} class. This changes the window to be
+ floating (not fill the entire screen), and puts a frame around its
+ contents. You can set this theme on an activity if you would like to
+ make an activity that looks like a Dialog.
+ This is the default Dialog theme for applications targeting Honeycomb
+ or newer. -->
+ <style name="Theme.Holo.Dialog">
+ <item name="android:windowFrame">@null</item>
+ <item name="android:windowTitleStyle">@android:style/DialogWindowTitle.Holo</item>
+ <item name="android:windowBackground">@android:drawable/dialog_full_holo</item>
+ <item name="android:windowIsFloating">true</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowAnimationStyle">@android:style/Animation.Holo.Dialog</item>
+ <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
+ <item name="android:windowActionBar">false</item>
+
+ <item name="android:colorBackgroundCacheHint">@null</item>
+
+ <item name="textAppearance">@android:style/TextAppearance.Holo</item>
+ <item name="textAppearanceInverse">@android:style/TextAppearance.Holo.Inverse</item>
+ </style>
+
+ <!-- Variation of Theme.Holo.Dialog that does not include a frame (or background).
+ The view hierarchy of the dialog is responsible for drawing all of
+ its pixels. -->
+ <style name="Theme.Holo.Dialog.NoFrame">
+ <item name="windowBackground">@android:color/transparent</item>
+ <item name="android:windowFrame">@null</item>
+ <item name="windowContentOverlay">@null</item>
+ <item name="android:windowAnimationStyle">@null</item>
+ <item name="android:backgroundDimEnabled">false</item>
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowNoTitle">true</item>
+ </style>
+
+ <!-- Holo theme for alert dialog windows, which is used by the
+ {@link android.app.AlertDialog} class. This is basically a dialog
+ but sets the background to empty so it can do two-tone backgrounds.
+ For applications targeting Honeycomb or newer, this is the default
+ AlertDialog theme. -->
+ <style name="Theme.Holo.Dialog.Alert">
+ <item name="windowBackground">@android:color/transparent</item>
+ <item name="windowTitleStyle">@android:style/DialogWindowTitle.Holo</item>
+ <item name="windowContentOverlay">@null</item>
+ </style>
+
</resources>
diff --git a/core/tests/coretests/src/android/net/DownloadManagerBaseTest.java b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
similarity index 99%
rename from core/tests/coretests/src/android/net/DownloadManagerBaseTest.java
rename to core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
index a7ec7d5..ed42e64 100644
--- a/core/tests/coretests/src/android/net/DownloadManagerBaseTest.java
+++ b/core/tests/coretests/src/android/app/DownloadManagerBaseTest.java
@@ -14,18 +14,18 @@
* limitations under the License.
*/
-package android.net;
+package android.app;
+import android.app.DownloadManager.Query;
+import android.app.DownloadManager.Request;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.ConnectivityManager;
-import android.net.DownloadManager;
import android.net.NetworkInfo;
-import android.net.DownloadManager.Query;
-import android.net.DownloadManager.Request;
+import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.Environment;
diff --git a/core/tests/coretests/src/android/net/DownloadManagerIntegrationTest.java b/core/tests/coretests/src/android/app/DownloadManagerIntegrationTest.java
similarity index 98%
rename from core/tests/coretests/src/android/net/DownloadManagerIntegrationTest.java
rename to core/tests/coretests/src/android/app/DownloadManagerIntegrationTest.java
index a61f02d..38f336e 100644
--- a/core/tests/coretests/src/android/net/DownloadManagerIntegrationTest.java
+++ b/core/tests/coretests/src/android/app/DownloadManagerIntegrationTest.java
@@ -14,18 +14,18 @@
* limitations under the License.
*/
-package android.net;
+package android.app;
+import android.app.DownloadManager.Query;
+import android.app.DownloadManager.Request;
+import android.app.DownloadManagerBaseTest.DataType;
+import android.app.DownloadManagerBaseTest.MultipleDownloadsCompletedReceiver;
import android.content.BroadcastReceiver;
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;
-import android.net.DownloadManagerBaseTest.MultipleDownloadsCompletedReceiver;
+import android.net.Uri;
import android.net.wifi.WifiManager;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
diff --git a/core/tests/coretests/src/android/net/DownloadManagerStressTest.java b/core/tests/coretests/src/android/app/DownloadManagerStressTest.java
similarity index 97%
rename from core/tests/coretests/src/android/net/DownloadManagerStressTest.java
rename to core/tests/coretests/src/android/app/DownloadManagerStressTest.java
index 9fa8620..4ff0295 100644
--- a/core/tests/coretests/src/android/net/DownloadManagerStressTest.java
+++ b/core/tests/coretests/src/android/app/DownloadManagerStressTest.java
@@ -14,14 +14,15 @@
* limitations under the License.
*/
-package android.net;
+package android.app;
import java.io.File;
import java.util.Random;
+import android.app.DownloadManager.Query;
+import android.app.DownloadManager.Request;
import android.database.Cursor;
-import android.net.DownloadManager.Query;
-import android.net.DownloadManager.Request;
+import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
diff --git a/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
index 576765c..7206f4a 100644
--- a/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
+++ b/core/tests/hosttests/test-apps/DownloadManagerTestApp/Android.mk
@@ -19,7 +19,7 @@
LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := $(call all-java-files-under, src) \
- ../../../coretests/src/android/net/DownloadManagerBaseTest.java
+ ../../../coretests/src/android/app/DownloadManagerBaseTest.java
LOCAL_STATIC_JAVA_LIBRARIES := android-common frameworks-core-util-lib
LOCAL_SDK_VERSION := current
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 f21e7ac..c0f670b 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
@@ -15,13 +15,13 @@
*/
package com.android.frameworks.downloadmanagertests;
+import android.app.DownloadManager;
+import android.app.DownloadManager.Query;
+import android.app.DownloadManager.Request;
+import android.app.DownloadManagerBaseTest;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
-import android.net.DownloadManager;
-import android.net.DownloadManager.Query;
-import android.net.DownloadManager.Request;
-import android.net.DownloadManagerBaseTest;
import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 2aa3e84..c4421c3 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -601,9 +601,9 @@
while(mRun) {
rbuf[0] = 0;
int msg = mRS.nContextGetMessage(mRS.mContext, rbuf, true);
- if ((msg == 0) && mRun) {
+ if ((msg == 0)) {
// Can happen for two reasons
- if (rbuf[0] > 0) {
+ if (rbuf[0] > 0 && mRun) {
// 1: Buffer needs to be enlarged.
rbuf = new int[rbuf[0] + 2];
} else {
@@ -616,6 +616,7 @@
} catch(InterruptedException e) {
}
}
+ continue;
}
if(mRS.mMessageCallback != null) {
mRS.mMessageCallback.mData = rbuf;
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
index 9a09586..ed2f7d7 100644
--- a/include/media/stagefright/AudioPlayer.h
+++ b/include/media/stagefright/AudioPlayer.h
@@ -27,6 +27,7 @@
class MediaSource;
class AudioTrack;
+class AwesomePlayer;
class AudioPlayer : public TimeSource {
public:
@@ -35,7 +36,9 @@
SEEK_COMPLETE
};
- AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink);
+ AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink,
+ AwesomePlayer *audioObserver = NULL);
+
virtual ~AudioPlayer();
// Caller retains ownership of "source".
@@ -91,6 +94,7 @@
MediaBuffer *mFirstBuffer;
sp<MediaPlayerBase::AudioSink> mAudioSink;
+ AwesomePlayer *mObserver;
static void AudioCallback(int event, void *user, void *info);
void AudioCallback(int event, void *info);
diff --git a/include/media/stagefright/MPEG2TSWriter.h b/include/media/stagefright/MPEG2TSWriter.h
new file mode 100644
index 0000000..551ca01
--- /dev/null
+++ b/include/media/stagefright/MPEG2TSWriter.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MPEG2TS_WRITER_H_
+
+#define MPEG2TS_WRITER_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AHandlerReflector.h>
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/MediaWriter.h>
+
+namespace android {
+
+struct MPEG2TSWriter : public MediaWriter {
+ MPEG2TSWriter(const char *filename);
+
+ virtual status_t addSource(const sp<MediaSource> &source);
+ virtual status_t start(MetaData *param = NULL);
+ virtual status_t stop();
+ virtual status_t pause();
+ virtual bool reachedEOS();
+ virtual status_t dump(int fd, const Vector<String16>& args);
+
+ void onMessageReceived(const sp<AMessage> &msg);
+
+protected:
+ virtual ~MPEG2TSWriter();
+
+private:
+ enum {
+ kWhatSourceNotify = 'noti'
+ };
+
+ struct SourceInfo;
+
+ FILE *mFile;
+ sp<ALooper> mLooper;
+ sp<AHandlerReflector<MPEG2TSWriter> > mReflector;
+
+ bool mStarted;
+
+ Vector<sp<SourceInfo> > mSources;
+ size_t mNumSourcesDone;
+
+ int64_t mNumTSPacketsWritten;
+ int64_t mNumTSPacketsBeforeMeta;
+
+ void writeTS();
+ void writeProgramAssociationTable();
+ void writeProgramMap();
+ void writeAccessUnit(int32_t sourceIndex, const sp<ABuffer> &buffer);
+
+ DISALLOW_EVIL_CONSTRUCTORS(MPEG2TSWriter);
+};
+
+} // namespace android
+
+#endif // MPEG2TS_WRITER_H_
diff --git a/include/media/stagefright/MetaData.h b/include/media/stagefright/MetaData.h
index 1594e31..ab2f11d 100644
--- a/include/media/stagefright/MetaData.h
+++ b/include/media/stagefright/MetaData.h
@@ -95,6 +95,8 @@
// Ogg files can be tagged to be automatically looping...
kKeyAutoLoop = 'autL', // bool (int32_t)
+
+ kKeyValidSamples = 'valD', // int32_t
};
enum {
diff --git a/include/storage/IMountService.h b/include/storage/IMountService.h
index a2735a4..436fc38 100644
--- a/include/storage/IMountService.h
+++ b/include/storage/IMountService.h
@@ -62,7 +62,8 @@
virtual void finishMediaUpdate() = 0;
virtual void mountObb(const String16& filename, const String16& key,
const sp<IObbActionListener>& token) = 0;
- virtual void unmountObb(const String16& filename, const bool force) = 0;
+ virtual void unmountObb(const String16& filename, const bool force,
+ const sp<IObbActionListener>& token) = 0;
virtual bool isObbMounted(const String16& filename) = 0;
virtual bool getMountedObbPath(const String16& filename, String16& path) = 0;
};
diff --git a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
index cd8f814..dbc9133 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
+++ b/libs/rs/java/tests/src/com/android/rs/test/RSTestCore.java
@@ -40,6 +40,8 @@
private ScriptC_rslist mScript;
private ArrayList<UnitTest> unitTests;
+ private ListIterator<UnitTest> test_iter;
+ private UnitTest activeTest;
public void init(RenderScriptGL rs, Resources res, int width, int height) {
mRS = rs;
@@ -54,9 +56,13 @@
unitTests.add(new UT_primitives(this, mRes));
unitTests.add(new UT_fp_mad(this, mRes));
/*
- unitTests.add(new UnitTest("<Pass>", 1));
+ unitTests.add(new UnitTest(null, "<Pass>", 1));
unitTests.add(new UnitTest());
- unitTests.add(new UnitTest("<Fail>", -1));
+ unitTests.add(new UnitTest(null, "<Fail>", -1));
+
+ for (int i = 0; i < 20; i++) {
+ unitTests.add(new UnitTest(null, "<Pass>", 1));
+ }
*/
UnitTest [] uta = new UnitTest[unitTests.size()];
@@ -71,19 +77,6 @@
uta[i].setItem(listElem);
}
- /* Run the actual unit tests */
- ListIterator<UnitTest> test_iter = unitTests.listIterator();
- while (test_iter.hasNext()) {
- UnitTest t = test_iter.next();
- t.start();
- /*
- try {
- t.join();
- } catch (InterruptedException e) {
- }
- */
- }
-
mListAllocs.copyAll();
mScript.bind_gList(mListAllocs);
@@ -92,10 +85,40 @@
mScript.set_gFont(mFont);
mRS.contextBindRootScript(mScript);
- mRS.finish();
+
+ test_iter = unitTests.listIterator();
+ refreshTestResults(); /* Kick off the first test */
+ }
+
+ static int count = 0;
+ public void checkAndRunNextTest() {
+ if (activeTest != null) {
+ if (!activeTest.isAlive()) {
+ /* Properly clean up on our last test */
+ try {
+ activeTest.join();
+ }
+ catch (InterruptedException e) {
+ }
+ activeTest = null;
+ }
+ }
+
+ if (activeTest == null) {
+ if (test_iter.hasNext()) {
+ activeTest = test_iter.next();
+ activeTest.start();
+ /* This routine will only get called once when a new test
+ * should start running. The message handler in UnitTest.java
+ * ensures this. */
+ }
+ }
+ count++;
}
public void refreshTestResults() {
+ checkAndRunNextTest();
+
if (mListAllocs != null && mScript != null && mRS != null) {
mListAllocs.copyAll();
@@ -111,6 +134,7 @@
mScript.set_gDY(0.0f);
mLastX = x;
mLastY = y;
+ refreshTestResults();
}
public void onActionMove(int x, int y) {
@@ -125,5 +149,6 @@
mLastX = x;
mLastY = y;
+ refreshTestResults();
}
}
diff --git a/libs/rs/java/tests/src/com/android/rs/test/UnitTest.java b/libs/rs/java/tests/src/com/android/rs/test/UnitTest.java
index d98b763..5eb0d67 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/UnitTest.java
+++ b/libs/rs/java/tests/src/com/android/rs/test/UnitTest.java
@@ -16,6 +16,7 @@
package com.android.rs.test;
import android.renderscript.RenderScript.RSMessage;
+import android.util.Log;
public class UnitTest extends Thread {
public String name;
@@ -27,11 +28,15 @@
public static final int RS_MSG_TEST_PASSED = 100;
public static final int RS_MSG_TEST_FAILED = 101;
+ private static int numTests = 0;
+ public int testID;
+
protected UnitTest(RSTestCore rstc, String n, int initResult) {
super();
mRSTC = rstc;
name = n;
result = initResult;
+ testID = numTests++;
}
protected UnitTest(RSTestCore rstc, String n) {
@@ -56,12 +61,20 @@
result = -1;
break;
default:
- break;
+ android.util.Log.v("RenderScript", "Unit test got unexpected message");
+ return;
}
if (mItem != null) {
mItem.result = result;
- mRSTC.refreshTestResults();
+ try {
+ mRSTC.refreshTestResults();
+ }
+ catch (IllegalStateException e) {
+ /* Ignore the case where our message receiver has been
+ disconnected. This happens when we leave the application
+ before it finishes running all of the unit tests. */
+ }
}
}
};
@@ -72,6 +85,9 @@
public void run() {
/* This method needs to be implemented for each subclass */
+ if (mRSTC != null) {
+ mRSTC.refreshTestResults();
+ }
}
}
diff --git a/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs b/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs
index eb82e56..dfd77e6 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs
+++ b/libs/rs/java/tests/src/com/android/rs/test/fp_mad.rs
@@ -170,7 +170,7 @@
// TODO Actually verify test result accuracy
rsDebug("fp_mad_test PASSED", 0);
- rsSendToClient(RS_MSG_TEST_PASSED);
+ rsSendToClientBlocking(RS_MSG_TEST_PASSED);
}
diff --git a/libs/rs/java/tests/src/com/android/rs/test/primitives.rs b/libs/rs/java/tests/src/com/android/rs/test/primitives.rs
index 2ba5d52..5312bcc 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/primitives.rs
+++ b/libs/rs/java/tests/src/com/android/rs/test/primitives.rs
@@ -42,10 +42,10 @@
failed |= test_primitive_types(index);
if (failed) {
- rsSendToClient(RS_MSG_TEST_FAILED);
+ rsSendToClientBlocking(RS_MSG_TEST_FAILED);
}
else {
- rsSendToClient(RS_MSG_TEST_PASSED);
+ rsSendToClientBlocking(RS_MSG_TEST_PASSED);
}
}
diff --git a/libs/rs/java/tests/src/com/android/rs/test/rslist.rs b/libs/rs/java/tests/src/com/android/rs/test/rslist.rs
index 72d1850..a5f0f6b 100644
--- a/libs/rs/java/tests/src/com/android/rs/test/rslist.rs
+++ b/libs/rs/java/tests/src/com/android/rs/test/rslist.rs
@@ -56,6 +56,27 @@
int height = rsgGetHeight();
int itemHeight = 80;
+ int totalItemHeight = itemHeight * allocSize;
+
+ /* Prevent scrolling above the top of the list */
+ int firstItem = height - totalItemHeight;
+ if (firstItem < 0) {
+ firstItem = 0;
+ }
+
+ /* Prevent scrolling past the last line of the list */
+ int lastItem = -1 * (totalItemHeight - height);
+ if (lastItem > 0) {
+ lastItem = 0;
+ }
+
+ if (textPos > firstItem) {
+ textPos = firstItem;
+ }
+ else if (textPos < lastItem) {
+ textPos = lastItem;
+ }
+
int currentYPos = itemHeight + textPos;
for(int i = 0; i < allocSize; i ++) {
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 3681bc2..a7f380f 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -33,6 +33,8 @@
#include <GLES2/gl2ext.h>
#include <cutils/sched_policy.h>
+#include <sys/syscall.h>
+#include <string.h>
using namespace android;
using namespace android::renderscript;
@@ -371,11 +373,15 @@
rsc->mWorkers.mLaunchSignals[idx].init();
rsc->mWorkers.mNativeThreadId[idx] = gettid();
- //cpu_set_t cpset[16];
- //int ret = sched_getaffinity(rsc->mWorkers.mNativeThreadId[idx], sizeof(cpset), &cpset);
- //LOGE("ret = %i", ret);
-
-//sched_setaffinity
+#if 0
+ typedef struct {uint64_t bits[1024 / 64]; } cpu_set_t;
+ cpu_set_t cpuset;
+ memset(&cpuset, 0, sizeof(cpuset));
+ cpuset.bits[idx / 64] |= 1ULL << (idx % 64);
+ int ret = syscall(241, rsc->mWorkers.mNativeThreadId[idx],
+ sizeof(cpuset), &cpuset);
+ LOGE("SETAFFINITY ret = %i %s", ret, EGLUtils::strerror(ret));
+#endif
setpriority(PRIO_PROCESS, rsc->mWorkers.mNativeThreadId[idx], rsc->mThreadPriority);
while(rsc->mRunning) {
@@ -490,6 +496,7 @@
usleep(100);
}
+ mWorkers.mCompleteSignal.init();
mWorkers.mRunningCount = 0;
mWorkers.mLaunchCount = 0;
for (uint32_t ct=0; ct < mWorkers.mCount; ct++) {
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index bce9c13..b85d2a8 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -174,7 +174,7 @@
uint32_t getMaxVertexUniformVectors() const {return mGL.mMaxVertexUniformVectors;}
void launchThreads(WorkerCallback_t cbk, void *data);
- uint32_t getWorkerPoolSize() const {return (uint32_t)mWorkers.mRunningCount;}
+ uint32_t getWorkerPoolSize() const {return (uint32_t)mWorkers.mCount;}
protected:
Device *mDev;
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index f905492..e9621b9 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -201,7 +201,7 @@
}
//LOGE("usr idx %i, x %i,%i y %i,%i", idx, mtls->xStart, mtls->xEnd, yStart, yEnd);
-
+ //LOGE("usr ptr in %p, out %p", mtls->ptrIn, mtls->ptrOut);
for (uint32_t y = yStart; y < yEnd; y++) {
uint32_t offset = mtls->dimX * y;
uint8_t *xPtrOut = mtls->ptrOut + (mtls->eStrideOut * offset);
@@ -296,14 +296,12 @@
mtls.eStrideOut = aout->getType()->getElementSizeBytes();
}
-
- if ((rsc->getWorkerPoolSize() > 1) && mEnviroment.mIsThreadable &&
- ((mtls.dimY * mtls.dimZ * mtls.dimArray) > 1)) {
+ if ((rsc->getWorkerPoolSize() > 1) && mEnviroment.mIsThreadable && (mtls.dimY > 1)) {
//LOGE("launch 1");
rsc->launchThreads(wc_xy, &mtls);
- //LOGE("launch 2");
} else {
+ //LOGE("launch 3");
for (uint32_t ar = mtls.arrayStart; ar < mtls.arrayEnd; ar++) {
for (uint32_t z = mtls.zStart; z < mtls.zEnd; z++) {
for (uint32_t y = mtls.yStart; y < mtls.yEnd; y++) {
@@ -380,11 +378,11 @@
if (sym) {
return sym->mPtr;
}
- s->mEnviroment.mIsThreadable = false;
sym = ScriptCState::lookupSymbolCL(name);
if (sym) {
return sym->mPtr;
}
+ s->mEnviroment.mIsThreadable = false;
sym = ScriptCState::lookupSymbolGL(name);
if (sym) {
return sym->mPtr;
diff --git a/libs/storage/IMountService.cpp b/libs/storage/IMountService.cpp
index 902bb27..3ad9319 100644
--- a/libs/storage/IMountService.cpp
+++ b/libs/storage/IMountService.cpp
@@ -429,8 +429,8 @@
reply.readExceptionCode();
}
- void mountObb(const String16& filename, const String16& key, const sp<
- IObbActionListener>& token)
+ void mountObb(const String16& filename, const String16& key,
+ const sp<IObbActionListener>& token)
{
Parcel data, reply;
data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
@@ -448,7 +448,7 @@
}
}
- void unmountObb(const String16& filename, const bool force)
+ void unmountObb(const String16& filename, const bool force, const sp<IObbActionListener>& token)
{
Parcel data, reply;
data.writeInterfaceToken(IMountService::getInterfaceDescriptor());
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index 9e78a4a..16ce24b 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -1070,7 +1070,8 @@
}
// Figure out whether splitting will be allowed for this window.
- if (newTouchedWindow->layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH) {
+ if (newTouchedWindow
+ && (newTouchedWindow->layoutParamsFlags & InputWindow::FLAG_SPLIT_TOUCH)) {
// New window supports splitting.
isSplit = true;
} else if (isSplit) {
@@ -1916,6 +1917,14 @@
// The first/last pointer went down/up.
action = maskedAction == AMOTION_EVENT_ACTION_POINTER_DOWN
? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
+ } else {
+ // A secondary pointer went down/up.
+ uint32_t splitPointerIndex = 0;
+ while (pointerId != splitPointerIds[splitPointerIndex]) {
+ splitPointerIndex += 1;
+ }
+ action = maskedAction | (splitPointerIndex
+ << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
}
} else {
// An unrelated pointer changed.
diff --git a/location/Android.mk b/location/Android.mk
new file mode 100644
index 0000000..12db2f7
--- /dev/null
+++ b/location/Android.mk
@@ -0,0 +1,19 @@
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(TARGET_BUILD_APPS),)
+include $(call all-makefiles-under, $(LOCAL_PATH))
+endif
diff --git a/location/lib/Android.mk b/location/lib/Android.mk
new file mode 100644
index 0000000..a06478a
--- /dev/null
+++ b/location/lib/Android.mk
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+LOCAL_PATH := $(call my-dir)
+
+# the library
+# ============================================================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= com.android.location.provider
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := \
+ $(call all-subdir-java-files)
+
+include $(BUILD_JAVA_LIBRARY)
+
+
+# ==== com.google.location.xml lib def ========================
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := com.android.location.provider.xml
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_CLASS := ETC
+
+# This will install the file in /system/etc/permissions
+#
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
+
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+
+include $(BUILD_PREBUILT)
diff --git a/location/lib/com.android.location.provider.xml b/location/lib/com.android.location.provider.xml
new file mode 100644
index 0000000..000e68f
--- /dev/null
+++ b/location/lib/com.android.location.provider.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<permissions>
+ <library name="com.android.location.provider"
+ file="/system/framework/com.android.location.provider.jar" />
+</permissions>
diff --git a/location/java/android/location/provider/GeocodeProvider.java b/location/lib/java/com/android/location/provider/GeocodeProvider.java
similarity index 98%
rename from location/java/android/location/provider/GeocodeProvider.java
rename to location/lib/java/com/android/location/provider/GeocodeProvider.java
index 493c631..666bb02 100644
--- a/location/java/android/location/provider/GeocodeProvider.java
+++ b/location/lib/java/com/android/location/provider/GeocodeProvider.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.location.provider;
+package com.android.location.provider;
import android.os.IBinder;
@@ -80,4 +80,3 @@
return mProvider;
}
}
-
diff --git a/location/java/android/location/provider/LocationProvider.java b/location/lib/java/com/android/location/provider/LocationProvider.java
similarity index 99%
rename from location/java/android/location/provider/LocationProvider.java
rename to location/lib/java/com/android/location/provider/LocationProvider.java
index 14dea14..3714f40 100644
--- a/location/java/android/location/provider/LocationProvider.java
+++ b/location/lib/java/com/android/location/provider/LocationProvider.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.location.provider;
+package com.android.location.provider;
import android.content.Context;
import android.net.NetworkInfo;
@@ -356,4 +356,3 @@
*/
public abstract void onRemoveListener(int uid, WorkSource ws);
}
-
diff --git a/media/java/android/media/MtpCursor.java b/media/java/android/media/MtpCursor.java
index b9dd03e..ff8799a 100644
--- a/media/java/android/media/MtpCursor.java
+++ b/media/java/android/media/MtpCursor.java
@@ -31,7 +31,7 @@
static final String TAG = "MtpCursor";
static final int NO_COUNT = -1;
- /* constants for mQueryType */
+ /* constants for queryType */
public static final int DEVICE = 1;
public static final int DEVICE_ID = 2;
public static final int STORAGE = 3;
@@ -41,27 +41,15 @@
public static final int STORAGE_CHILDREN = 7;
public static final int OBJECT_CHILDREN = 8;
- private int mQueryType;
- private int mDeviceID;
- private long mStorageID;
- private long mQbjectID;
-
/** The names of the columns in the projection */
private String[] mColumns;
/** The number of rows in the cursor */
private int mCount = NO_COUNT;
- private final MtpClient mClient;
public MtpCursor(MtpClient client, int queryType, int deviceID, long storageID, long objectID,
String[] projection) {
-
- mClient = client;
- mQueryType = queryType;
- mDeviceID = deviceID;
- mStorageID = storageID;
- mQbjectID = objectID;
mColumns = projection;
HashMap<String, Integer> map;
diff --git a/media/java/android/media/videoeditor/AudioTrack.java b/media/java/android/media/videoeditor/AudioTrack.java
index 9d40a78..468ba2a 100755
--- a/media/java/android/media/videoeditor/AudioTrack.java
+++ b/media/java/android/media/videoeditor/AudioTrack.java
@@ -35,6 +35,11 @@
private long mEndBoundaryTimeMs;
private boolean mLoop;
+ private final int mAudioChannels;
+ private final int mAudioType;
+ private final int mAudioBitrate;
+ private final int mAudioSamplingFrequency;
+
// Ducking variables
private int mDuckingThreshold;
private int mDuckingLowVolume;
@@ -54,7 +59,6 @@
/**
* Constructor
- *
* @param audioTrackId The AudioTrack id
* @param filename The absolute file name
*
@@ -68,6 +72,13 @@
mStartTimeMs = 0;
// TODO: This value represents to the duration of the audio file
mDurationMs = 300000;
+ // TODO: This value needs to be read from the audio track of the source
+ // file
+ mAudioChannels = 2;
+ mAudioType = MediaProperties.ACODEC_AAC_LC;
+ mAudioBitrate = 128000;
+ mAudioSamplingFrequency = 44100;
+
mTimelineDurationMs = mDurationMs;
mVolumePercent = 100;
@@ -104,6 +115,34 @@
}
/**
+ * @return The number of audio channels in the source of this audio track
+ */
+ public int getAudioChannels() {
+ return mAudioChannels;
+ }
+
+ /**
+ * @return The audio codec of the source of this audio track
+ */
+ public int getAudioType() {
+ return mAudioType;
+ }
+
+ /**
+ * @return The audio sample frequency of the audio track
+ */
+ public int getAudioSamplingFrequency() {
+ return mAudioSamplingFrequency;
+ }
+
+ /**
+ * @return The audio bitrate of the audio track
+ */
+ public int getAudioBitrate() {
+ return mAudioBitrate;
+ }
+
+ /**
* Set the volume of this audio track as percentage of the volume in the
* original audio source file.
*
@@ -112,8 +151,8 @@
* is same as original volume. It it is set to 200, then volume
* is doubled (provided that volume amplification is supported)
*
- * @throws UnsupportedOperationException if volume amplification is requested
- * and is not supported.
+ * @throws UnsupportedOperationException if volume amplification is
+ * requested and is not supported.
*/
public void setVolume(int volumePercent) {
mVolumePercent = volumePercent;
@@ -209,8 +248,8 @@
/**
* Enable the loop mode for this audio track. Note that only one of the
- * audio tracks in the timeline can have the loop mode enabled. When
- * looping is enabled the samples between mBeginBoundaryTimeMs and
+ * audio tracks in the timeline can have the loop mode enabled. When looping
+ * is enabled the samples between mBeginBoundaryTimeMs and
* mEndBoundaryTimeMs are looped.
*/
public void enableLoop() {
@@ -285,18 +324,19 @@
*/
public void extractAudioWaveform(ExtractAudioWaveformProgressListener listener)
throws IOException {
- // TODO: Set mAudioWaveformFilename at the end once the extract is complete
+ // TODO: Set mAudioWaveformFilename at the end once the extract is
+ // complete
}
/**
* Get the audio waveform file name if extractAudioWaveform was successful.
* The file format is as following:
* <ul>
- * <li>first 4 bytes provide the number of samples for each value, as
- * big-endian signed</li>
- * <li>4 following bytes is the total number of values in the file, as
- * big-endian signed</li>
- * <li>then, all values follow as bytes</li>
+ * <li>first 4 bytes provide the number of samples for each value, as
+ * big-endian signed</li>
+ * <li>4 following bytes is the total number of values in the file, as
+ * big-endian signed</li>
+ * <li>then, all values follow as bytes</li>
* </ul>
*
* @return the name of the file, null if the file does not exist
diff --git a/media/java/android/media/videoeditor/Effect.java b/media/java/android/media/videoeditor/Effect.java
index 8c39577..038bfc2 100755
--- a/media/java/android/media/videoeditor/Effect.java
+++ b/media/java/android/media/videoeditor/Effect.java
@@ -26,6 +26,8 @@
public abstract class Effect {
// Instance variables
private final String mUniqueId;
+ // The effect owner
+ private final MediaItem mMediaItem;
protected long mDurationMs;
// The start time of the effect relative to the media item timeline
protected long mStartTimeMs;
@@ -35,6 +37,7 @@
*/
@SuppressWarnings("unused")
private Effect() {
+ mMediaItem = null;
mUniqueId = null;
mStartTimeMs = 0;
mDurationMs = 0;
@@ -43,12 +46,22 @@
/**
* Constructor
*
+ * @param mediaItem The media item owner
* @param effectId The effect id
* @param startTimeMs The start time relative to the media item to which it
* is applied
* @param durationMs The effect duration in milliseconds
*/
- public Effect(String effectId, long startTimeMs, long durationMs) {
+ public Effect(MediaItem mediaItem, String effectId, long startTimeMs, long durationMs) {
+ if (mediaItem == null) {
+ throw new IllegalArgumentException("Media item cannot be null");
+ }
+
+ if (startTimeMs + durationMs > mediaItem.getTimelineDuration()) {
+ throw new IllegalArgumentException("Invalid start time and duration");
+ }
+
+ mMediaItem = mediaItem;
mUniqueId = effectId;
mStartTimeMs = startTimeMs;
mDurationMs = durationMs;
@@ -68,7 +81,13 @@
* @param durationMs of the effect in milliseconds
*/
public void setDuration(long durationMs) {
+ if (mStartTimeMs + durationMs > mMediaItem.getTimelineDuration()) {
+ throw new IllegalArgumentException("Duration is too large");
+ }
+
mDurationMs = durationMs;
+
+ mMediaItem.invalidateTransitions(this);
}
/**
@@ -88,7 +107,13 @@
* of the media item in milliseconds
*/
public void setStartTime(long startTimeMs) {
+ if (startTimeMs + mDurationMs > mMediaItem.getTimelineDuration()) {
+ throw new IllegalArgumentException("Start time is too large");
+ }
+
mStartTimeMs = startTimeMs;
+
+ mMediaItem.invalidateTransitions(this);
}
/**
@@ -98,6 +123,13 @@
return mStartTimeMs;
}
+ /**
+ * @return The media item owner
+ */
+ public MediaItem getMediaItem() {
+ return mMediaItem;
+ }
+
/*
* {@inheritDoc}
*/
diff --git a/media/java/android/media/videoeditor/EffectColor.java b/media/java/android/media/videoeditor/EffectColor.java
index 7c61627..f38cf75 100755
--- a/media/java/android/media/videoeditor/EffectColor.java
+++ b/media/java/android/media/videoeditor/EffectColor.java
@@ -61,12 +61,13 @@
*/
@SuppressWarnings("unused")
private EffectColor() {
- this(null, 0, 0, 0, 0);
+ this(null, null, 0, 0, 0, 0);
}
/**
* Constructor
*
+ * @param mediaItem The media item owner
* @param effectId The effect id
* @param startTimeMs The start time relative to the media item to which it
* is applied
@@ -77,9 +78,9 @@
* @param param if type is TYPE_COLOR, param is the RGB color as 888.
* Otherwise, param is ignored
*/
- public EffectColor(String effectId, long startTimeMs, long durationMs,
+ public EffectColor(MediaItem mediaItem, String effectId, long startTimeMs, long durationMs,
int type, int param) {
- super(effectId, startTimeMs, durationMs);
+ super(mediaItem, effectId, startTimeMs, durationMs);
mType = type;
mParam = param;
}
diff --git a/media/java/android/media/videoeditor/EffectKenBurns.java b/media/java/android/media/videoeditor/EffectKenBurns.java
index c6d22f4..fd2da5c 100755
--- a/media/java/android/media/videoeditor/EffectKenBurns.java
+++ b/media/java/android/media/videoeditor/EffectKenBurns.java
@@ -35,22 +35,23 @@
*/
@SuppressWarnings("unused")
private EffectKenBurns() throws IOException {
- this(null, null, null, 0, 0);
+ this(null, null, null, null, 0, 0);
}
/**
* Constructor
*
+ * @param mediaItem The media item owner
* @param effectId The effect id
* @param startRect The start rectangle
* @param endRect The end rectangle
* @param startTimeMs The start time
* @param durationMs The duration of the Ken Burns effect in milliseconds
*/
- public EffectKenBurns(String effectId, Rect startRect, Rect endRect, long startTime,
- long durationMs)
+ public EffectKenBurns(MediaItem mediaItem, String effectId, Rect startRect, Rect endRect,
+ long startTime, long durationMs)
throws IOException {
- super(effectId, startTime, durationMs);
+ super(mediaItem, effectId, startTime, durationMs);
mStartRect = startRect;
mEndRect = endRect;
diff --git a/media/java/android/media/videoeditor/MediaItem.java b/media/java/android/media/videoeditor/MediaItem.java
index e8c2a37..f4651af 100755
--- a/media/java/android/media/videoeditor/MediaItem.java
+++ b/media/java/android/media/videoeditor/MediaItem.java
@@ -205,6 +205,10 @@
* added.
*/
public void addEffect(Effect effect) {
+ if (effect.getMediaItem() != this) {
+ throw new IllegalArgumentException("Media item mismatch");
+ }
+
if (mEffects.contains(effect)) {
throw new IllegalArgumentException("Effect already exists: " + effect.getId());
}
@@ -278,6 +282,10 @@
* the bitmap do not match the dimensions of the media item
*/
public void addOverlay(Overlay overlay) {
+ if (overlay.getMediaItem() != this) {
+ throw new IllegalArgumentException("Media item mismatch");
+ }
+
if (mOverlays.contains(overlay)) {
throw new IllegalArgumentException("Overlay already exists: " + overlay.getId());
}
@@ -428,7 +436,7 @@
*
* @param effect The effect that was added or removed
*/
- private void invalidateTransitions(Effect effect) {
+ void invalidateTransitions(Effect effect) {
// Check if the effect overlaps with the beginning and end transitions
if (mBeginTransition != null) {
if (effect.getStartTime() < mBeginTransition.getDuration()) {
@@ -449,7 +457,7 @@
*
* @param overlay The effect that was added or removed
*/
- private void invalidateTransitions(Overlay overlay) {
+ void invalidateTransitions(Overlay overlay) {
// Check if the overlay overlaps with the beginning and end transitions
if (mBeginTransition != null) {
if (overlay.getStartTime() < mBeginTransition.getDuration()) {
diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java
index c70bc6a..47d4fa0 100755
--- a/media/java/android/media/videoeditor/MediaVideoItem.java
+++ b/media/java/android/media/videoeditor/MediaVideoItem.java
@@ -82,7 +82,8 @@
private final PlaybackProgressListener mListener;
private final int mCallbackAfterFrameCount;
private final long mFromMs, mToMs;
- private boolean mRun, mLoop;
+ private boolean mRun;
+ private final boolean mLoop;
private long mPositionMs;
/**
diff --git a/media/java/android/media/videoeditor/Overlay.java b/media/java/android/media/videoeditor/Overlay.java
index 5065636..d9e7f85 100755
--- a/media/java/android/media/videoeditor/Overlay.java
+++ b/media/java/android/media/videoeditor/Overlay.java
@@ -16,6 +16,9 @@
package android.media.videoeditor;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* This is the super class for all Overlay classes.
@@ -24,23 +27,27 @@
public abstract class Overlay {
// Instance variables
private final String mUniqueId;
+ // The overlay owner
+ private final MediaItem mMediaItem;
+ // user attributes
+ private final Map<String, String> mUserAttributes;
protected long mStartTimeMs;
protected long mDurationMs;
+
/**
* Default constructor
*/
@SuppressWarnings("unused")
private Overlay() {
- mUniqueId = null;
- mStartTimeMs = 0;
- mDurationMs = 0;
+ this(null, null, 0, 0);
}
/**
* Constructor
*
+ * @param mediaItem The media item owner
* @param overlayId The overlay id
* @param startTimeMs The start time relative to the media item start time
* @param durationMs The duration
@@ -48,10 +55,20 @@
* @throws IllegalArgumentException if the file type is not PNG or the
* startTimeMs and durationMs are incorrect.
*/
- public Overlay(String overlayId, long startTimeMs, long durationMs) {
+ public Overlay(MediaItem mediaItem, String overlayId, long startTimeMs, long durationMs) {
+ if (mediaItem == null) {
+ throw new IllegalArgumentException("Media item cannot be null");
+ }
+
+ if (startTimeMs + durationMs > mediaItem.getTimelineDuration()) {
+ throw new IllegalArgumentException("Invalid start time and duration");
+ }
+
+ mMediaItem = mediaItem;
mUniqueId = overlayId;
mStartTimeMs = startTimeMs;
mDurationMs = durationMs;
+ mUserAttributes = new HashMap<String, String>();
}
/**
@@ -75,7 +92,13 @@
* @param durationMs The duration in milliseconds
*/
public void setDuration(long durationMs) {
+ if (mStartTimeMs + durationMs > mMediaItem.getTimelineDuration()) {
+ throw new IllegalArgumentException("Duration is too large");
+ }
+
mDurationMs = durationMs;
+
+ mMediaItem.invalidateTransitions(this);
}
/**
@@ -93,7 +116,37 @@
* @param startTimeMs start time in milliseconds
*/
public void setStartTime(long startTimeMs) {
+ if (startTimeMs + mDurationMs > mMediaItem.getTimelineDuration()) {
+ throw new IllegalArgumentException("Start time is too large");
+ }
+
mStartTimeMs = startTimeMs;
+
+ mMediaItem.invalidateTransitions(this);
+ }
+
+ /**
+ * @return The media item owner
+ */
+ public MediaItem getMediaItem() {
+ return mMediaItem;
+ }
+
+ /**
+ * Set a user attribute
+ *
+ * @param name The attribute name
+ * @param value The attribute value
+ */
+ public void setUserAttribute(String name, String value) {
+ mUserAttributes.put(name, value);
+ }
+
+ /**
+ * @return The user attributes
+ */
+ public Map<String, String> getUserAttributes() {
+ return mUserAttributes;
}
/*
diff --git a/media/java/android/media/videoeditor/OverlayFrame.java b/media/java/android/media/videoeditor/OverlayFrame.java
index 3abac6c..c7dfc39 100755
--- a/media/java/android/media/videoeditor/OverlayFrame.java
+++ b/media/java/android/media/videoeditor/OverlayFrame.java
@@ -32,7 +32,7 @@
*/
public class OverlayFrame extends Overlay {
// Instance variables
- private final Bitmap mBitmap;
+ private Bitmap mBitmap;
private String mFilename;
/**
@@ -41,12 +41,13 @@
*/
@SuppressWarnings("unused")
private OverlayFrame() {
- this(null, (String)null, 0, 0);
+ this(null, null, (String)null, 0, 0);
}
/**
* Constructor for an OverlayFrame
*
+ * @param mediaItem The media item owner
* @param overlayId The overlay id
* @param bitmap The bitmap to be used as an overlay. The size of the
* bitmap must equal to the size of the media item to which it is
@@ -57,9 +58,9 @@
* @throws IllegalArgumentException if the file type is not PNG or the
* startTimeMs and durationMs are incorrect.
*/
- public OverlayFrame(String overlayId, Bitmap bitmap, long startTimeMs,
+ public OverlayFrame(MediaItem mediaItem, String overlayId, Bitmap bitmap, long startTimeMs,
long durationMs) {
- super(overlayId, startTimeMs, durationMs);
+ super(mediaItem, overlayId, startTimeMs, durationMs);
mBitmap = bitmap;
mFilename = null;
}
@@ -68,6 +69,7 @@
* Constructor for an OverlayFrame. This constructor can be used to
* restore the overlay after it was saved internally by the video editor.
*
+ * @param mediaItem The media item owner
* @param overlayId The overlay id
* @param filename The file name that contains the overlay.
* @param startTimeMs The overlay start time in milliseconds
@@ -76,8 +78,9 @@
* @throws IllegalArgumentException if the file type is not PNG or the
* startTimeMs and durationMs are incorrect.
*/
- OverlayFrame(String overlayId, String filename, long startTimeMs, long durationMs) {
- super(overlayId, startTimeMs, durationMs);
+ OverlayFrame(MediaItem mediaItem, String overlayId, String filename, long startTimeMs,
+ long durationMs) {
+ super(mediaItem, overlayId, startTimeMs, durationMs);
mFilename = filename;
mBitmap = BitmapFactory.decodeFile(mFilename);
}
@@ -90,6 +93,22 @@
}
/**
+ * @param bitmap The overlay bitmap
+ */
+ public void setBitmap(Bitmap bitmap) {
+ mBitmap = bitmap;
+ if (mFilename != null) {
+ // Delete the file
+ new File(mFilename).delete();
+ // Invalidate the filename
+ mFilename = null;
+ }
+
+ // Invalidate the transitions if necessary
+ getMediaItem().invalidateTransitions(this);
+ }
+
+ /**
* Get the file name of this overlay
*/
String getFilename() {
diff --git a/media/java/android/media/videoeditor/VideoEditorTestImpl.java b/media/java/android/media/videoeditor/VideoEditorTestImpl.java
index 0861992..5df4ea5 100644
--- a/media/java/android/media/videoeditor/VideoEditorTestImpl.java
+++ b/media/java/android/media/videoeditor/VideoEditorTestImpl.java
@@ -25,6 +25,7 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -50,6 +51,10 @@
private static final String TAG_MEDIA_ITEM = "media_item";
private static final String TAG_TRANSITIONS = "transitions";
private static final String TAG_TRANSITION = "transition";
+ private static final String TAG_OVERLAYS = "overlays";
+ private static final String TAG_OVERLAY = "overlay";
+ private static final String TAG_OVERLAY_USER_ATTRIBUTES = "overlay_user_attributes";
+
private static final String ATTR_ID = "id";
private static final String ATTR_FILENAME = "filename";
private static final String ATTR_AUDIO_WAVEFORM_FILENAME = "wavefoem";
@@ -572,6 +577,40 @@
Long.toString(mediaItem.getTimelineDuration()));
}
+ final List<Overlay> overlays = mediaItem.getAllOverlays();
+ if (overlays.size() > 0) {
+ serializer.startTag("", TAG_OVERLAYS);
+ for (Overlay overlay : overlays) {
+ serializer.startTag("", TAG_OVERLAY);
+ serializer.attribute("", ATTR_ID, overlay.getId());
+ serializer.attribute("", ATTR_TYPE, overlay.getClass().getSimpleName());
+ serializer.attribute("", ATTR_BEGIN_TIME,
+ Long.toString(overlay.getStartTime()));
+ serializer.attribute("", ATTR_DURATION, Long.toString(overlay.getDuration()));
+ if (overlay instanceof OverlayFrame) {
+ final OverlayFrame overlayFrame = (OverlayFrame)overlay;
+ overlayFrame.save(this);
+ if (overlayFrame.getFilename() != null) {
+ serializer.attribute("", ATTR_FILENAME, overlayFrame.getFilename());
+ }
+ }
+
+ // Save the user attributes
+ serializer.startTag("", TAG_OVERLAY_USER_ATTRIBUTES);
+ final Map<String, String> userAttributes = overlay.getUserAttributes();
+ for (String name : userAttributes.keySet()) {
+ final String value = userAttributes.get(name);
+ if (value != null) {
+ serializer.attribute("", name, value);
+ }
+ }
+ serializer.endTag("", TAG_OVERLAY_USER_ATTRIBUTES);
+
+ serializer.endTag("", TAG_OVERLAY);
+ }
+ serializer.endTag("", TAG_OVERLAYS);
+ }
+
serializer.endTag("", TAG_MEDIA_ITEM);
}
serializer.endTag("", TAG_MEDIA_ITEMS);
@@ -629,21 +668,22 @@
parser.setInput(new FileInputStream(file), "UTF-8");
int eventType = parser.getEventType();
String name;
+ MediaItem currentMediaItem = null;
+ Overlay currentOverlay = null;
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_TAG: {
name = parser.getName();
- if (name.equals(TAG_PROJECT)) {
+ if (TAG_PROJECT.equals(name)) {
mAspectRatio = Integer.parseInt(parser.getAttributeValue("",
ATTR_ASPECT_RATIO));
- } else if (name.equals(TAG_MEDIA_ITEM)) {
+ } else if (TAG_MEDIA_ITEM.equals(name)) {
final String mediaItemId = parser.getAttributeValue("", ATTR_ID);
final String type = parser.getAttributeValue("", ATTR_TYPE);
final String filename = parser.getAttributeValue("", ATTR_FILENAME);
final int renderingMode = Integer.parseInt(parser.getAttributeValue("",
ATTR_RENDERING_MODE));
- MediaItem currentMediaItem;
if (MediaImageItem.class.getSimpleName().equals(type)) {
final long durationMs = Long.parseLong(parser.getAttributeValue("",
ATTR_DURATION));
@@ -673,11 +713,36 @@
if (currentMediaItem != null) {
mMediaItems.add(currentMediaItem);
}
- } else if (name.equals(TAG_TRANSITION)) {
+ } else if (TAG_TRANSITION.equals(name)) {
final Transition transition = parseTransition(parser);
if (transition != null) {
mTransitions.add(transition);
}
+ } else if (TAG_OVERLAY.equals(name)) {
+ if (currentMediaItem != null) {
+ currentOverlay = parseOverlay(parser, currentMediaItem);
+ if (currentOverlay != null) {
+ currentMediaItem.addOverlay(currentOverlay);
+ }
+ }
+ } else if (TAG_OVERLAY_USER_ATTRIBUTES.equals(name)) {
+ if (currentOverlay != null) {
+ final int attributesCount = parser.getAttributeCount();
+ for (int i = 0; i < attributesCount; i++) {
+ currentOverlay.setUserAttribute(parser.getAttributeName(i),
+ parser.getAttributeValue(i));
+ }
+ }
+ }
+ break;
+ }
+
+ case XmlPullParser.END_TAG: {
+ name = parser.getName();
+ if (TAG_MEDIA_ITEM.equals(name)) {
+ currentMediaItem = null;
+ } else if (TAG_OVERLAY.equals(name)) {
+ currentOverlay = null;
}
break;
}
@@ -764,6 +829,31 @@
return transition;
}
+ /**
+ * Parse the overlay
+ *
+ * @param parser The parser
+ * @param mediaItem The media item owner
+ *
+ * @return The overlay
+ */
+ private Overlay parseOverlay(XmlPullParser parser, MediaItem mediaItem) {
+ final String overlayId = parser.getAttributeValue("", ATTR_ID);
+ final String type = parser.getAttributeValue("", ATTR_TYPE);
+ final long durationMs = Long.parseLong(parser.getAttributeValue("", ATTR_DURATION));
+ final long startTimeMs = Long.parseLong(parser.getAttributeValue("", ATTR_BEGIN_TIME));
+
+ final Overlay overlay;
+ if (OverlayFrame.class.getSimpleName().equals(type)) {
+ final String filename = parser.getAttributeValue("", ATTR_FILENAME);
+ overlay = new OverlayFrame(mediaItem, overlayId, filename, startTimeMs, durationMs);
+ } else {
+ overlay = null;
+ }
+
+ return overlay;
+ }
+
public void cancelExport(String filename) {
}
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
index 8f40130..ebe3302 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.cpp
@@ -63,7 +63,6 @@
// Flag to allow a one time init of global memory, only happens on first call ever
int LvmInitFlag = LVM_FALSE;
-int LvmSessionsActive = 0;
SessionContext GlobalSessionMemory[LVM_MAX_SESSIONS];
int SessionIndex[LVM_MAX_SESSIONS];
@@ -189,16 +188,19 @@
int32_t sessionId,
int32_t ioId,
effect_interface_t *pInterface){
- int ret;
+ int ret = 0;
int sessionNo;
int i;
- EffectContext *pContext = new EffectContext;
+ EffectContext *pContext = NULL;
+ bool newBundle = false;
+ SessionContext *pSessionContext;
LOGV("\n\tEffectCreate start session %d", sessionId);
if (pInterface == NULL || uuid == NULL){
LOGV("\tLVM_ERROR : EffectCreate() called with NULL pointer");
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit;
}
if(LvmInitFlag == LVM_FALSE){
@@ -207,8 +209,6 @@
LvmGlobalBundle_init();
}
- LOGV("\tEffectCreate: There are %d LVM sessions acive\n", LvmSessionsActive);
-
// Find next available sessionNo
for(i=0; i<LVM_MAX_SESSIONS; i++){
if((SessionIndex[i] == LVM_UNUSED_SESSION)||(SessionIndex[i] == sessionId)){
@@ -221,23 +221,20 @@
if(i==LVM_MAX_SESSIONS){
LOGV("\tLVM_ERROR : Cannot find memory to allocate for current session");
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit;
}
+
+ pContext = new EffectContext;
+
// If this is the first create in this session
if(GlobalSessionMemory[sessionNo].bBundledEffectsEnabled == LVM_FALSE){
LOGV("\tEffectCreate - This is the first effect in current sessionId %d sessionNo %d",
sessionId, sessionNo);
- LvmSessionsActive++;
-
- if(LvmSessionsActive >= LVM_MAX_SESSIONS){
- LOGV("\tLVM_ERROR : Number of active session is greater than LVM_MAX_SESSIONS (%d)",
- LVM_MAX_SESSIONS);
- return -EINVAL;
- }
-
GlobalSessionMemory[sessionNo].bBundledEffectsEnabled = LVM_TRUE;
GlobalSessionMemory[sessionNo].pBundledContext = new BundledEffectContext;
+ newBundle = true;
pContext->pBundledContext = GlobalSessionMemory[sessionNo].pBundledContext;
pContext->pBundledContext->SessionNo = sessionNo;
@@ -251,17 +248,16 @@
pContext->pBundledContext->bVirtualizerTempDisabled = LVM_FALSE;
pContext->pBundledContext->NumberEffectsEnabled = 0;
pContext->pBundledContext->NumberEffectsCalled = 0;
- pContext->pBundledContext->frameCount = 0;
pContext->pBundledContext->firstVolume = LVM_TRUE;
#ifdef LVM_PCM
-
char fileName[256];
snprintf(fileName, 256, "/data/tmp/bundle_%p_pcm_in.pcm", pContext->pBundledContext);
pContext->pBundledContext->PcmInPtr = fopen(fileName, "w");
if (pContext->pBundledContext->PcmInPtr == NULL) {
LOGV("cannot open %s", fileName);
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit;
}
snprintf(fileName, 256, "/data/tmp/bundle_%p_pcm_out.pcm", pContext->pBundledContext);
@@ -270,7 +266,8 @@
LOGV("cannot open %s", fileName);
fclose(pContext->pBundledContext->PcmInPtr);
pContext->pBundledContext->PcmInPtr = NULL;
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit;
}
#endif
@@ -285,15 +282,18 @@
pContext->pBundledContext->bMuteEnabled = LVM_FALSE;
pContext->pBundledContext->bStereoPositionEnabled = LVM_FALSE;
pContext->pBundledContext->positionSaved = 0;
+ pContext->pBundledContext->workBuffer = NULL;
+ pContext->pBundledContext->frameCount = -1;
+ pContext->pBundledContext->SamplesToExitCountVirt = 0;
+ pContext->pBundledContext->SamplesToExitCountBb = 0;
+ pContext->pBundledContext->SamplesToExitCountEq = 0;
LOGV("\tEffectCreate - Calling LvmBundle_init");
ret = LvmBundle_init(pContext);
if (ret < 0){
LOGV("\tLVM_ERROR : EffectCreate() Bundle init failed");
- delete pContext->pBundledContext;
- delete pContext;
- return ret;
+ goto exit;
}
}
else{
@@ -304,13 +304,14 @@
}
LOGV("\tEffectCreate - pBundledContext is %p", pContext->pBundledContext);
- SessionContext *pSessionContext = &GlobalSessionMemory[pContext->pBundledContext->SessionNo];
+ pSessionContext = &GlobalSessionMemory[pContext->pBundledContext->SessionNo];
// Create each Effect
if (memcmp(uuid, &gBassBoostDescriptor.uuid, sizeof(effect_uuid_t)) == 0){
// Create Bass Boost
LOGV("\tEffectCreate - Effect to be created is LVM_BASS_BOOST");
pSessionContext->bBassInstantiated = LVM_TRUE;
+ pContext->pBundledContext->SamplesToExitCountBb = 0;
pContext->itfe = &gLvmEffectInterface;
pContext->EffectType = LVM_BASS_BOOST;
@@ -318,6 +319,7 @@
// Create Virtualizer
LOGV("\tEffectCreate - Effect to be created is LVM_VIRTUALIZER");
pSessionContext->bVirtualizerInstantiated=LVM_TRUE;
+ pContext->pBundledContext->SamplesToExitCountVirt = 0;
pContext->itfe = &gLvmEffectInterface;
pContext->EffectType = LVM_VIRTUALIZER;
@@ -325,6 +327,7 @@
// Create Equalizer
LOGV("\tEffectCreate - Effect to be created is LVM_EQUALIZER");
pSessionContext->bEqualizerInstantiated = LVM_TRUE;
+ pContext->pBundledContext->SamplesToExitCountEq = 0;
pContext->itfe = &gLvmEffectInterface;
pContext->EffectType = LVM_EQUALIZER;
@@ -338,46 +341,77 @@
}
else{
LOGV("\tLVM_ERROR : EffectCreate() invalid UUID");
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit;
}
- *pInterface = (effect_interface_t)pContext;
+exit:
+ if (ret != 0) {
+ if (pContext != NULL) {
+ if (newBundle) {
+ GlobalSessionMemory[sessionNo].bBundledEffectsEnabled = LVM_FALSE;
+ SessionIndex[sessionNo] = LVM_UNUSED_SESSION;
+ delete pContext->pBundledContext;
+ }
+ delete pContext;
+ }
+ *pInterface = (effect_interface_t)NULL;
+ } else {
+ *pInterface = (effect_interface_t)pContext;
+ }
LOGV("\tEffectCreate end..\n\n");
- return 0;
+ return ret;
} /* end EffectCreate */
extern "C" int EffectRelease(effect_interface_t interface){
LOGV("\n\tEffectRelease start %p", interface);
EffectContext * pContext = (EffectContext *)interface;
- LOGV("\n\tEffectRelease start interface: %p, context %p", interface, pContext->pBundledContext);
+ LOGV("\tEffectRelease start interface: %p, context %p", interface, pContext->pBundledContext);
if (pContext == NULL){
LOGV("\tLVM_ERROR : EffectRelease called with NULL pointer");
return -EINVAL;
}
-
- Effect_setEnabled(pContext, LVM_FALSE);
-
SessionContext *pSessionContext = &GlobalSessionMemory[pContext->pBundledContext->SessionNo];
// Clear the instantiated flag for the effect
+ // protect agains the case where an effect is un-instantiated without being disabled
if(pContext->EffectType == LVM_BASS_BOOST) {
LOGV("\tEffectRelease LVM_BASS_BOOST Clearing global intstantiated flag");
pSessionContext->bBassInstantiated = LVM_FALSE;
+ if(pContext->pBundledContext->SamplesToExitCountBb > 0){
+ pContext->pBundledContext->NumberEffectsEnabled--;
+ }
+ pContext->pBundledContext->SamplesToExitCountBb = 0;
} else if(pContext->EffectType == LVM_VIRTUALIZER) {
LOGV("\tEffectRelease LVM_VIRTUALIZER Clearing global intstantiated flag");
pSessionContext->bVirtualizerInstantiated = LVM_FALSE;
+ if(pContext->pBundledContext->SamplesToExitCountVirt > 0){
+ pContext->pBundledContext->NumberEffectsEnabled--;
+ }
+ pContext->pBundledContext->SamplesToExitCountVirt = 0;
} else if(pContext->EffectType == LVM_EQUALIZER) {
LOGV("\tEffectRelease LVM_EQUALIZER Clearing global intstantiated flag");
pSessionContext->bEqualizerInstantiated =LVM_FALSE;
+ if(pContext->pBundledContext->SamplesToExitCountEq > 0){
+ pContext->pBundledContext->NumberEffectsEnabled--;
+ }
+ pContext->pBundledContext->SamplesToExitCountEq = 0;
} else if(pContext->EffectType == LVM_VOLUME) {
LOGV("\tEffectRelease LVM_VOLUME Clearing global intstantiated flag");
pSessionContext->bVolumeInstantiated = LVM_FALSE;
+ if (pContext->pBundledContext->bVolumeEnabled == LVM_TRUE){
+ pContext->pBundledContext->NumberEffectsEnabled--;
+ }
} else {
LOGV("\tLVM_ERROR : EffectRelease : Unsupported effect\n\n\n\n\n\n\n");
}
+ // Disable effect, in this case ignore errors (return codes)
+ // if an effect has already been disabled
+ Effect_setEnabled(pContext, LVM_FALSE);
+
// if all effects are no longer instantiaed free the lvm memory and delete BundledEffectContext
if ((pSessionContext->bBassInstantiated == LVM_FALSE) &&
(pSessionContext->bVolumeInstantiated == LVM_FALSE) &&
@@ -395,8 +429,6 @@
}
#endif
- LvmSessionsActive--;
- LOGV("\tEffectRelease: There are %d LVM sessions remaining\n", LvmSessionsActive);
// Clear the SessionIndex
for(int i=0; i<LVM_MAX_SESSIONS; i++){
@@ -409,11 +441,14 @@
}
LOGV("\tEffectRelease: All effects are no longer instantiated\n");
- pSessionContext->bBundledEffectsEnabled =LVM_FALSE;
+ pSessionContext->bBundledEffectsEnabled = LVM_FALSE;
pSessionContext->pBundledContext = LVM_NULL;
LOGV("\tEffectRelease: Freeing LVM Bundle memory\n");
LvmEffect_free(pContext);
LOGV("\tEffectRelease: Deleting LVM Bundle context %p\n", pContext->pBundledContext);
+ if (pContext->pBundledContext->workBuffer != NULL) {
+ free(pContext->pBundledContext->workBuffer);
+ }
delete pContext->pBundledContext;
pContext->pBundledContext = LVM_NULL;
}
@@ -643,6 +678,14 @@
return 0;
} /* end LvmBundle_init */
+
+static inline int16_t clamp16(int32_t sample)
+{
+ if ((sample>>15) ^ (sample>>31))
+ sample = 0x7FFF ^ (sample>>31);
+ return sample;
+}
+
//----------------------------------------------------------------------------
// LvmBundle_process()
//----------------------------------------------------------------------------
@@ -668,39 +711,25 @@
LVM_ControlParams_t ActiveParams; /* Current control Parameters */
LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
-
LVM_INT16 *pOutTmp;
+
if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_WRITE){
pOutTmp = pOut;
}else if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
- pOutTmp = (LVM_INT16 *)malloc(frameCount * sizeof(LVM_INT16) * 2);
- if(pOutTmp == NULL){
- LOGV("\tLVM_ERROR : LvmBundle_process failed to allocate memory for "
- "EFFECT_BUFFER_ACCESS_ACCUMULATE mode");
- return -EINVAL;
+ if (pContext->pBundledContext->frameCount != frameCount) {
+ if (pContext->pBundledContext->workBuffer != NULL) {
+ free(pContext->pBundledContext->workBuffer);
+ }
+ pContext->pBundledContext->workBuffer =
+ (LVM_INT16 *)malloc(frameCount * sizeof(LVM_INT16) * 2);
+ pContext->pBundledContext->frameCount = frameCount;
}
+ pOutTmp = pContext->pBundledContext->workBuffer;
}else{
LOGV("LVM_ERROR : LvmBundle_process invalid access mode");
return -EINVAL;
}
- /* Get the current settings */
- LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance,
- &ActiveParams);
-
- LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "LvmBundle_process")
- if(LvmStatus != LVM_SUCCESS) return -EINVAL;
-
- pContext->pBundledContext->frameCount++;
- if(pContext->pBundledContext->frameCount == 100)
- {
- //LOGV("\tBB: %d VIRT: %d EQ: %d, session (%d), context is %p\n",
- //ActiveParams.BE_OperatingMode,
- //ActiveParams.VirtualizerOperatingMode, ActiveParams.EQNB_OperatingMode,
- //pContext->pBundledContext->SessionNo, pContext->pBundledContext);
- pContext->pBundledContext->frameCount = 0;
- }
-
#ifdef LVM_PCM
fwrite(pIn, frameCount*sizeof(LVM_INT16)*2, 1, pContext->pBundledContext->PcmInPtr);
fflush(pContext->pBundledContext->PcmInPtr);
@@ -725,9 +754,8 @@
if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
for (int i=0; i<frameCount*2; i++){
- pOut[i] += pOutTmp[i];
+ pOut[i] = clamp16((LVM_INT32)pOut[i] + (LVM_INT32)pOutTmp[i]);
}
- free(pOutTmp);
}
return 0;
} /* end LvmBundle_process */
@@ -813,15 +841,15 @@
ActiveParams.BE_OperatingMode = LVM_BE_OFF;
}
if(pContext->EffectType == LVM_VIRTUALIZER) {
- LOGV("\tLvmEffect_disable : Enabling LVM_VIRTUALIZER");
+ LOGV("\tLvmEffect_disable : Disabling LVM_VIRTUALIZER");
ActiveParams.VirtualizerOperatingMode = LVM_MODE_OFF;
}
if(pContext->EffectType == LVM_EQUALIZER) {
- LOGV("\tLvmEffect_disable : Enabling LVM_EQUALIZER");
+ LOGV("\tLvmEffect_disable : Disabling LVM_EQUALIZER");
ActiveParams.EQNB_OperatingMode = LVM_EQNB_OFF;
}
if(pContext->EffectType == LVM_VOLUME) {
- LOGV("\tLvmEffect_disable : Enabling LVM_VOLUME");
+ LOGV("\tLvmEffect_disable : Disabling LVM_VOLUME");
}
LvmStatus = LVM_SetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
@@ -2406,85 +2434,114 @@
switch (pContext->EffectType) {
case LVM_BASS_BOOST:
if (pContext->pBundledContext->bBassEnabled == LVM_TRUE) {
- LOGV("\tLVM_ERROR : Effect_setEnabled() LVM_BASS_BOOST is already enabled");
+ LOGV("\tEffect_setEnabled() LVM_BASS_BOOST is already enabled");
return -EINVAL;
}
+ if(pContext->pBundledContext->SamplesToExitCountBb <= 0){
+ pContext->pBundledContext->NumberEffectsEnabled++;
+ }
pContext->pBundledContext->SamplesToExitCountBb =
(LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
pContext->pBundledContext->bBassEnabled = LVM_TRUE;
break;
case LVM_EQUALIZER:
if (pContext->pBundledContext->bEqualizerEnabled == LVM_TRUE) {
- LOGV("\tLVM_ERROR : Effect_setEnabled() LVM_EQUALIZER is already enabled");
+ LOGV("\tEffect_setEnabled() LVM_EQUALIZER is already enabled");
return -EINVAL;
}
+ if(pContext->pBundledContext->SamplesToExitCountEq <= 0){
+ pContext->pBundledContext->NumberEffectsEnabled++;
+ }
pContext->pBundledContext->SamplesToExitCountEq =
(LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
pContext->pBundledContext->bEqualizerEnabled = LVM_TRUE;
break;
case LVM_VIRTUALIZER:
if (pContext->pBundledContext->bVirtualizerEnabled == LVM_TRUE) {
- LOGV("\tLVM_ERROR : Effect_setEnabled() LVM_VIRTUALIZER is already enabled");
+ LOGV("\tEffect_setEnabled() LVM_VIRTUALIZER is already enabled");
return -EINVAL;
}
+ if(pContext->pBundledContext->SamplesToExitCountVirt <= 0){
+ pContext->pBundledContext->NumberEffectsEnabled++;
+ }
pContext->pBundledContext->SamplesToExitCountVirt =
(LVM_INT32)(pContext->pBundledContext->SamplesPerSecond*0.1);
pContext->pBundledContext->bVirtualizerEnabled = LVM_TRUE;
break;
case LVM_VOLUME:
if (pContext->pBundledContext->bVolumeEnabled == LVM_TRUE) {
- LOGV("\tLVM_ERROR : Effect_setEnabled() LVM_VOLUME is already enabled");
+ LOGV("\tEffect_setEnabled() LVM_VOLUME is already enabled");
return -EINVAL;
}
+ pContext->pBundledContext->NumberEffectsEnabled++;
pContext->pBundledContext->bVolumeEnabled = LVM_TRUE;
break;
default:
- LOGV("\tLVM_ERROR : Effect_setEnabled() invalid effect type");
+ LOGV("\tEffect_setEnabled() invalid effect type");
return -EINVAL;
}
- pContext->pBundledContext->NumberEffectsEnabled++;
LvmEffect_enable(pContext);
} else {
switch (pContext->EffectType) {
case LVM_BASS_BOOST:
if (pContext->pBundledContext->bBassEnabled == LVM_FALSE) {
- LOGV("\tLVM_ERROR : Effect_setEnabled() LVM_BASS_BOOST is already disabled");
+ LOGV("\tEffect_setEnabled() LVM_BASS_BOOST is already disabled");
return -EINVAL;
}
pContext->pBundledContext->bBassEnabled = LVM_FALSE;
break;
case LVM_EQUALIZER:
if (pContext->pBundledContext->bEqualizerEnabled == LVM_FALSE) {
- LOGV("\tLVM_ERROR : Effect_setEnabled() LVM_EQUALIZER is already disabled");
+ LOGV("\tEffect_setEnabled() LVM_EQUALIZER is already disabled");
return -EINVAL;
}
pContext->pBundledContext->bEqualizerEnabled = LVM_FALSE;
break;
case LVM_VIRTUALIZER:
if (pContext->pBundledContext->bVirtualizerEnabled == LVM_FALSE) {
- LOGV("\tLVM_ERROR : Effect_setEnabled() LVM_VIRTUALIZER is already disabled");
+ LOGV("\tEffect_setEnabled() LVM_VIRTUALIZER is already disabled");
return -EINVAL;
}
pContext->pBundledContext->bVirtualizerEnabled = LVM_FALSE;
break;
case LVM_VOLUME:
if (pContext->pBundledContext->bVolumeEnabled == LVM_FALSE) {
- LOGV("\tLVM_ERROR : Effect_setEnabled() LVM_VOLUME is already disabled");
+ LOGV("\tEffect_setEnabled() LVM_VOLUME is already disabled");
return -EINVAL;
}
pContext->pBundledContext->bVolumeEnabled = LVM_FALSE;
break;
default:
- LOGV("\tLVM_ERROR : Effect_setEnabled() invalid effect type");
+ LOGV("\tEffect_setEnabled() invalid effect type");
return -EINVAL;
}
- pContext->pBundledContext->NumberEffectsEnabled--;
LvmEffect_disable(pContext);
}
return 0;
}
+//----------------------------------------------------------------------------
+// LVC_Convert_VolToDb()
+//----------------------------------------------------------------------------
+// Purpose:
+// Convery volume in Q24 to dB
+//
+// Inputs:
+// vol: Q.24 volume dB
+//
+//-----------------------------------------------------------------------
+
+int16_t LVC_Convert_VolToDb(uint32_t vol){
+ int16_t dB;
+
+ dB = LVC_ToDB_s32Tos16(vol <<7);
+ dB = (dB +8)>>4;
+ dB = (dB <-96) ? -96 : dB ;
+
+ return dB;
+}
+
} // namespace
} // namespace
@@ -2493,32 +2550,31 @@
audio_buffer_t *inBuffer,
audio_buffer_t *outBuffer){
EffectContext * pContext = (EffectContext *) self;
- LVM_ControlParams_t ActiveParams; /* Current control Parameters */
LVM_ReturnStatus_en LvmStatus = LVM_SUCCESS; /* Function call status */
int status = 0;
- int status2Sec = 0;
int lvmStatus = 0;
LVM_INT16 *in = (LVM_INT16 *)inBuffer->raw;
LVM_INT16 *out = (LVM_INT16 *)outBuffer->raw;
-//LOGV("\tEffect_process Start : Enabled = %d Called = %d",
-//pContext->pBundledContext->NumberEffectsEnabled,pContext->pBundledContext->NumberEffectsCalled);
-// LOGV("\tEffect_process Start : Samples left %d %d %d",
+//LOGV("\tEffect_process Start : Enabled = %d Called = %d (%8d %8d %8d)",
+//pContext->pBundledContext->NumberEffectsEnabled,pContext->pBundledContext->NumberEffectsCalled,
// pContext->pBundledContext->SamplesToExitCountBb,
// pContext->pBundledContext->SamplesToExitCountVirt,
// pContext->pBundledContext->SamplesToExitCountEq);
-// LvmStatus = LVM_GetControlParameters(pContext->pBundledContext->hInstance, &ActiveParams);
-// LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeGetStereoPosition")
-// if(LvmStatus != LVM_SUCCESS) return -EINVAL;
-// LOGV("\tEffect_process Internal Operating Modes: BB %d VIRT %d EQ %d",
-// ActiveParams.BE_OperatingMode, ActiveParams.VirtualizerOperatingMode,
-// ActiveParams.EQNB_OperatingMode);
-
if (pContext == NULL){
LOGV("\tLVM_ERROR : Effect_process() ERROR pContext == NULL");
return -EINVAL;
}
+
+ //if(pContext->EffectType == LVM_BASS_BOOST){
+ // LOGV("\tEffect_process: Effect type is BASS_BOOST");
+ //}else if(pContext->EffectType == LVM_EQUALIZER){
+ // LOGV("\tEffect_process: Effect type is LVM_EQUALIZER");
+ //}else if(pContext->EffectType == LVM_VIRTUALIZER){
+ // LOGV("\tEffect_process: Effect type is LVM_VIRTUALIZER");
+ //}
+
if (inBuffer == NULL || inBuffer->raw == NULL ||
outBuffer == NULL || outBuffer->raw == NULL ||
inBuffer->frameCount != outBuffer->frameCount){
@@ -2529,70 +2585,57 @@
(pContext->EffectType == LVM_BASS_BOOST)){
//LOGV("\tEffect_process() LVM_BASS_BOOST Effect is not enabled");
if(pContext->pBundledContext->SamplesToExitCountBb > 0){
- status2Sec = -ENODATA;
pContext->pBundledContext->SamplesToExitCountBb -= outBuffer->frameCount * 2; // STEREO
//LOGV("\tEffect_process: Waiting to turn off BASS_BOOST, %d samples left",
// pContext->pBundledContext->SamplesToExitCountBb);
} else {
status = -ENODATA;
+ pContext->pBundledContext->NumberEffectsEnabled--;
}
}
if ((pContext->pBundledContext->bVolumeEnabled == LVM_FALSE)&&
(pContext->EffectType == LVM_VOLUME)){
//LOGV("\tEffect_process() LVM_VOLUME Effect is not enabled");
status = -ENODATA;
+ pContext->pBundledContext->NumberEffectsEnabled--;
}
if ((pContext->pBundledContext->bEqualizerEnabled == LVM_FALSE)&&
(pContext->EffectType == LVM_EQUALIZER)){
//LOGV("\tEffect_process() LVM_EQUALIZER Effect is not enabled");
if(pContext->pBundledContext->SamplesToExitCountEq > 0){
- status2Sec = -ENODATA;
pContext->pBundledContext->SamplesToExitCountEq -= outBuffer->frameCount * 2; // STEREO
- //LOGV("\tEffect_process: Waiting for 2 secs to turn off EQUALIZER, %d samples left",
+ //LOGV("\tEffect_process: Waiting to turn off EQUALIZER, %d samples left",
// pContext->pBundledContext->SamplesToExitCountEq);
} else {
status = -ENODATA;
+ pContext->pBundledContext->NumberEffectsEnabled--;
}
}
if ((pContext->pBundledContext->bVirtualizerEnabled == LVM_FALSE)&&
(pContext->EffectType == LVM_VIRTUALIZER)){
//LOGV("\tEffect_process() LVM_VIRTUALIZER Effect is not enabled");
if(pContext->pBundledContext->SamplesToExitCountVirt > 0){
- status2Sec = -ENODATA;
pContext->pBundledContext->SamplesToExitCountVirt -= outBuffer->frameCount * 2;// STEREO
- //LOGV("\tEffect_process: Waiting for 2 secs to turn off VIRTUALIZER, %d samples left",
+ //LOGV("\tEffect_process: Waiting for to turn off VIRTUALIZER, %d samples left",
// pContext->pBundledContext->SamplesToExitCountVirt);
} else {
status = -ENODATA;
+ pContext->pBundledContext->NumberEffectsEnabled--;
}
}
- // If this is the last frame of an effect process its output with no effect
- if(status == -ENODATA){
- if (pContext->config.outputCfg.accessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE){
- //LOGV("\tLVM_ERROR : Effect_process() accumulating last frame into output buffer");
- //LOGV("\tLVM_ERROR : Effect_process() trying copying last frame into output buffer");
- //LOGV("\tLVM_ERROR : Enabled = %d Called = %d",
- //pContext->pBundledContext->NumberEffectsEnabled,
- //pContext->pBundledContext->NumberEffectsCalled);
-
- }else{
- //LOGV("\tLVM_ERROR : Effect_process() copying last frame into output buffer");
- }
- }
-
- if((status2Sec != -ENODATA)&&(status != -ENODATA)){
+ if(status != -ENODATA){
pContext->pBundledContext->NumberEffectsCalled++;
}
if(pContext->pBundledContext->NumberEffectsCalled ==
pContext->pBundledContext->NumberEffectsEnabled){
- //LOGV("\tEffect_process Calling process with %d effects enabled, %d called: Effect %d",
+ //LOGV("\tEffect_process Calling process with %d effects enabled, %d called: Effect %d",
//pContext->pBundledContext->NumberEffectsEnabled,
//pContext->pBundledContext->NumberEffectsCalled, pContext->EffectType);
if(status == -ENODATA){
- //LOGV("\tLVM_ERROR : Effect_process() actually processing last frame");
+ LOGV("\tEffect_process() processing last frame");
}
pContext->pBundledContext->NumberEffectsCalled = 0;
/* Process all the available frames, block processing is
@@ -2836,10 +2879,10 @@
case EFFECT_CMD_SET_PARAM:{
//LOGV("\tEffect_command cmdCode Case: EFFECT_CMD_SET_PARAM start");
if(pContext->EffectType == LVM_BASS_BOOST){
- //LOGV("\tBassBoost_command EFFECT_CMD_SET_PARAM param %d, *replySize %d, value %d ",
- // *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)),
- // *replySize,
- // *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t)));
+ //LOGV("\tBassBoost_command EFFECT_CMD_SET_PARAM param %d, *replySize %d, value %d",
+ // *(int32_t *)((char *)pCmdData + sizeof(effect_param_t)),
+ // *replySize,
+ // *(int16_t *)((char *)pCmdData + sizeof(effect_param_t) + sizeof(int32_t)));
if (pCmdData == NULL||
cmdSize != (int)(sizeof(effect_param_t) + sizeof(int32_t) +sizeof(int16_t))||
@@ -3038,30 +3081,71 @@
}
case EFFECT_CMD_SET_VOLUME:
{
- int32_t vol = *(int32_t *)pCmdData;
- int16_t dB;
- int32_t vol_ret[2] = {1<<24,1<<24}; // Apply no volume
+ uint32_t leftVolume, rightVolume;
+ int16_t leftdB, rightdB;
+ int16_t maxdB, pandB;
+ int32_t vol_ret[2] = {1<<24,1<<24}; // Apply no volume
+ int status = 0;
+ LVM_ControlParams_t ActiveParams; /* Current control Parameters */
+ LVM_ReturnStatus_en LvmStatus=LVM_SUCCESS; /* Function call status */
// if pReplyData is NULL, VOL_CTRL is delegated to another effect
if(pReplyData == LVM_NULL){
break;
}
- if(vol==0x1000000){
- vol -= 1;
+ if (pCmdData == NULL ||
+ cmdSize != 2 * sizeof(uint32_t)) {
+ LOGV("\tLVM_ERROR : Effect_command cmdCode Case: "
+ "EFFECT_CMD_SET_VOLUME: ERROR");
+ return -EINVAL;
}
- // Convert volume linear (Q8.24) to volume dB (0->-96)
- dB = android::LVC_ToDB_s32Tos16(vol <<7);
- dB = (dB +8)>>4;
- dB = (dB <-96) ? -96 : dB ;
- LOGV("\tEFFECT_CMD_SET_VOLUME Session: %d, SessionID: %d VOLUME is %d dB (%d), "
- "effect is %d",
- pContext->pBundledContext->SessionNo, pContext->pBundledContext->SessionId,
- (int32_t)dB, vol<<7, pContext->EffectType);
+ leftVolume = ((*(uint32_t *)pCmdData));
+ rightVolume = ((*((uint32_t *)pCmdData + 1)));
+
+ if(leftVolume == 0x1000000){
+ leftVolume -= 1;
+ }
+ if(rightVolume == 0x1000000){
+ rightVolume -= 1;
+ }
+
+ // Convert volume to dB
+ leftdB = android::LVC_Convert_VolToDb(leftVolume);
+ rightdB = android::LVC_Convert_VolToDb(rightVolume);
+
+ pandB = rightdB - leftdB;
+
+ // Calculate max volume in dB
+ maxdB = leftdB;
+ if(rightdB > maxdB){
+ maxdB = rightdB;
+ }
+ //LOGV("\tEFFECT_CMD_SET_VOLUME Session: %d, SessionID: %d VOLUME is %d dB (%d), "
+ // "effect is %d",
+ //pContext->pBundledContext->SessionNo, pContext->pBundledContext->SessionId,
+ //(int32_t)maxdB, maxVol<<7, pContext->EffectType);
+ //LOGV("\tEFFECT_CMD_SET_VOLUME: Left is %d, Right is %d", leftVolume, rightVolume);
+ //LOGV("\tEFFECT_CMD_SET_VOLUME: Left %ddB, Right %ddB, Position %ddB",
+ // leftdB, rightdB, pandB);
memcpy(pReplyData, vol_ret, sizeof(int32_t)*2);
- android::VolumeSetVolumeLevel(pContext, (int16_t)(dB*100));
+ android::VolumeSetVolumeLevel(pContext, (int16_t)(maxdB*100));
+
+ /* Get the current settings */
+ LvmStatus =LVM_GetControlParameters(pContext->pBundledContext->hInstance,&ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_GetControlParameters", "VolumeSetStereoPosition")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
+
+ /* Volume parameters */
+ ActiveParams.VC_Balance = pandB;
+ LOGV("\t\tVolumeSetStereoPosition() (-96dB -> +96dB)-> %d\n", ActiveParams.VC_Balance );
+
+ /* Activate the initial settings */
+ LvmStatus =LVM_SetControlParameters(pContext->pBundledContext->hInstance,&ActiveParams);
+ LVM_ERROR_CHECK(LvmStatus, "LVM_SetControlParameters", "VolumeSetStereoPosition")
+ if(LvmStatus != LVM_SUCCESS) return -EINVAL;
break;
}
case EFFECT_CMD_SET_AUDIO_MODE:
diff --git a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
index 91963af..2b51029 100644
--- a/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
+++ b/media/libeffects/lvm/wrapper/Bundle/EffectBundle.h
@@ -88,12 +88,13 @@
int positionSaved;
bool bMuteEnabled; /* Must store as mute = -96dB level */
bool bStereoPositionEnabled;
- int frameCount;
LVM_Fs_en SampleRate;
int SamplesPerSecond;
int SamplesToExitCountEq;
int SamplesToExitCountBb;
int SamplesToExitCountVirt;
+ LVM_INT16 *workBuffer;
+ int frameCount;
#ifdef LVM_PCM
FILE *PcmInPtr;
FILE *PcmOutPtr;
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index ffe1983..877e787 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -534,8 +534,9 @@
if (f) {
while (!feof(f)) {
fgets(buffer, SIZE, f);
- if (strstr(buffer, " /sdcard/") ||
+ if (strstr(buffer, " /mnt/sdcard/") ||
strstr(buffer, " /system/sounds/") ||
+ strstr(buffer, " /data/") ||
strstr(buffer, " /system/media/")) {
result.append(" ");
result.append(buffer);
@@ -569,8 +570,9 @@
} else {
linkto[len] = 0;
}
- if (strstr(linkto, "/sdcard/") == linkto ||
+ if (strstr(linkto, "/mnt/sdcard/") == linkto ||
strstr(linkto, "/system/sounds/") == linkto ||
+ strstr(linkto, "/data/") == linkto ||
strstr(linkto, "/system/media/") == linkto) {
result.append(" ");
result.append(buffer);
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 3bf8ae7..472bfcf 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -18,6 +18,7 @@
HTTPStream.cpp \
JPEGSource.cpp \
MP3Extractor.cpp \
+ MPEG2TSWriter.cpp \
MPEG4Extractor.cpp \
MPEG4Writer.cpp \
MediaBuffer.cpp \
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index c27cfc8..b314114 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -27,9 +27,13 @@
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
+#include "include/AwesomePlayer.h"
+
namespace android {
-AudioPlayer::AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink)
+AudioPlayer::AudioPlayer(
+ const sp<MediaPlayerBase::AudioSink> &audioSink,
+ AwesomePlayer *observer)
: mAudioTrack(NULL),
mInputBuffer(NULL),
mSampleRate(0),
@@ -45,7 +49,8 @@
mIsFirstBuffer(false),
mFirstBufferResult(OK),
mFirstBuffer(NULL),
- mAudioSink(audioSink) {
+ mAudioSink(audioSink),
+ mObserver(observer) {
}
AudioPlayer::~AudioPlayer() {
@@ -301,6 +306,9 @@
}
mSeeking = false;
+ if (mObserver) {
+ mObserver->postAudioSeekComplete();
+ }
}
}
@@ -323,6 +331,10 @@
Mutex::Autolock autoLock(mLock);
if (err != OK) {
+ if (mObserver && !mReachedEOS) {
+ mObserver->postAudioEOS();
+ }
+
mReachedEOS = true;
mFinalStatus = err;
break;
@@ -411,6 +423,12 @@
mReachedEOS = false;
mSeekTimeUs = time_us;
+ if (mAudioSink != NULL) {
+ mAudioSink->flush();
+ } else {
+ mAudioTrack->flush();
+ }
+
return OK;
}
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index fd5f30b..97c9003 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -642,7 +642,7 @@
if (mAudioSource != NULL) {
if (mAudioPlayer == NULL) {
if (mAudioSink != NULL) {
- mAudioPlayer = new AudioPlayer(mAudioSink);
+ mAudioPlayer = new AudioPlayer(mAudioSink, this);
mAudioPlayer->setSource(mAudioSource);
// We've already started the MediaSource in order to enable
@@ -669,8 +669,6 @@
} else {
mAudioPlayer->resume();
}
-
- postCheckAudioStatusEvent_l();
}
if (mTimeSource == NULL && mAudioPlayer == NULL) {
@@ -1191,7 +1189,7 @@
return;
}
mAudioStatusEventPending = true;
- mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll);
+ mQueue.postEvent(mCheckAudioStatusEvent);
}
void AwesomePlayer::onCheckAudioStatus() {
@@ -1222,8 +1220,6 @@
mFlags |= FIRST_FRAME;
postStreamDoneEvent_l(finalStatus);
}
-
- postCheckAudioStatusEvent_l();
}
status_t AwesomePlayer::prepare() {
@@ -1685,5 +1681,13 @@
return mExtractorFlags;
}
+void AwesomePlayer::postAudioEOS() {
+ postCheckAudioStatusEvent_l();
+}
+
+void AwesomePlayer::postAudioSeekComplete() {
+ postCheckAudioStatusEvent_l();
+}
+
} // namespace android
diff --git a/media/libstagefright/MPEG2TSWriter.cpp b/media/libstagefright/MPEG2TSWriter.cpp
new file mode 100644
index 0000000..ee74b88
--- /dev/null
+++ b/media/libstagefright/MPEG2TSWriter.cpp
@@ -0,0 +1,758 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "MPEG2TSWriter"
+#include <media/stagefright/foundation/ADebug.h>
+
+#include <media/stagefright/foundation/hexdump.h>
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MPEG2TSWriter.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/Utils.h>
+
+#include "include/ESDS.h"
+
+namespace android {
+
+struct MPEG2TSWriter::SourceInfo : public AHandler {
+ SourceInfo(const sp<MediaSource> &source);
+
+ void start(const sp<AMessage> ¬ify);
+ void stop();
+
+ unsigned streamType() const;
+ unsigned incrementContinuityCounter();
+
+ enum {
+ kNotifyStartFailed,
+ kNotifyBuffer,
+ kNotifyReachedEOS,
+ };
+
+protected:
+ virtual void onMessageReceived(const sp<AMessage> &msg);
+
+ virtual ~SourceInfo();
+
+private:
+ enum {
+ kWhatStart = 'strt',
+ kWhatRead = 'read',
+ };
+
+ sp<MediaSource> mSource;
+ sp<ALooper> mLooper;
+ sp<AMessage> mNotify;
+
+ sp<ABuffer> mAACBuffer;
+
+ unsigned mStreamType;
+ unsigned mContinuityCounter;
+
+ void extractCodecSpecificData();
+
+ void appendAACFrames(MediaBuffer *buffer);
+ void flushAACFrames();
+
+ void postAVCFrame(MediaBuffer *buffer);
+
+ DISALLOW_EVIL_CONSTRUCTORS(SourceInfo);
+};
+
+MPEG2TSWriter::SourceInfo::SourceInfo(const sp<MediaSource> &source)
+ : mSource(source),
+ mLooper(new ALooper),
+ mStreamType(0),
+ mContinuityCounter(0) {
+ mLooper->setName("MPEG2TSWriter source");
+
+ sp<MetaData> meta = mSource->getFormat();
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
+ mStreamType = 0x0f;
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+ mStreamType = 0x1b;
+ } else {
+ TRESPASS();
+ }
+}
+
+MPEG2TSWriter::SourceInfo::~SourceInfo() {
+}
+
+unsigned MPEG2TSWriter::SourceInfo::streamType() const {
+ return mStreamType;
+}
+
+unsigned MPEG2TSWriter::SourceInfo::incrementContinuityCounter() {
+ if (++mContinuityCounter == 16) {
+ mContinuityCounter = 0;
+ }
+
+ return mContinuityCounter;
+}
+
+void MPEG2TSWriter::SourceInfo::start(const sp<AMessage> ¬ify) {
+ mLooper->registerHandler(this);
+ mLooper->start();
+
+ mNotify = notify;
+
+ (new AMessage(kWhatStart, id()))->post();
+}
+
+void MPEG2TSWriter::SourceInfo::stop() {
+ mLooper->unregisterHandler(id());
+ mLooper->stop();
+}
+
+void MPEG2TSWriter::SourceInfo::extractCodecSpecificData() {
+ sp<MetaData> meta = mSource->getFormat();
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
+ return;
+ }
+
+ sp<ABuffer> out = new ABuffer(1024);
+ out->setRange(0, 0);
+
+ uint32_t type;
+ const void *data;
+ size_t size;
+ CHECK(meta->findData(kKeyAVCC, &type, &data, &size));
+
+ const uint8_t *ptr = (const uint8_t *)data;
+
+ size_t numSeqParameterSets = ptr[5] & 31;
+
+ ptr += 6;
+ size -= 6;
+
+ for (size_t i = 0; i < numSeqParameterSets; ++i) {
+ CHECK(size >= 2);
+ size_t length = U16_AT(ptr);
+
+ ptr += 2;
+ size -= 2;
+
+ CHECK(size >= length);
+
+ CHECK_LE(out->size() + 4 + length, out->capacity());
+ memcpy(out->data() + out->size(), "\x00\x00\x00\x01", 4);
+ memcpy(out->data() + out->size() + 4, ptr, length);
+ out->setRange(0, out->size() + length + 4);
+
+ ptr += length;
+ size -= length;
+ }
+
+ CHECK(size >= 1);
+ size_t numPictureParameterSets = *ptr;
+ ++ptr;
+ --size;
+
+ for (size_t i = 0; i < numPictureParameterSets; ++i) {
+ CHECK(size >= 2);
+ size_t length = U16_AT(ptr);
+
+ ptr += 2;
+ size -= 2;
+
+ CHECK(size >= length);
+
+ CHECK_LE(out->size() + 4 + length, out->capacity());
+ memcpy(out->data() + out->size(), "\x00\x00\x00\x01", 4);
+ memcpy(out->data() + out->size() + 4, ptr, length);
+ out->setRange(0, out->size() + length + 4);
+
+ ptr += length;
+ size -= length;
+ }
+
+ out->meta()->setInt64("timeUs", 0ll);
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kNotifyBuffer);
+ notify->setObject("buffer", out);
+ notify->post();
+}
+
+void MPEG2TSWriter::SourceInfo::postAVCFrame(MediaBuffer *buffer) {
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kNotifyBuffer);
+
+ sp<ABuffer> copy =
+ new ABuffer(buffer->range_length());
+ memcpy(copy->data(),
+ (const uint8_t *)buffer->data()
+ + buffer->range_offset(),
+ buffer->range_length());
+
+ int64_t timeUs;
+ CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
+ copy->meta()->setInt64("timeUs", timeUs);
+
+ int32_t isSync;
+ if (buffer->meta_data()->findInt32(kKeyIsSyncFrame, &isSync)
+ && isSync != 0) {
+ copy->meta()->setInt32("isSync", true);
+ }
+
+ notify->setObject("buffer", copy);
+ notify->post();
+}
+
+void MPEG2TSWriter::SourceInfo::appendAACFrames(MediaBuffer *buffer) {
+ if (mAACBuffer != NULL
+ && mAACBuffer->size() + 7 + buffer->range_length()
+ > mAACBuffer->capacity()) {
+ flushAACFrames();
+ }
+
+ if (mAACBuffer == NULL) {
+ size_t alloc = 4096;
+ if (buffer->range_length() + 7 > alloc) {
+ alloc = 7 + buffer->range_length();
+ }
+
+ mAACBuffer = new ABuffer(alloc);
+
+ int64_t timeUs;
+ CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
+
+ mAACBuffer->meta()->setInt64("timeUs", timeUs);
+ mAACBuffer->meta()->setInt32("isSync", true);
+
+ mAACBuffer->setRange(0, 0);
+ }
+
+ sp<MetaData> meta = mSource->getFormat();
+ uint32_t type;
+ const void *data;
+ size_t size;
+ CHECK(meta->findData(kKeyESDS, &type, &data, &size));
+
+ ESDS esds((const char *)data, size);
+ CHECK_EQ(esds.InitCheck(), (status_t)OK);
+
+ const uint8_t *codec_specific_data;
+ size_t codec_specific_data_size;
+ esds.getCodecSpecificInfo(
+ (const void **)&codec_specific_data, &codec_specific_data_size);
+
+ CHECK_GE(codec_specific_data_size, 2u);
+
+ unsigned profile = (codec_specific_data[0] >> 3) - 1;
+
+ unsigned sampling_freq_index =
+ ((codec_specific_data[0] & 7) << 1)
+ | (codec_specific_data[1] >> 7);
+
+ unsigned channel_configuration =
+ (codec_specific_data[1] >> 3) & 0x0f;
+
+ uint8_t *ptr = mAACBuffer->data() + mAACBuffer->size();
+
+ const uint32_t aac_frame_length = buffer->range_length() + 7;
+
+ *ptr++ = 0xff;
+ *ptr++ = 0xf1; // b11110001, ID=0, layer=0, protection_absent=1
+
+ *ptr++ =
+ profile << 6
+ | sampling_freq_index << 2
+ | ((channel_configuration >> 2) & 1); // private_bit=0
+
+ // original_copy=0, home=0, copyright_id_bit=0, copyright_id_start=0
+ *ptr++ =
+ (channel_configuration & 3) << 6
+ | aac_frame_length >> 11;
+ *ptr++ = (aac_frame_length >> 3) & 0xff;
+ *ptr++ = (aac_frame_length & 7) << 5;
+
+ // adts_buffer_fullness=0, number_of_raw_data_blocks_in_frame=0
+ *ptr++ = 0;
+
+ memcpy(ptr,
+ (const uint8_t *)buffer->data() + buffer->range_offset(),
+ buffer->range_length());
+
+ ptr += buffer->range_length();
+
+ mAACBuffer->setRange(0, ptr - mAACBuffer->data());
+}
+
+void MPEG2TSWriter::SourceInfo::flushAACFrames() {
+ if (mAACBuffer == NULL) {
+ return;
+ }
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kNotifyBuffer);
+ notify->setObject("buffer", mAACBuffer);
+ notify->post();
+
+ mAACBuffer.clear();
+}
+
+void MPEG2TSWriter::SourceInfo::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatStart:
+ {
+ status_t err = mSource->start();
+ if (err != OK) {
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kNotifyStartFailed);
+ notify->post();
+ break;
+ }
+
+ extractCodecSpecificData();
+
+ (new AMessage(kWhatRead, id()))->post();
+ break;
+ }
+
+ case kWhatRead:
+ {
+ MediaBuffer *buffer;
+ status_t err = mSource->read(&buffer);
+
+ if (err != OK && err != INFO_FORMAT_CHANGED) {
+ if (mStreamType == 0x0f) {
+ flushAACFrames();
+ }
+
+ sp<AMessage> notify = mNotify->dup();
+ notify->setInt32("what", kNotifyReachedEOS);
+ notify->setInt32("status", err);
+ notify->post();
+ break;
+ }
+
+ if (err == OK) {
+ if (buffer->range_length() > 0) {
+ if (mStreamType == 0x0f) {
+ appendAACFrames(buffer);
+ } else {
+ postAVCFrame(buffer);
+ }
+ }
+
+ buffer->release();
+ buffer = NULL;
+ }
+
+ msg->post();
+ break;
+ }
+
+ default:
+ TRESPASS();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+MPEG2TSWriter::MPEG2TSWriter(const char *filename)
+ : mFile(fopen(filename, "wb")),
+ mStarted(false),
+ mNumSourcesDone(0),
+ mNumTSPacketsWritten(0),
+ mNumTSPacketsBeforeMeta(0) {
+ CHECK(mFile != NULL);
+
+ mLooper = new ALooper;
+ mLooper->setName("MPEG2TSWriter");
+
+ mReflector = new AHandlerReflector<MPEG2TSWriter>(this);
+
+ mLooper->registerHandler(mReflector);
+ mLooper->start();
+}
+
+MPEG2TSWriter::~MPEG2TSWriter() {
+ mLooper->unregisterHandler(mReflector->id());
+ mLooper->stop();
+
+ fclose(mFile);
+ mFile = NULL;
+}
+
+status_t MPEG2TSWriter::addSource(const sp<MediaSource> &source) {
+ CHECK(!mStarted);
+
+ sp<MetaData> meta = source->getFormat();
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ if (strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)
+ && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ sp<SourceInfo> info = new SourceInfo(source);
+
+ mSources.push(info);
+
+ return OK;
+}
+
+status_t MPEG2TSWriter::start(MetaData *param) {
+ CHECK(!mStarted);
+
+ mStarted = true;
+ mNumSourcesDone = 0;
+ mNumTSPacketsWritten = 0;
+ mNumTSPacketsBeforeMeta = 0;
+
+ for (size_t i = 0; i < mSources.size(); ++i) {
+ sp<AMessage> notify =
+ new AMessage(kWhatSourceNotify, mReflector->id());
+
+ notify->setInt32("source-index", i);
+
+ mSources.editItemAt(i)->start(notify);
+ }
+
+ return OK;
+}
+
+status_t MPEG2TSWriter::stop() {
+ CHECK(mStarted);
+
+ for (size_t i = 0; i < mSources.size(); ++i) {
+ mSources.editItemAt(i)->stop();
+ }
+ mStarted = false;
+
+ return OK;
+}
+
+status_t MPEG2TSWriter::pause() {
+ CHECK(mStarted);
+
+ return OK;
+}
+
+bool MPEG2TSWriter::reachedEOS() {
+ return !mStarted || (mNumSourcesDone == mSources.size() ? true : false);
+}
+
+status_t MPEG2TSWriter::dump(int fd, const Vector<String16> &args) {
+ return OK;
+}
+
+void MPEG2TSWriter::onMessageReceived(const sp<AMessage> &msg) {
+ switch (msg->what()) {
+ case kWhatSourceNotify:
+ {
+ int32_t sourceIndex;
+ CHECK(msg->findInt32("source-index", &sourceIndex));
+
+ int32_t what;
+ CHECK(msg->findInt32("what", &what));
+
+ if (what == SourceInfo::kNotifyReachedEOS
+ || what == SourceInfo::kNotifyStartFailed) {
+ ++mNumSourcesDone;
+ } else if (what == SourceInfo::kNotifyBuffer) {
+ sp<RefBase> obj;
+ CHECK(msg->findObject("buffer", &obj));
+
+ writeTS();
+
+ sp<ABuffer> buffer = static_cast<ABuffer *>(obj.get());
+ writeAccessUnit(sourceIndex, buffer);
+ }
+ break;
+ }
+
+ default:
+ TRESPASS();
+ }
+}
+
+void MPEG2TSWriter::writeProgramAssociationTable() {
+ // 0x47
+ // transport_error_indicator = b0
+ // payload_unit_start_indicator = b1
+ // transport_priority = b0
+ // PID = b0000000000000 (13 bits)
+ // transport_scrambling_control = b00
+ // adaptation_field_control = b01 (no adaptation field, payload only)
+ // continuity_counter = b????
+ // skip = 0x00
+ // --- payload follows
+ // table_id = 0x00
+ // section_syntax_indicator = b1
+ // must_be_zero = b0
+ // reserved = b11
+ // section_length = 0x00d
+ // transport_stream_id = 0x0000
+ // reserved = b11
+ // version_number = b00001
+ // current_next_indicator = b1
+ // section_number = 0x00
+ // last_section_number = 0x00
+ // one program follows:
+ // program_number = 0x0001
+ // reserved = b111
+ // program_map_PID = 0x01e0 (13 bits!)
+ // CRC = 0x????????
+
+ static const uint8_t kData[] = {
+ 0x47,
+ 0x40, 0x00, 0x10, 0x00, // b0100 0000 0000 0000 0001 ???? 0000 0000
+ 0x00, 0xb0, 0x0d, 0x00, // b0000 0000 1011 0000 0000 1101 0000 0000
+ 0x00, 0xc3, 0x00, 0x00, // b0000 0000 1100 0011 0000 0000 0000 0000
+ 0x00, 0x01, 0xe1, 0xe0, // b0000 0000 0000 0001 1110 0001 1110 0000
+ 0x00, 0x00, 0x00, 0x00 // b???? ???? ???? ???? ???? ???? ???? ????
+ };
+
+ sp<ABuffer> buffer = new ABuffer(188);
+ memset(buffer->data(), 0, buffer->size());
+ memcpy(buffer->data(), kData, sizeof(kData));
+
+ static const unsigned kContinuityCounter = 5;
+ buffer->data()[3] |= kContinuityCounter;
+
+ CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), buffer->size());
+}
+
+void MPEG2TSWriter::writeProgramMap() {
+ // 0x47
+ // transport_error_indicator = b0
+ // payload_unit_start_indicator = b1
+ // transport_priority = b0
+ // PID = b0 0001 1110 0000 (13 bits) [0x1e0]
+ // transport_scrambling_control = b00
+ // adaptation_field_control = b01 (no adaptation field, payload only)
+ // continuity_counter = b????
+ // skip = 0x00
+ // -- payload follows
+ // table_id = 0x02
+ // section_syntax_indicator = b1
+ // must_be_zero = b0
+ // reserved = b11
+ // section_length = 0x???
+ // program_number = 0x0001
+ // reserved = b11
+ // version_number = b00001
+ // current_next_indicator = b1
+ // section_number = 0x00
+ // last_section_number = 0x00
+ // reserved = b111
+ // PCR_PID = b? ???? ???? ???? (13 bits)
+ // reserved = b1111
+ // program_info_length = 0x000
+ // one or more elementary stream descriptions follow:
+ // stream_type = 0x??
+ // reserved = b111
+ // elementary_PID = b? ???? ???? ???? (13 bits)
+ // reserved = b1111
+ // ES_info_length = 0x000
+ // CRC = 0x????????
+
+ static const uint8_t kData[] = {
+ 0x47,
+ 0x41, 0xe0, 0x10, 0x00, // b0100 0001 1110 0000 0001 ???? 0000 0000
+ 0x02, 0xb0, 0x00, 0x00, // b0000 0010 1011 ???? ???? ???? 0000 0000
+ 0x01, 0xc3, 0x00, 0x00, // b0000 0001 1100 0011 0000 0000 0000 0000
+ 0xe0, 0x00, 0xf0, 0x00 // b111? ???? ???? ???? 1111 0000 0000 0000
+ };
+
+ sp<ABuffer> buffer = new ABuffer(188);
+ memset(buffer->data(), 0, buffer->size());
+ memcpy(buffer->data(), kData, sizeof(kData));
+
+ static const unsigned kContinuityCounter = 5;
+ buffer->data()[3] |= kContinuityCounter;
+
+ size_t section_length = 5 * mSources.size() + 4 + 9;
+ buffer->data()[6] |= section_length >> 8;
+ buffer->data()[7] = section_length & 0xff;
+
+ static const unsigned kPCR_PID = 0x1e1;
+ buffer->data()[13] |= (kPCR_PID >> 8) & 0x1f;
+ buffer->data()[14] = kPCR_PID & 0xff;
+
+ uint8_t *ptr = &buffer->data()[sizeof(kData)];
+ for (size_t i = 0; i < mSources.size(); ++i) {
+ *ptr++ = mSources.editItemAt(i)->streamType();
+
+ const unsigned ES_PID = 0x1e0 + i + 1;
+ *ptr++ = 0xe0 | (ES_PID >> 8);
+ *ptr++ = ES_PID & 0xff;
+ *ptr++ = 0xf0;
+ *ptr++ = 0x00;
+ }
+
+ *ptr++ = 0x00;
+ *ptr++ = 0x00;
+ *ptr++ = 0x00;
+ *ptr++ = 0x00;
+
+ CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), buffer->size());
+}
+
+void MPEG2TSWriter::writeAccessUnit(
+ int32_t sourceIndex, const sp<ABuffer> &accessUnit) {
+ // 0x47
+ // transport_error_indicator = b0
+ // payload_unit_start_indicator = b1
+ // transport_priority = b0
+ // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex]
+ // transport_scrambling_control = b00
+ // adaptation_field_control = b01 (no adaptation field, payload only)
+ // continuity_counter = b????
+ // -- payload follows
+ // packet_startcode_prefix = 0x000001
+ // stream_id = 0x?? (0xe0 for avc video, 0xc0 for aac audio)
+ // PES_packet_length = 0x????
+ // reserved = b10
+ // PES_scrambling_control = b00
+ // PES_priority = b0
+ // data_alignment_indicator = b1
+ // copyright = b0
+ // original_or_copy = b0
+ // PTS_DTS_flags = b10 (PTS only)
+ // ESCR_flag = b0
+ // ES_rate_flag = b0
+ // DSM_trick_mode_flag = b0
+ // additional_copy_info_flag = b0
+ // PES_CRC_flag = b0
+ // PES_extension_flag = b0
+ // PES_header_data_length = 0x05
+ // reserved = b0010 (PTS)
+ // PTS[32..30] = b???
+ // reserved = b1
+ // PTS[29..15] = b??? ???? ???? ???? (15 bits)
+ // reserved = b1
+ // PTS[14..0] = b??? ???? ???? ???? (15 bits)
+ // reserved = b1
+ // the first fragment of "buffer" follows
+
+ sp<ABuffer> buffer = new ABuffer(188);
+ memset(buffer->data(), 0, buffer->size());
+
+ const unsigned PID = 0x1e0 + sourceIndex + 1;
+
+ const unsigned continuity_counter =
+ mSources.editItemAt(sourceIndex)->incrementContinuityCounter();
+
+ // XXX if there are multiple streams of a kind (more than 1 audio or
+ // more than 1 video) they need distinct stream_ids.
+ const unsigned stream_id =
+ mSources.editItemAt(sourceIndex)->streamType() == 0x0f ? 0xc0 : 0xe0;
+
+ int64_t timeUs;
+ CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
+
+ uint32_t PTS = (timeUs * 9ll) / 100ll;
+
+ size_t PES_packet_length = accessUnit->size() + 8;
+
+ uint8_t *ptr = buffer->data();
+ *ptr++ = 0x47;
+ *ptr++ = 0x40 | (PID >> 8);
+ *ptr++ = PID & 0xff;
+ *ptr++ = 0x10 | continuity_counter;
+ *ptr++ = 0x00;
+ *ptr++ = 0x00;
+ *ptr++ = 0x01;
+ *ptr++ = stream_id;
+ *ptr++ = PES_packet_length >> 8;
+ *ptr++ = PES_packet_length & 0xff;
+ *ptr++ = 0x84;
+ *ptr++ = 0x80;
+ *ptr++ = 0x05;
+ *ptr++ = 0x20 | (((PTS >> 30) & 7) << 1) | 1;
+ *ptr++ = (PTS >> 22) & 0xff;
+ *ptr++ = (((PTS >> 15) & 0x7f) << 1) | 1;
+ *ptr++ = (PTS >> 7) & 0xff;
+ *ptr++ = ((PTS & 0x7f) << 1) | 1;
+
+ size_t sizeLeft = buffer->data() + buffer->size() - ptr;
+ size_t copy = accessUnit->size();
+ if (copy > sizeLeft) {
+ copy = sizeLeft;
+ }
+
+ memcpy(ptr, accessUnit->data(), copy);
+
+ CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile), buffer->size());
+
+ size_t offset = copy;
+ while (offset < accessUnit->size()) {
+ // for subsequent fragments of "buffer":
+ // 0x47
+ // transport_error_indicator = b0
+ // payload_unit_start_indicator = b0
+ // transport_priority = b0
+ // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex]
+ // transport_scrambling_control = b00
+ // adaptation_field_control = b01 (no adaptation field, payload only)
+ // continuity_counter = b????
+ // the fragment of "buffer" follows.
+
+ memset(buffer->data(), 0, buffer->size());
+
+ const unsigned continuity_counter =
+ mSources.editItemAt(sourceIndex)->incrementContinuityCounter();
+
+ ptr = buffer->data();
+ *ptr++ = 0x47;
+ *ptr++ = 0x00 | (PID >> 8);
+ *ptr++ = PID & 0xff;
+ *ptr++ = 0x10 | continuity_counter;
+
+ size_t sizeLeft = buffer->data() + buffer->size() - ptr;
+ size_t copy = accessUnit->size() - offset;
+ if (copy > sizeLeft) {
+ copy = sizeLeft;
+ }
+
+ memcpy(ptr, accessUnit->data() + offset, copy);
+ CHECK_EQ(fwrite(buffer->data(), 1, buffer->size(), mFile),
+ buffer->size());
+
+ offset += copy;
+ }
+}
+
+void MPEG2TSWriter::writeTS() {
+ if (mNumTSPacketsWritten >= mNumTSPacketsBeforeMeta) {
+ writeProgramAssociationTable();
+ writeProgramMap();
+
+ mNumTSPacketsBeforeMeta = mNumTSPacketsWritten + 2500;
+ }
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index 7a8cf32..43938b2 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -93,7 +93,10 @@
sp<DataSource> mSource;
off_t mOffset;
Page mCurrentPage;
+ uint64_t mPrevGranulePosition;
size_t mCurrentPageSize;
+ bool mFirstPacketInPage;
+ uint64_t mCurrentPageSamples;
size_t mNextLaceIndex;
off_t mFirstDataOffset;
@@ -113,6 +116,8 @@
void parseFileMetaData();
void extractAlbumArt(const void *data, size_t size);
+ uint64_t findPrevGranulePosition(off_t pageOffset);
+
MyVorbisExtractor(const MyVorbisExtractor &);
MyVorbisExtractor &operator=(const MyVorbisExtractor &);
};
@@ -193,7 +198,10 @@
MyVorbisExtractor::MyVorbisExtractor(const sp<DataSource> &source)
: mSource(source),
mOffset(0),
+ mPrevGranulePosition(0),
mCurrentPageSize(0),
+ mFirstPacketInPage(true),
+ mCurrentPageSamples(0),
mNextLaceIndex(0),
mFirstDataOffset(-1) {
mCurrentPage.mNumSegments = 0;
@@ -238,6 +246,52 @@
}
}
+// Given the offset of the "current" page, find the page immediately preceding
+// it (if any) and return its granule position.
+// To do this we back up from the "current" page's offset until we find any
+// page preceding it and then scan forward to just before the current page.
+uint64_t MyVorbisExtractor::findPrevGranulePosition(off_t pageOffset) {
+ off_t prevPageOffset = 0;
+ off_t prevGuess = pageOffset;
+ for (;;) {
+ if (prevGuess >= 5000) {
+ prevGuess -= 5000;
+ } else {
+ prevGuess = 0;
+ }
+
+ LOGV("backing up %ld bytes", pageOffset - prevGuess);
+
+ CHECK_EQ(findNextPage(prevGuess, &prevPageOffset), (status_t)OK);
+
+ if (prevPageOffset < pageOffset || prevGuess == 0) {
+ break;
+ }
+ }
+
+ if (prevPageOffset == pageOffset) {
+ // We did not find a page preceding this one.
+ return 0;
+ }
+
+ LOGV("prevPageOffset at %ld, pageOffset at %ld", prevPageOffset, pageOffset);
+
+ for (;;) {
+ Page prevPage;
+ ssize_t n = readPage(prevPageOffset, &prevPage);
+
+ if (n <= 0) {
+ return 0;
+ }
+
+ prevPageOffset += n;
+
+ if (prevPageOffset == pageOffset) {
+ return prevPage.mGranulePosition;
+ }
+ }
+}
+
status_t MyVorbisExtractor::seekToOffset(off_t offset) {
if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) {
// Once we know where the actual audio data starts (past the headers)
@@ -252,9 +306,16 @@
return err;
}
+ // We found the page we wanted to seek to, but we'll also need
+ // the page preceding it to determine how many valid samples are on
+ // this page.
+ mPrevGranulePosition = findPrevGranulePosition(pageOffset);
+
mOffset = pageOffset;
mCurrentPageSize = 0;
+ mFirstPacketInPage = true;
+ mCurrentPageSamples = 0;
mCurrentPage.mNumSegments = 0;
mNextLaceIndex = 0;
@@ -399,6 +460,12 @@
buffer->meta_data()->setInt64(kKeyTime, timeUs);
}
+ if (mFirstPacketInPage) {
+ buffer->meta_data()->setInt32(
+ kKeyValidSamples, mCurrentPageSamples);
+ mFirstPacketInPage = false;
+ }
+
*out = buffer;
return OK;
@@ -423,6 +490,12 @@
return n < 0 ? n : (status_t)ERROR_END_OF_STREAM;
}
+ mCurrentPageSamples =
+ mCurrentPage.mGranulePosition - mPrevGranulePosition;
+ mFirstPacketInPage = true;
+
+ mPrevGranulePosition = mCurrentPage.mGranulePosition;
+
mCurrentPageSize = n;
mNextLaceIndex = 0;
@@ -435,6 +508,10 @@
buffer->meta_data()->setInt64(kKeyTime, timeUs);
}
+ buffer->meta_data()->setInt32(
+ kKeyValidSamples, mCurrentPageSamples);
+ mFirstPacketInPage = false;
+
*out = buffer;
return OK;
diff --git a/media/libstagefright/codecs/aacdec/AACDecoder.cpp b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
index e4ed5e6..f58c16d 100644
--- a/media/libstagefright/codecs/aacdec/AACDecoder.cpp
+++ b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
@@ -171,6 +171,10 @@
mInputBuffer->release();
mInputBuffer = NULL;
}
+
+ // Make sure that the next buffer output does not still
+ // depend on fragments from the last one decoded.
+ PVMP4AudioDecoderResetBuffer(mDecoderBuf);
} else {
seekTimeUs = -1;
}
diff --git a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
index c4a8280..59dd740 100644
--- a/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
+++ b/media/libstagefright/codecs/mp3dec/MP3Decoder.cpp
@@ -132,6 +132,10 @@
mInputBuffer->release();
mInputBuffer = NULL;
}
+
+ // Make sure that the next buffer output does not still
+ // depend on fragments from the last one decoded.
+ pvmp3_InitDecoder(mConfig, mDecoderBuf);
} else {
seekTimeUs = -1;
}
diff --git a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp b/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
index 53f0638..703b41e 100644
--- a/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/VorbisDecoder.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "VorbisDecoder"
+#include <utils/Log.h>
+
#include "VorbisDecoder.h"
#include <media/stagefright/MediaBufferGroup.h>
@@ -108,6 +112,7 @@
mAnchorTimeUs = 0;
mNumFramesOutput = 0;
+ mNumFramesLeftOnPage = 0;
mStarted = true;
return OK;
@@ -188,6 +193,13 @@
}
}
+ if (numFrames > mNumFramesLeftOnPage) {
+ LOGV("discarding %d frames at end of page",
+ numFrames - mNumFramesLeftOnPage);
+ numFrames = mNumFramesLeftOnPage;
+ }
+ mNumFramesLeftOnPage -= numFrames;
+
out->set_range(0, numFrames * sizeof(int16_t) * mNumChannels);
return numFrames;
@@ -226,6 +238,12 @@
CHECK(seekTimeUs < 0);
}
+ int32_t numPageSamples;
+ if (inputBuffer->meta_data()->findInt32(
+ kKeyValidSamples, &numPageSamples)) {
+ mNumFramesLeftOnPage = numPageSamples;
+ }
+
MediaBuffer *outputBuffer;
CHECK_EQ(mBufferGroup->acquire_buffer(&outputBuffer), OK);
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index ea2f7d5..db98253 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -93,6 +93,9 @@
// This is a mask of MediaExtractor::Flags.
uint32_t flags() const;
+ void postAudioEOS();
+ void postAudioSeekComplete();
+
private:
friend struct AwesomeEvent;
diff --git a/media/libstagefright/include/VorbisDecoder.h b/media/libstagefright/include/VorbisDecoder.h
index e9a488a..13e8b77 100644
--- a/media/libstagefright/include/VorbisDecoder.h
+++ b/media/libstagefright/include/VorbisDecoder.h
@@ -55,6 +55,7 @@
int32_t mSampleRate;
int64_t mAnchorTimeUs;
int64_t mNumFramesOutput;
+ int32_t mNumFramesLeftOnPage;
vorbis_dsp_state *mState;
vorbis_info *mVi;
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 9952783..47cca80 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -389,20 +389,23 @@
// ES data follows.
- onPayloadData(
- PTS_DTS_flags, PTS, DTS,
- br->data(), br->numBitsLeft() / 8);
-
if (PES_packet_length != 0) {
CHECK_GE(PES_packet_length, PES_header_data_length + 3);
unsigned dataLength =
PES_packet_length - 3 - PES_header_data_length;
- CHECK_EQ(br->numBitsLeft(), dataLength * 8);
+ CHECK_GE(br->numBitsLeft(), dataLength * 8);
+
+ onPayloadData(
+ PTS_DTS_flags, PTS, DTS, br->data(), dataLength);
br->skipBits(dataLength * 8);
} else {
+ onPayloadData(
+ PTS_DTS_flags, PTS, DTS,
+ br->data(), br->numBitsLeft() / 8);
+
size_t payloadSizeBits = br->numBitsLeft();
CHECK((payloadSizeBits % 8) == 0);
@@ -491,7 +494,7 @@
CHECK(picParamSet != NULL);
buffer->setRange(stopOffset, size - stopOffset);
- LOGI("buffer has %d bytes left.", buffer->size());
+ LOGV("buffer has %d bytes left.", buffer->size());
size_t csdSize =
1 + 3 + 1 + 1
@@ -527,6 +530,8 @@
const uint8_t *data = *_data;
size_t size = *_size;
+ // hexdump(data, size);
+
*nalStart = NULL;
*nalSize = 0;
@@ -572,18 +577,23 @@
++offset;
}
- CHECK_LT(offset + 2, size);
-
*nalStart = &data[startOffset];
*nalSize = endOffset - startOffset;
- *_data = &data[offset];
- *_size = size - offset;
+ if (offset + 2 < size) {
+ *_data = &data[offset];
+ *_size = size - offset;
+ } else {
+ *_data = NULL;
+ *_size = 0;
+ }
return true;
}
sp<ABuffer> MakeCleanAVCData(const uint8_t *data, size_t size) {
+ // hexdump(data, size);
+
const uint8_t *tmpData = data;
size_t tmpSize = size;
@@ -591,6 +601,7 @@
const uint8_t *nalStart;
size_t nalSize;
while (getNextNALUnit(&tmpData, &tmpSize, &nalStart, &nalSize)) {
+ // hexdump(nalStart, nalSize);
totalSize += 4 + nalSize;
}
@@ -615,15 +626,15 @@
CHECK_EQ(br.getBits(2), 0u);
br.getBits(1); // protection_absent
unsigned profile = br.getBits(2);
- LOGI("profile = %u", profile);
+ LOGV("profile = %u", profile);
CHECK_NE(profile, 3u);
unsigned sampling_freq_index = br.getBits(4);
br.getBits(1); // private_bit
unsigned channel_configuration = br.getBits(3);
CHECK_NE(channel_configuration, 0u);
- LOGI("sampling_freq_index = %u", sampling_freq_index);
- LOGI("channel_configuration = %u", channel_configuration);
+ LOGV("sampling_freq_index = %u", sampling_freq_index);
+ LOGV("channel_configuration = %u", channel_configuration);
CHECK_LE(sampling_freq_index, 11u);
static const int32_t kSamplingFreq[] = {
@@ -707,8 +718,8 @@
sp<ABuffer> csd =
FindMPEG2ADTSConfig(buffer, &sampleRate, &channelCount);
- LOGI("sampleRate = %d", sampleRate);
- LOGI("channelCount = %d", channelCount);
+ LOGV("sampleRate = %d", sampleRate);
+ LOGV("channelCount = %d", channelCount);
meta->setInt32(kKeySampleRate, sampleRate);
meta->setInt32(kKeyChannelCount, channelCount);
@@ -716,7 +727,7 @@
meta->setData(kKeyESDS, 0, csd->data(), csd->size());
}
- LOGI("created source!");
+ LOGV("created source!");
mSource = new AnotherPacketSource(meta);
// fall through
@@ -915,7 +926,10 @@
unsigned adaptation_field_control = br->getBits(2);
LOGV("adaptation_field_control = %u", adaptation_field_control);
- MY_LOGV("continuity_counter = %u", br->getBits(4));
+ unsigned continuity_counter = br->getBits(4);
+ LOGV("continuity_counter = %u", continuity_counter);
+
+ // LOGI("PID = 0x%04x, continuity_counter = %u", PID, continuity_counter);
if (adaptation_field_control == 2 || adaptation_field_control == 3) {
parseAdaptationField(br);
diff --git a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
index 56ca375..2417305 100644
--- a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
+++ b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
@@ -32,6 +32,8 @@
namespace android {
+static const size_t kTSPacketSize = 188;
+
struct MPEG2TSSource : public MediaSource {
MPEG2TSSource(
const sp<MPEG2TSExtractor> &extractor,
@@ -126,27 +128,37 @@
void MPEG2TSExtractor::init() {
bool haveAudio = false;
bool haveVideo = false;
+ int numPacketsParsed = 0;
while (feedMore() == OK) {
ATSParser::SourceType type;
if (haveAudio && haveVideo) {
break;
}
- if (haveVideo) {
- type = ATSParser::MPEG2ADTS_AUDIO;
- } else {
- type = ATSParser::AVC_VIDEO;
- }
- sp<AnotherPacketSource> impl =
- (AnotherPacketSource *)mParser->getSource(type).get();
+ if (!haveVideo) {
+ sp<AnotherPacketSource> impl =
+ (AnotherPacketSource *)mParser->getSource(
+ ATSParser::AVC_VIDEO).get();
- if (impl != NULL) {
- if (type == ATSParser::MPEG2ADTS_AUDIO) {
- haveAudio = true;
- } else {
+ if (impl != NULL) {
haveVideo = true;
+ mSourceImpls.push(impl);
}
- mSourceImpls.push(impl);
+ }
+
+ if (!haveAudio) {
+ sp<AnotherPacketSource> impl =
+ (AnotherPacketSource *)mParser->getSource(
+ ATSParser::MPEG2ADTS_AUDIO).get();
+
+ if (impl != NULL) {
+ haveAudio = true;
+ mSourceImpls.push(impl);
+ }
+ }
+
+ if (++numPacketsParsed > 1500) {
+ break;
}
}
@@ -156,8 +168,6 @@
status_t MPEG2TSExtractor::feedMore() {
Mutex::Autolock autoLock(mLock);
- static const size_t kTSPacketSize = 188;
-
uint8_t packet[kTSPacketSize];
ssize_t n = mDataSource->readAt(mOffset, packet, kTSPacketSize);
@@ -176,23 +186,18 @@
bool SniffMPEG2TS(
const sp<DataSource> &source, String8 *mimeType, float *confidence,
sp<AMessage> *) {
-#if 0
- char header;
- if (source->readAt(0, &header, 1) != 1 || header != 0x47) {
- return false;
+ for (int i = 0; i < 5; ++i) {
+ char header;
+ if (source->readAt(kTSPacketSize * i, &header, 1) != 1
+ || header != 0x47) {
+ return false;
+ }
}
- *confidence = 0.05f;
+ *confidence = 0.1f;
mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
return true;
-#else
- // For now we're going to never identify this type of stream, since we'd
- // just base our decision on a single byte...
- // Instead you can instantiate an MPEG2TSExtractor by explicitly stating
- // its proper mime type in the call to MediaExtractor::Create(...).
- return false;
-#endif
}
} // namespace android
diff --git a/media/mtp/MtpCursor.cpp b/media/mtp/MtpCursor.cpp
index 865a294..35d90dc 100644
--- a/media/mtp/MtpCursor.cpp
+++ b/media/mtp/MtpCursor.cpp
@@ -399,8 +399,7 @@
}
-bool MtpCursor::putLong(CursorWindow* window, int value, int row, int column) {
-
+bool MtpCursor::putLong(CursorWindow* window, int64_t value, int row, int column) {
if (!window->putLong(row, column, value)) {
window->freeLastRow();
LOGE("Failed allocating space for a long in column %d", column);
diff --git a/media/mtp/MtpCursor.h b/media/mtp/MtpCursor.h
index 9e9833f..2e03c29 100644
--- a/media/mtp/MtpCursor.h
+++ b/media/mtp/MtpCursor.h
@@ -67,7 +67,7 @@
MtpObjectHandle objectID, int row);
bool prepareRow(CursorWindow* window);
- bool putLong(CursorWindow* window, int value, int row, int column);
+ bool putLong(CursorWindow* window, int64_t value, int row, int column);
bool putString(CursorWindow* window, const char* text, int row, int column);
bool putThumbnail(CursorWindow* window, MtpObjectHandle objectID,
MtpObjectFormat format, int row, int column);
diff --git a/native/android/Android.mk b/native/android/Android.mk
index cc35a3a..44ec83f 100644
--- a/native/android/Android.mk
+++ b/native/android/Android.mk
@@ -12,6 +12,7 @@
looper.cpp \
native_activity.cpp \
native_window.cpp \
+ obb.cpp \
sensor.cpp \
storage_manager.cpp
diff --git a/native/android/obb.cpp b/native/android/obb.cpp
new file mode 100644
index 0000000..e0cb1a6
--- /dev/null
+++ b/native/android/obb.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "NObb"
+
+#include <android/obb.h>
+
+#include <utils/Log.h>
+#include <utils/ObbFile.h>
+
+using namespace android;
+
+struct AObbInfo : public ObbFile {};
+
+AObbInfo* AObbScanner_getObbInfo(const char* filename) {
+ AObbInfo* obbFile = new AObbInfo();
+ if (obbFile == NULL || !obbFile->readFrom(filename)) {
+ delete obbFile;
+ return NULL;
+ }
+ obbFile->incStrong((void*)AObbScanner_getObbInfo);
+ return static_cast<AObbInfo*>(obbFile);
+}
+
+void AObbInfo_delete(AObbInfo* obbInfo) {
+ if (obbInfo != NULL) {
+ obbInfo->decStrong((void*)AObbScanner_getObbInfo);
+ }
+}
+
+const char* AObbInfo_getPackageName(AObbInfo* obbInfo) {
+ return obbInfo->getPackageName();
+}
+
+int32_t AObbInfo_getVersion(AObbInfo* obbInfo) {
+ return obbInfo->getVersion();
+}
+
+int32_t AObbInfo_getFlags(AObbInfo* obbInfo) {
+ return obbInfo->getFlags();
+}
diff --git a/native/android/storage_manager.cpp b/native/android/storage_manager.cpp
index 6dbe746..2f20641 100644
--- a/native/android/storage_manager.cpp
+++ b/native/android/storage_manager.cpp
@@ -38,20 +38,20 @@
mStorageManager(mgr)
{}
- virtual void onObbResult(const android::String16& filename, const android::String16& state) {
- LOGD("Got obb result (%s, %s)\n", String8(filename).string(), String8(state).string());
- }
+ virtual void onObbResult(const android::String16& filename, const android::String16& state);
};
struct AStorageManager : public RefBase {
protected:
- void* mObbCallback;
+ AStorageManager_obbCallbackFunc mObbCallback;
+ void* mObbCallbackData;
sp<ObbActionListener> mObbActionListener;
sp<IMountService> mMountService;
public:
- AStorageManager() :
- mObbCallback(NULL)
+ AStorageManager()
+ : mObbCallback(NULL)
+ , mObbCallbackData(NULL)
{
}
@@ -73,8 +73,15 @@
return true;
}
- void setObbCallback(void* cb) {
+ void setObbCallback(AStorageManager_obbCallbackFunc cb, void* data) {
mObbCallback = cb;
+ mObbCallbackData = data;
+ }
+
+ void fireCallback(const char* filename, const char* state) {
+ if (mObbCallback != NULL) {
+ mObbCallback(filename, state, mObbCallbackData);
+ }
}
void mountObb(const char* filename, const char* key) {
@@ -85,7 +92,7 @@
void unmountObb(const char* filename, const bool force) {
String16 filename16(filename);
- mMountService->unmountObb(filename16, force);
+ mMountService->unmountObb(filename16, force, mObbActionListener);
}
int isObbMounted(const char* filename) {
@@ -104,6 +111,10 @@
}
};
+void ObbActionListener::onObbResult(const android::String16& filename, const android::String16& state) {
+ mStorageManager->fireCallback(String8(filename).string(), String8(state).string());
+}
+
AStorageManager* AStorageManager_new() {
sp<AStorageManager> mgr = new AStorageManager();
@@ -120,8 +131,8 @@
}
}
-void AStorageManager_setObbCallback(AStorageManager* mgr, void* cb) {
- mgr->setObbCallback(cb);
+void AStorageManager_setObbCallback(AStorageManager* mgr, AStorageManager_obbCallbackFunc cb, void* data) {
+ mgr->setObbCallback(cb, data);
}
void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key) {
diff --git a/native/include/android/obb.h b/native/include/android/obb.h
new file mode 100644
index 0000000..65e9b2a
--- /dev/null
+++ b/native/include/android/obb.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef ANDROID_OBB_H
+#define ANDROID_OBB_H
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct AObbInfo;
+typedef struct AObbInfo AObbInfo;
+
+enum {
+ AOBBINFO_OVERLAY = 0x0001,
+};
+
+/**
+ * Scan an OBB and get information about it.
+ */
+AObbInfo* AObbScanner_getObbInfo(const char* filename);
+
+/**
+ * Destroy the AObbInfo object. You must call this when finished with the object.
+ */
+void AObbInfo_delete(AObbInfo* obbInfo);
+
+/**
+ * Get the package name for the OBB.
+ */
+const char* AObbInfo_getPackageName(AObbInfo* obbInfo);
+
+/**
+ * Get the version of an OBB file.
+ */
+int32_t AObbInfo_getVersion(AObbInfo* obbInfo);
+
+/**
+ * Get the flags of an OBB file.
+ */
+int32_t AObbInfo_getFlags(AObbInfo* obbInfo);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // ANDROID_OBB_H
diff --git a/native/include/android/storage_manager.h b/native/include/android/storage_manager.h
index bbed8a4..6f925c1 100644
--- a/native/include/android/storage_manager.h
+++ b/native/include/android/storage_manager.h
@@ -37,17 +37,22 @@
void AStorageManager_delete(AStorageManager* mgr);
/**
- * Callback to call when requested OBB is complete.
+ * Callback function for asynchronous calls made on OBB files.
*/
-void AStorageManager_setObbCallback(AStorageManager* mgr, void* cb);
+typedef void (*AStorageManager_obbCallbackFunc)(const char* filename, const char* state, void* data);
/**
- * Attempts to mount an OBB file.
+ * Callback to call when requested asynchronous OBB operation is complete.
+ */
+void AStorageManager_setObbCallback(AStorageManager* mgr, AStorageManager_obbCallbackFunc cb, void* data);
+
+/**
+ * Attempts to mount an OBB file. This is an asynchronous operation.
*/
void AStorageManager_mountObb(AStorageManager* mgr, const char* filename, const char* key);
/**
- * Attempts to unmount an OBB file.
+ * Attempts to unmount an OBB file. This is an asynchronous operation.
*/
void AStorageManager_unmountObb(AStorageManager* mgr, const char* filename, const int force);
@@ -66,4 +71,4 @@
};
#endif
-#endif // ANDROID_PACKAGE_MANAGER_H
+#endif // ANDROID_STORAGE_MANAGER_H
diff --git a/opengl/tests/testFramerate/Android.mk b/opengl/tests/testFramerate/Android.mk
new file mode 100644
index 0000000..500abf3
--- /dev/null
+++ b/opengl/tests/testFramerate/Android.mk
@@ -0,0 +1,19 @@
+#########################################################################
+# Test framerate and look for hiccups
+#########################################################################
+
+TOP_LOCAL_PATH:= $(call my-dir)
+
+# Build activity
+
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := TestFramerate
+
+include $(BUILD_PACKAGE)
diff --git a/opengl/tests/testFramerate/AndroidManifest.xml b/opengl/tests/testFramerate/AndroidManifest.xml
new file mode 100644
index 0000000..e04342c
--- /dev/null
+++ b/opengl/tests/testFramerate/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.testframerate">
+ <uses-sdk android:targetSdkVersion="8" android:minSdkVersion="8" />
+
+ <application
+ android:label="@string/testFramerate_activity">
+ <activity android:name="TestFramerateActivity"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+ android:launchMode="singleTask"
+ android:configChanges="orientation|keyboardHidden">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/opengl/tests/testFramerate/res/values/strings.xml b/opengl/tests/testFramerate/res/values/strings.xml
new file mode 100644
index 0000000..e6b3088
--- /dev/null
+++ b/opengl/tests/testFramerate/res/values/strings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- This file contains resource definitions for displayed strings, allowing
+ them to be changed based on the locale and options. -->
+
+<resources>
+ <!-- Simple strings. -->
+ <string name="testFramerate_activity">TestFramerate</string>
+
+</resources>
+
diff --git a/opengl/tests/testFramerate/src/com/android/testframerate/TestFramerateActivity.java b/opengl/tests/testFramerate/src/com/android/testframerate/TestFramerateActivity.java
new file mode 100644
index 0000000..cbe279b
--- /dev/null
+++ b/opengl/tests/testFramerate/src/com/android/testframerate/TestFramerateActivity.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.testframerate;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.WindowManager;
+
+import java.io.File;
+
+
+public class TestFramerateActivity extends Activity {
+
+ TestFramerateView mView;
+
+ @Override protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ mView = new TestFramerateView(getApplication());
+ setContentView(mView);
+ mView.setFocusableInTouchMode(true);
+ }
+
+ @Override protected void onPause() {
+ super.onPause();
+ mView.onPause();
+ }
+
+ @Override protected void onResume() {
+ super.onResume();
+ mView.onResume();
+ }
+}
diff --git a/opengl/tests/testFramerate/src/com/android/testframerate/TestFramerateView.java b/opengl/tests/testFramerate/src/com/android/testframerate/TestFramerateView.java
new file mode 100644
index 0000000..f3fb5de
--- /dev/null
+++ b/opengl/tests/testFramerate/src/com/android/testframerate/TestFramerateView.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.testframerate;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.SystemProperties;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.opengl.GLES20;
+
+class TestFramerateView extends GLSurfaceView {
+ private static String TAG = "TestFramerateView";
+
+ public TestFramerateView(Context context) {
+ super(context);
+ setEGLContextClientVersion(2);
+ setRenderer(new Renderer());
+ }
+
+ private long mLastTime_us = 0;
+ private long mNumShortFramesElapsed = 0;
+ private void registerTime(long now_us) {
+ long longFrameTime_ms = Integer.parseInt(SystemProperties.get("debug.longframe_ms", "16"));
+ long elapsedTime_us = now_us - mLastTime_us;
+ float fps = 1000000.f / elapsedTime_us;
+ if (mLastTime_us > 0 && elapsedTime_us > longFrameTime_ms*1000) {
+ Log.v(TAG, "Long frame: " + elapsedTime_us/1000.f + " ms (" + fps + " fps)");
+ if (mNumShortFramesElapsed > 0) {
+ Log.v(TAG, " Short frames since last long frame: " + mNumShortFramesElapsed);
+ mNumShortFramesElapsed = 0;
+ }
+ } else {
+ ++mNumShortFramesElapsed;
+ }
+
+ mLastTime_us = now_us;
+ }
+
+ private class Renderer implements GLSurfaceView.Renderer {
+ public Renderer() {
+ }
+
+
+ public void onDrawFrame(GL10 gl) {
+ long now_us = System.nanoTime() / 1000;
+ registerTime(now_us);
+
+ float red = (now_us % 1000000) / 1000000.f;
+ float green = (now_us % 2000000) / 2000000.f;
+ float blue = (now_us % 3000000) / 3000000.f;
+ GLES20.glClearColor(red, green, blue, 1.0f);
+ GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
+ }
+
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ GLES20.glViewport(0, 0, width, height);
+ }
+
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ }
+
+ }
+}
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index f08bd3c..eb86277 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -156,7 +156,12 @@
}
public ObbInfo getObbInfo(String filename) {
- return ObbScanner.getObbInfo(filename);
+ try {
+ return ObbScanner.getObbInfo(filename);
+ } catch (IOException e) {
+ Log.d(TAG, "Couldn't get OBB info", e);
+ return null;
+ }
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CarrierLabel.java b/packages/SystemUI/src/com/android/systemui/statusbar/CarrierLabel.java
index d89d093..31b78b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CarrierLabel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CarrierLabel.java
@@ -99,7 +99,7 @@
}
if (showSpn && spn != null) {
if (something) {
- str.append(' ');
+ str.append('\n');
}
str.append(spn);
something = true;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 8a732ed..97b8086 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -5332,6 +5332,15 @@
}
}
+ // Release effect engine here so that it is done immediately. Otherwise it will be released
+ // by the destructor when the last strong reference on the this object is released which can
+ // happen after next process is called on this effect.
+ if (size == 0 && mEffectInterface != NULL) {
+ // release effect engine
+ EffectRelease(mEffectInterface);
+ mEffectInterface = NULL;
+ }
+
return size;
}
@@ -6145,21 +6154,36 @@
// Must be called with EffectChain::mLock locked
void AudioFlinger::EffectChain::process_l()
{
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread == 0) {
+ LOGW("process_l(): cannot promote mixer thread");
+ return;
+ }
+ PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+ bool isGlobalSession = (mSessionId == AudioSystem::SESSION_OUTPUT_MIX) ||
+ (mSessionId == AudioSystem::SESSION_OUTPUT_STAGE);
+ bool tracksOnSession = false;
+ if (!isGlobalSession) {
+ tracksOnSession =
+ playbackThread->hasAudioSession(mSessionId) & PlaybackThread::TRACK_SESSION;
+ }
+
size_t size = mEffects.size();
- for (size_t i = 0; i < size; i++) {
- mEffects[i]->process();
+ // do not process effect if no track is present in same audio session
+ if (isGlobalSession || tracksOnSession) {
+ for (size_t i = 0; i < size; i++) {
+ mEffects[i]->process();
+ }
}
for (size_t i = 0; i < size; i++) {
mEffects[i]->updateState();
}
// if no track is active, input buffer must be cleared here as the mixer process
// will not do it
- if (mSessionId > 0 && activeTracks() == 0) {
- sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- size_t numSamples = thread->frameCount() * thread->channelCount();
- memset(mInBuffer, 0, numSamples * sizeof(int16_t));
- }
+ if (tracksOnSession &&
+ activeTracks() == 0) {
+ size_t numSamples = playbackThread->frameCount() * playbackThread->channelCount();
+ memset(mInBuffer, 0, numSamples * sizeof(int16_t));
}
}
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index f943a10..808c679 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -320,6 +320,7 @@
// Callback is disabled by default
mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
mOrientation = 0;
+ mOrientationChanged = false;
mPlayShutterSound = true;
cameraService->setCameraBusy(cameraId);
cameraService->loadSound();
@@ -491,6 +492,7 @@
// Force the destruction of any previous overlay
sp<Overlay> dummy;
mHardware->setOverlay(dummy);
+ mOverlayRef = 0;
}
}
if (surface != 0) {
@@ -518,11 +520,12 @@
CameraParameters params(mHardware->getParameters());
params.getPreviewSize(&w, &h);
- if (w != mOverlayW || h != mOverlayH) {
+ if (w != mOverlayW || h != mOverlayH || mOrientationChanged) {
// Force the destruction of any previous overlay
sp<Overlay> dummy;
mHardware->setOverlay(dummy);
mOverlayRef = 0;
+ mOrientationChanged = false;
}
status_t result = NO_ERROR;
@@ -802,6 +805,7 @@
status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
LOG1("sendCommand (pid %d)", getCallingPid());
+ int orientation;
Mutex::Autolock lock(mLock);
status_t result = checkPidAndHardware();
if (result != NO_ERROR) return result;
@@ -813,20 +817,24 @@
}
switch (arg1) {
case 0:
- mOrientation = ISurface::BufferHeap::ROT_0;
+ orientation = ISurface::BufferHeap::ROT_0;
break;
case 90:
- mOrientation = ISurface::BufferHeap::ROT_90;
+ orientation = ISurface::BufferHeap::ROT_90;
break;
case 180:
- mOrientation = ISurface::BufferHeap::ROT_180;
+ orientation = ISurface::BufferHeap::ROT_180;
break;
case 270:
- mOrientation = ISurface::BufferHeap::ROT_270;
+ orientation = ISurface::BufferHeap::ROT_270;
break;
default:
return BAD_VALUE;
}
+ if (mOrientation != orientation) {
+ mOrientation = orientation;
+ if (mOverlayRef != 0) mOrientationChanged = true;
+ }
return OK;
} else if (cmd == CAMERA_CMD_ENABLE_SHUTTER_SOUND) {
switch (arg1) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 2b5c511..d57364a 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -173,7 +173,9 @@
int mOverlayW;
int mOverlayH;
int mPreviewCallbackFlag;
- int mOrientation;
+ int mOrientation; // Current display orientation
+ // True if display orientation has been changed. This is only used in overlay.
+ int mOrientationChanged;
bool mPlayShutterSound;
// Ensures atomicity among the public methods
diff --git a/services/java/com/android/server/EntropyService.java b/services/java/com/android/server/EntropyService.java
index 81ae26f..0f1fc78 100644
--- a/services/java/com/android/server/EntropyService.java
+++ b/services/java/com/android/server/EntropyService.java
@@ -139,6 +139,7 @@
out.println(SystemProperties.get("ro.bootloader"));
out.println(SystemProperties.get("ro.hardware"));
out.println(SystemProperties.get("ro.revision"));
+ out.println(new Object().hashCode());
out.println(System.currentTimeMillis());
out.println(System.nanoTime());
} catch (IOException e) {
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index 32f5e73..e6c6953 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -46,6 +46,7 @@
import android.os.storage.StorageResultCode;
import android.util.Slog;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -150,7 +151,7 @@
* Mounted OBB tracking information. Used to track the current state of all
* OBBs.
*/
- final private Map<IObbActionListener, ObbState> mObbMounts = new HashMap<IObbActionListener, ObbState>();
+ final private Map<IObbActionListener, List<ObbState>> mObbMounts = new HashMap<IObbActionListener, List<ObbState>>();
final private Map<String, ObbState> mObbPathToStateMap = new HashMap<String, ObbState>();
class ObbState implements IBinder.DeathRecipient {
@@ -162,13 +163,13 @@
}
// OBB source filename
- String filename;
+ final String filename;
// Token of remote Binder caller
- IObbActionListener token;
+ final IObbActionListener token;
// Binder.callingUid()
- public int callerUid;
+ final public int callerUid;
// Whether this is mounted currently.
boolean mounted;
@@ -227,9 +228,9 @@
private static final int MAX_UNMOUNT_RETRIES = 4;
class UnmountCallBack {
- String path;
+ final String path;
+ final boolean force;
int retries;
- boolean force;
UnmountCallBack(String path, boolean force) {
retries = 0;
@@ -244,7 +245,7 @@
}
class UmsEnableCallBack extends UnmountCallBack {
- String method;
+ final String method;
UmsEnableCallBack(String path, String method, boolean force) {
super(path, force);
@@ -1526,10 +1527,6 @@
throw new IllegalArgumentException("OBB file is already mounted");
}
- if (mObbMounts.containsKey(token)) {
- throw new IllegalArgumentException("You may only have one OBB mounted at a time");
- }
-
final int callerUid = Binder.getCallingUid();
obbState = new ObbState(filename, token, callerUid);
addObbState(obbState);
@@ -1567,14 +1564,25 @@
private void addObbState(ObbState obbState) {
synchronized (mObbMounts) {
- mObbMounts.put(obbState.token, obbState);
+ List<ObbState> obbStates = mObbMounts.get(obbState.token);
+ if (obbStates == null) {
+ obbStates = new ArrayList<ObbState>();
+ mObbMounts.put(obbState.token, obbStates);
+ }
+ obbStates.add(obbState);
mObbPathToStateMap.put(obbState.filename, obbState);
}
}
private void removeObbState(ObbState obbState) {
synchronized (mObbMounts) {
- mObbMounts.remove(obbState.token);
+ final List<ObbState> obbStates = mObbMounts.get(obbState.token);
+ if (obbStates != null) {
+ obbStates.remove(obbState);
+ }
+ if (obbStates == null || obbStates.isEmpty()) {
+ mObbMounts.remove(obbState.token);
+ }
mObbPathToStateMap.remove(obbState.filename);
}
}
@@ -1750,7 +1758,7 @@
}
}
- abstract void handleExecute() throws RemoteException;
+ abstract void handleExecute() throws RemoteException, IOException;
abstract void handleError();
}
@@ -1762,8 +1770,12 @@
mKey = key;
}
- public void handleExecute() throws RemoteException {
+ public void handleExecute() throws RemoteException, IOException {
ObbInfo obbInfo = mContainerService.getObbInfo(mObbState.filename);
+ if (obbInfo == null) {
+ throw new IOException("Couldn't read OBB file");
+ }
+
if (!isUidOwnerOfPackageOrSystem(obbInfo.packageName, mObbState.callerUid)) {
throw new IllegalArgumentException("Caller package does not match OBB file");
}
@@ -1786,15 +1798,17 @@
if (rc == StorageResultCode.OperationSucceeded) {
try {
- mObbState.token.onObbResult(mObbState.filename, "mounted");
+ mObbState.token.onObbResult(mObbState.filename, Environment.MEDIA_MOUNTED);
} catch (RemoteException e) {
Slog.w(TAG, "MountServiceListener went away while calling onObbStateChanged");
}
} else {
- Slog.e(TAG, "Couldn't mount OBB file");
+ Slog.e(TAG, "Couldn't mount OBB file: " + rc);
// We didn't succeed, so remove this from the mount-set.
removeObbState(mObbState);
+
+ mObbState.token.onObbResult(mObbState.filename, Environment.MEDIA_BAD_REMOVAL);
}
}
@@ -1802,7 +1816,7 @@
removeObbState(mObbState);
try {
- mObbState.token.onObbResult(mObbState.filename, "error");
+ mObbState.token.onObbResult(mObbState.filename, Environment.MEDIA_BAD_REMOVAL);
} catch (RemoteException e) {
Slog.e(TAG, "Couldn't send back OBB mount error for " + mObbState.filename);
}
@@ -1831,8 +1845,11 @@
mForceUnmount = force;
}
- public void handleExecute() throws RemoteException {
+ public void handleExecute() throws RemoteException, IOException {
ObbInfo obbInfo = mContainerService.getObbInfo(mObbState.filename);
+ if (obbInfo == null) {
+ throw new IOException("Couldn't read OBB file");
+ }
if (!isCallerOwnerOfPackageOrSystem(obbInfo.packageName)) {
throw new IllegalArgumentException("Caller package does not match OBB file");
@@ -1856,13 +1873,13 @@
removeObbState(mObbState);
try {
- mObbState.token.onObbResult(mObbState.filename, "unmounted");
+ mObbState.token.onObbResult(mObbState.filename, Environment.MEDIA_UNMOUNTED);
} catch (RemoteException e) {
Slog.w(TAG, "MountServiceListener went away while calling onObbStateChanged");
}
} else {
try {
- mObbState.token.onObbResult(mObbState.filename, "error");
+ mObbState.token.onObbResult(mObbState.filename, Environment.MEDIA_BAD_REMOVAL);
} catch (RemoteException e) {
Slog.w(TAG, "MountServiceListener went away while calling onObbStateChanged");
}
@@ -1873,7 +1890,7 @@
removeObbState(mObbState);
try {
- mObbState.token.onObbResult(mObbState.filename, "error");
+ mObbState.token.onObbResult(mObbState.filename, Environment.MEDIA_BAD_REMOVAL);
} catch (RemoteException e) {
Slog.e(TAG, "Couldn't send back OBB unmount error for " + mObbState.filename);
}
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 9401ff8..4532c1c 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -2105,6 +2105,7 @@
}
public void userActivity(long time, boolean noChangeLights) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
userActivity(time, -1, noChangeLights, OTHER_EVENT, false);
}
@@ -2128,7 +2129,6 @@
private void userActivity(long time, long timeoutOverride, boolean noChangeLights,
int eventType, boolean force) {
- //mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)
&& (eventType == CHEEK_EVENT || eventType == TOUCH_EVENT)) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 5ca386b..7db6710 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -17,7 +17,6 @@
package com.android.server;
import com.android.server.am.ActivityManagerService;
-import com.android.server.sip.SipService;
import com.android.internal.os.BinderInternal;
import com.android.internal.os.SamplingProfilerIntegration;
@@ -435,16 +434,6 @@
}
try {
- SipService sipService = SipService.create(context);
- if (sipService != null) {
- Slog.i(TAG, "Sip Service");
- ServiceManager.addService("sip", sipService);
- }
- } catch (Throwable e) {
- Slog.e(TAG, "Failure starting SIP Service", e);
- }
-
- try {
Slog.i(TAG, "NetworkTimeUpdateService");
networkTimeUpdater = new NetworkTimeUpdateService(context);
} catch (Throwable e) {
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 7b2a570..760aa43 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -1191,7 +1191,7 @@
}
private boolean acquireWifiLockLocked(WifiLock wifiLock) {
- Slog.d(TAG, "acquireWifiLockLocked: " + wifiLock);
+ if (DBG) Slog.d(TAG, "acquireWifiLockLocked: " + wifiLock);
mLocks.addLock(wifiLock);
@@ -1258,7 +1258,7 @@
WifiLock wifiLock = mLocks.removeLock(lock);
- Slog.d(TAG, "releaseWifiLockLocked: " + wifiLock);
+ if (DBG) Slog.d(TAG, "releaseWifiLockLocked: " + wifiLock);
hadLock = (wifiLock != null);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 9685fb7..5c4b919 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -4225,29 +4225,75 @@
}
private final boolean checkHoldingPermissionsLocked(IPackageManager pm,
- ProviderInfo pi, int uid, int modeFlags) {
+ ProviderInfo pi, Uri uri, int uid, int modeFlags) {
+ boolean readPerm = (modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0;
+ boolean writePerm = (modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) == 0;
+ if (DEBUG_URI_PERMISSION) Slog.v(TAG,
+ "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
try {
- if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
- if ((pi.readPermission != null) &&
+ // Is the component private from the target uid?
+ final boolean prv = !pi.exported && pi.applicationInfo.uid != uid;
+
+ // Acceptable if the there is no read permission needed from the
+ // target or the target is holding the read permission.
+ if (!readPerm) {
+ if ((!prv && pi.readPermission == null) ||
(pm.checkUidPermission(pi.readPermission, uid)
- != PackageManager.PERMISSION_GRANTED)) {
- return false;
+ == PackageManager.PERMISSION_GRANTED)) {
+ readPerm = true;
}
}
- if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
- if ((pi.writePermission != null) &&
+
+ // Acceptable if the there is no write permission needed from the
+ // target or the target is holding the read permission.
+ if (!writePerm) {
+ if (!prv && (pi.writePermission == null) ||
(pm.checkUidPermission(pi.writePermission, uid)
- != PackageManager.PERMISSION_GRANTED)) {
- return false;
+ == PackageManager.PERMISSION_GRANTED)) {
+ writePerm = true;
}
}
- if (!pi.exported && pi.applicationInfo.uid != uid) {
- return false;
+
+ // Acceptable if there is a path permission matching the URI that
+ // the target holds the permission on.
+ PathPermission[] pps = pi.pathPermissions;
+ if (pps != null && (!readPerm || !writePerm)) {
+ final String path = uri.getPath();
+ int i = pps.length;
+ while (i > 0 && (!readPerm || !writePerm)) {
+ i--;
+ PathPermission pp = pps[i];
+ if (!readPerm) {
+ final String pprperm = pp.getReadPermission();
+ if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking read perm for "
+ + pprperm + " for " + pp.getPath()
+ + ": match=" + pp.match(path)
+ + " check=" + pm.checkUidPermission(pprperm, uid));
+ if (pprperm != null && pp.match(path) &&
+ (pm.checkUidPermission(pprperm, uid)
+ == PackageManager.PERMISSION_GRANTED)) {
+ readPerm = true;
+ }
+ }
+ if (!writePerm) {
+ final String ppwperm = pp.getWritePermission();
+ if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Checking write perm "
+ + ppwperm + " for " + pp.getPath()
+ + ": match=" + pp.match(path)
+ + " check=" + pm.checkUidPermission(ppwperm, uid));
+ if (ppwperm != null && pp.match(path) &&
+ (pm.checkUidPermission(ppwperm, uid)
+ == PackageManager.PERMISSION_GRANTED)) {
+ writePerm = true;
+ }
+ }
+ }
}
- return true;
} catch (RemoteException e) {
return false;
}
+
+ return readPerm && writePerm;
}
private final boolean checkUriPermissionLocked(Uri uri, int uid,
@@ -4340,7 +4386,7 @@
}
// First... does the target actually need this permission?
- if (checkHoldingPermissionsLocked(pm, pi, targetUid, modeFlags)) {
+ if (checkHoldingPermissionsLocked(pm, pi, uri, targetUid, modeFlags)) {
// No need to grant the target this permission.
if (DEBUG_URI_PERMISSION) Slog.v(TAG,
"Target " + targetPkg + " already has full permission to " + uri);
@@ -4374,7 +4420,7 @@
// Third... does the caller itself have permission to access
// this uri?
- if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
+ if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
throw new SecurityException("Uid " + callingUid
+ " does not have permission to uri " + uri);
@@ -4542,7 +4588,7 @@
}
// Does the caller have this permission on the URI?
- if (!checkHoldingPermissionsLocked(pm, pi, callingUid, modeFlags)) {
+ if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
// Right now, if you are not the original owner of the permission,
// you are not allowed to revoke it.
//if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
@@ -5599,6 +5645,38 @@
}
}
+ /**
+ * Allows app to retrieve the MIME type of a URI without having permission
+ * to access its content provider.
+ *
+ * CTS tests for this functionality can be run with "runtest cts-appsecurity".
+ *
+ * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
+ * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
+ */
+ public String getProviderMimeType(Uri uri) {
+ final String name = uri.getAuthority();
+ final long ident = Binder.clearCallingIdentity();
+ ContentProviderHolder holder = null;
+
+ try {
+ holder = getContentProviderExternal(name);
+ if (holder != null) {
+ return holder.provider.getType(uri);
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Content provider dead retrieving " + uri, e);
+ return null;
+ } finally {
+ if (holder != null) {
+ removeContentProviderExternal(name);
+ }
+ Binder.restoreCallingIdentity(ident);
+ }
+
+ return null;
+ }
+
// =========================================================
// GLOBAL MANAGEMENT
// =========================================================
diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java
index 0cb6943..e3347cb 100644
--- a/services/java/com/android/server/am/UriPermission.java
+++ b/services/java/com/android/server/am/UriPermission.java
@@ -27,8 +27,8 @@
*
* CTS tests for this functionality can be run with "runtest cts-appsecurity".
*
- * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert
- * /src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
+ * Test cases are at cts/tests/appsecurity-tests/test-apps/UsePermissionDiffCert/
+ * src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
*/
class UriPermission {
final int uid;
diff --git a/telephony/java/com/android/internal/telephony/Connection.java b/telephony/java/com/android/internal/telephony/Connection.java
index 3b6de6f..0d983b5 100644
--- a/telephony/java/com/android/internal/telephony/Connection.java
+++ b/telephony/java/com/android/internal/telephony/Connection.java
@@ -42,6 +42,7 @@
NUMBER_UNREACHABLE, /* cannot reach the peer */
INVALID_CREDENTIALS, /* invalid credentials */
OUT_OF_NETWORK, /* calling from out of network is not allowed */
+ SERVER_ERROR, /* server error */
TIMED_OUT, /* client timed out */
LOST_SIGNAL,
LIMIT_EXCEEDED, /* eg GSM ACM limit exceeded */
diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
index c0ad7e9..e0eac74 100755
--- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java
+++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java
@@ -444,18 +444,23 @@
@Override
public void hangup() throws CallStateException {
synchronized (SipPhone.class) {
- Log.v(LOG_TAG, "hang up call: " + getState() + ": " + this
- + " on phone " + getPhone());
- CallStateException excp = null;
- for (Connection c : connections) {
- try {
- c.hangup();
- } catch (CallStateException e) {
- excp = e;
+ if (state.isAlive()) {
+ Log.d(LOG_TAG, "hang up call: " + getState() + ": " + this
+ + " on phone " + getPhone());
+ CallStateException excp = null;
+ for (Connection c : connections) {
+ try {
+ c.hangup();
+ } catch (CallStateException e) {
+ excp = e;
+ }
}
+ if (excp != null) throw excp;
+ setState(State.DISCONNECTING);
+ } else {
+ Log.d(LOG_TAG, "hang up dead call: " + getState() + ": "
+ + this + " on phone " + getPhone());
}
- if (excp != null) throw excp;
- setState(State.DISCONNECTING);
}
}
@@ -640,14 +645,14 @@
@Override
public void onCallEstablished(SipAudioCall call) {
- call.startAudio();
onChanged(call);
+ if (mState == Call.State.ACTIVE) call.startAudio();
}
@Override
public void onCallHeld(SipAudioCall call) {
- call.startAudio();
onChanged(call);
+ if (mState == Call.State.HOLDING) call.startAudio();
}
@Override
@@ -787,11 +792,13 @@
public void hangup() throws CallStateException {
synchronized (SipPhone.class) {
Log.v(LOG_TAG, "hangup conn: " + mPeer.getUriString() + ": "
- + ": on phone " + getPhone().getPhoneName());
+ + mState + ": on phone " + getPhone().getPhoneName());
try {
- if (mSipAudioCall != null) mSipAudioCall.endCall();
- setState(Call.State.DISCONNECTING);
- setDisconnectCause(DisconnectCause.LOCAL);
+ if (mState.isAlive()) {
+ if (mSipAudioCall != null) mSipAudioCall.endCall();
+ setState(Call.State.DISCONNECTING);
+ setDisconnectCause(DisconnectCause.LOCAL);
+ }
} catch (SipException e) {
throw new CallStateException("hangup(): " + e);
}
@@ -875,8 +882,10 @@
case SipErrorCode.CROSS_DOMAIN_AUTHENTICATION:
onError(Connection.DisconnectCause.OUT_OF_NETWORK);
break;
- case SipErrorCode.SOCKET_ERROR:
case SipErrorCode.SERVER_ERROR:
+ onError(Connection.DisconnectCause.SERVER_ERROR);
+ break;
+ case SipErrorCode.SOCKET_ERROR:
case SipErrorCode.CLIENT_ERROR:
default:
Log.w(LOG_TAG, "error: " + SipErrorCode.toString(errorCode)
diff --git a/test-runner/src/android/test/mock/MockContentResolver.java b/test-runner/src/android/test/mock/MockContentResolver.java
index ab511f8..26eb8e4 100644
--- a/test-runner/src/android/test/mock/MockContentResolver.java
+++ b/test-runner/src/android/test/mock/MockContentResolver.java
@@ -75,6 +75,12 @@
/** @hide */
@Override
protected IContentProvider acquireProvider(Context context, String name) {
+ return acquireExistingProvider(context, name);
+ }
+
+ /** @hide */
+ @Override
+ protected IContentProvider acquireExistingProvider(Context context, String name) {
/*
* Gets the content provider from the local map
diff --git a/tests/DumpRenderTree2/assets/run_layout_tests.py b/tests/DumpRenderTree2/assets/run_layout_tests.py
index fd76e4a9..303a054 100755
--- a/tests/DumpRenderTree2/assets/run_layout_tests.py
+++ b/tests/DumpRenderTree2/assets/run_layout_tests.py
@@ -12,6 +12,7 @@
import logging
import optparse
import os
+import re
import sys
import subprocess
import tempfile
@@ -44,27 +45,33 @@
os.system(cmd);
# Run the tests in path
- cmd = "adb shell am instrument "
+ adb_cmd = "adb"
+ if options.serial:
+ adb_cmd += " -s " + options.serial
+ cmd = adb_cmd + " shell am instrument "
cmd += "-e class com.android.dumprendertree2.scriptsupport.Starter#startLayoutTests "
cmd += "-e path \"" + path + "\" "
- cmd +="-w com.android.dumprendertree2/com.android.dumprendertree2.scriptsupport.ScriptTestRunner"
+ cmd += "-w com.android.dumprendertree2/com.android.dumprendertree2.scriptsupport.ScriptTestRunner"
logging.info("Running the tests...")
- subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
+ (stdoutdata, stderrdata) = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
+ if re.search("^INSTRUMENTATION_STATUS_CODE: -1", stdoutdata, re.MULTILINE) != None:
+ logging.info("Failed to run the tests. Is DumpRenderTree2 installed on the device?")
+ return
logging.info("Downloading the summaries...")
# Download the txt summary to tmp folder
summary_txt_tmp_path = os.path.join(tmpdir, SUMMARY_TXT)
cmd = "rm -f " + summary_txt_tmp_path + ";"
- cmd += "adb pull " + RESULTS_ABSOLUTE_PATH + SUMMARY_TXT + " " + summary_txt_tmp_path
- subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
+ cmd += adb_cmd + " pull " + RESULTS_ABSOLUTE_PATH + SUMMARY_TXT + " " + summary_txt_tmp_path
+ subprocess.Popen(cmd, shell=True).wait()
# Download the html summary to tmp folder
details_html_tmp_path = os.path.join(tmpdir, DETAILS_HTML)
cmd = "rm -f " + details_html_tmp_path + ";"
- cmd += "adb pull " + RESULTS_ABSOLUTE_PATH + DETAILS_HTML + " " + details_html_tmp_path
- subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
+ cmd += adb_cmd + " pull " + RESULTS_ABSOLUTE_PATH + DETAILS_HTML + " " + details_html_tmp_path
+ subprocess.Popen(cmd, shell=True).wait()
# Print summary to console
logging.info("All done.\n")
@@ -82,5 +89,6 @@
help="Show the results the host's default web browser, default=true")
option_parser.add_option("", "--tests-root-directory",
help="The directory from which to take the tests, default is external/webkit/LayoutTests in this checkout of the Android tree")
+ option_parser.add_option("-s", "--serial", default=None, help="Specify the serial number of device to run test on")
options, args = option_parser.parse_args();
main(options, args);
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/FsUtils.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/FsUtils.java
index 4438811..4f9a737 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/FsUtils.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/FsUtils.java
@@ -223,10 +223,9 @@
try {
return getHttpClient().execute(httpRequest, handler);
} catch (IOException e) {
- Log.e(LOG_TAG, "url=" + url, e);
+ Log.e(LOG_TAG, "getLayoutTestsDirContents(): HTTP GET failed for URL " + url);
+ return null;
}
-
- return new LinkedList<String>();
}
public static void closeInputStream(InputStream inputStream) {
@@ -248,4 +247,4 @@
Log.e(LOG_TAG, "Couldn't close stream!", e);
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
index 089af0d..97d7cca 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
@@ -382,7 +382,9 @@
WebSettings webViewSettings = webView.getSettings();
webViewSettings.setAppCacheEnabled(true);
webViewSettings.setAppCachePath(getApplicationContext().getCacheDir().getPath());
- webViewSettings.setAppCacheMaxSize(Long.MAX_VALUE);
+ // Use of larger values causes unexplained AppCache database corruption.
+ // TODO: Investigate what's really going on here.
+ webViewSettings.setAppCacheMaxSize(100 * 1024 * 1024);
webViewSettings.setJavaScriptEnabled(true);
webViewSettings.setJavaScriptCanOpenWindowsAutomatically(true);
webViewSettings.setSupportMultipleWindows(true);
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/TestsListPreloaderThread.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/TestsListPreloaderThread.java
index e0f14500..0e7d47a 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/TestsListPreloaderThread.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/TestsListPreloaderThread.java
@@ -21,6 +21,7 @@
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
+import java.util.List;
/**
* A Thread that is responsible for generating a lists of tests to run.
@@ -35,7 +36,7 @@
private FileFilter mFileFilter;
/**
- * A relative path to the folder with the tests we want to run or particular test.
+ * A relative path to the directory with the tests we want to run or particular test.
* Used up to and including preloadTests().
*/
private String mRelativePath;
@@ -67,40 +68,44 @@
}
/**
- * Loads all the tests from the given folders and all the subfolders
+ * Loads all the tests from the given directories and all the subdirectories
* into mTestsList.
*
* @param dirRelativePath
*/
- private void loadTestsFromUrl(String dirRelativePath) {
- LinkedList<String> foldersList = new LinkedList<String>();
- foldersList.add(dirRelativePath);
+ private void loadTestsFromUrl(String rootRelativePath) {
+ LinkedList<String> directoriesList = new LinkedList<String>();
+ directoriesList.add(rootRelativePath);
String relativePath;
String itemName;
- while (!foldersList.isEmpty()) {
- relativePath = foldersList.removeFirst();
+ while (!directoriesList.isEmpty()) {
+ relativePath = directoriesList.removeFirst();
- for (String folderRelativePath : FsUtils.getLayoutTestsDirContents(relativePath,
- false, true)) {
- itemName = new File(folderRelativePath).getName();
- if (FileFilter.isTestDir(itemName)) {
- foldersList.add(folderRelativePath);
+ List<String> dirRelativePaths = FsUtils.getLayoutTestsDirContents(relativePath, false, true);
+ if (dirRelativePaths != null) {
+ for (String dirRelativePath : dirRelativePaths) {
+ itemName = new File(dirRelativePath).getName();
+ if (FileFilter.isTestDir(itemName)) {
+ directoriesList.add(dirRelativePath);
+ }
}
}
- for (String testRelativePath : FsUtils.getLayoutTestsDirContents(relativePath,
- false, false)) {
- itemName = new File(testRelativePath).getName();
- if (FileFilter.isTestFile(itemName)) {
- /** We chose to skip all the tests that are expected to crash. */
- if (!mFileFilter.isCrash(testRelativePath)) {
- mTestsList.add(testRelativePath);
- } else {
- /**
- * TODO: Summarizer is now in service - figure out how to send the info.
- * Previously: mSummarizer.addSkippedTest(relativePath);
- */
+ List<String> testRelativePaths = FsUtils.getLayoutTestsDirContents(relativePath, false, false);
+ if (testRelativePaths != null) {
+ for (String testRelativePath : testRelativePaths) {
+ itemName = new File(testRelativePath).getName();
+ if (FileFilter.isTestFile(itemName)) {
+ /** We choose to skip all the tests that are expected to crash. */
+ if (!mFileFilter.isCrash(testRelativePath)) {
+ mTestsList.add(testRelativePath);
+ } else {
+ /**
+ * TODO: Summarizer is now in service - figure out how to send the info.
+ * Previously: mSummarizer.addSkippedTest(relativePath);
+ */
+ }
}
}
}
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/AdbUtils.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/AdbUtils.java
index 086ff59..224509d 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/AdbUtils.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/AdbUtils.java
@@ -40,15 +40,10 @@
* remote machine. This can be achieved by calling configureSocket()
*
* @return a socket that can be configured to link to remote machine
+ * @throws IOException
*/
- public static Socket createSocket() {
- Socket socket = null;
- try {
- socket = new Socket(ADB_HOST, ADB_PORT);
- } catch (IOException e) {
- Log.e(LOG_TAG, "Creation failed.", e);
- }
- return socket;
+ public static Socket createSocket() throws IOException{
+ return new Socket(ADB_HOST, ADB_PORT);
}
/**
@@ -72,9 +67,9 @@
outputStream.write(cmd.getBytes());
int read = inputStream.read(buf);
if (read != ADB_RESPONSE_SIZE || !ADB_OK.equals(new String(buf))) {
- Log.w(LOG_TAG, "adb cmd faild.");
+ Log.w(LOG_TAG, "adb cmd failed.");
return false;
}
return true;
}
-}
\ No newline at end of file
+}
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/ConnectionHandler.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/ConnectionHandler.java
index 4f01dae..f19cd41 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/ConnectionHandler.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/ConnectionHandler.java
@@ -93,7 +93,8 @@
private OnFinishedCallback mOnFinishedCallback;
- public ConnectionHandler(String remoteMachineIp, int port, Socket fromSocket, Socket toSocket) {
+ public ConnectionHandler(String remoteMachineIp, int port, Socket fromSocket, Socket toSocket)
+ throws IOException {
mRemoteMachineIpAddress = remoteMachineIp;
mPort = port;
@@ -105,14 +106,12 @@
mToSocketInputStream = mToSocket.getInputStream();
mFromSocketOutputStream = mFromSocket.getOutputStream();
mToSocketOutputStream = mToSocket.getOutputStream();
- if (!AdbUtils.configureConnection(mToSocketInputStream, mToSocketOutputStream,
- mRemoteMachineIpAddress, mPort)) {
- throw new IOException("Configuring socket failed!");
- }
+ AdbUtils.configureConnection(mToSocketInputStream, mToSocketOutputStream,
+ mRemoteMachineIpAddress, mPort);
} catch (IOException e) {
Log.e(LOG_TAG, "Unable to start ConnectionHandler", e);
closeStreams();
- return;
+ throw e;
}
mFromToPipe = new SocketPipeThread(mFromSocketInputStream, mToSocketOutputStream);
@@ -170,4 +169,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/Forwarder.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/Forwarder.java
index b361a89..ce22fa0 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/Forwarder.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/forwarder/Forwarder.java
@@ -61,7 +61,6 @@
public void run() {
while (true) {
Socket localSocket;
- Socket remoteSocket;
try {
localSocket = mServerSocket.accept();
} catch (IOException e) {
@@ -70,24 +69,28 @@
break;
}
- remoteSocket = AdbUtils.createSocket();
-
- if (remoteSocket == null) {
+ Socket remoteSocket = null;
+ final ConnectionHandler connectionHandler;
+ try {
+ remoteSocket = AdbUtils.createSocket();
+ connectionHandler = new ConnectionHandler(
+ mRemoteMachineIpAddress, mPort, localSocket, remoteSocket);
+ } catch (IOException exception) {
try {
localSocket.close();
} catch (IOException e) {
Log.e(LOG_TAG, "mPort=" + mPort, e);
}
-
- Log.e(LOG_TAG, "run(): mPort= " + mPort + " Failed to start forwarding from " +
- localSocket);
+ if (remoteSocket != null) {
+ try {
+ remoteSocket.close();
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "mPort=" + mPort, e);
+ }
+ }
continue;
}
- final ConnectionHandler connectionHandler =
- new ConnectionHandler(mRemoteMachineIpAddress, mPort, localSocket,
- remoteSocket);
-
/**
* We have to close the sockets after the ConnectionHandler finishes, so we
* don't get "Too may open files" exception. We also remove the ConnectionHandler
@@ -126,4 +129,4 @@
Log.e(LOG_TAG, "mPort=" + mPort, e);
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/ui/DirListActivity.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/ui/DirListActivity.java
index 35de88a..5de69a7 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/ui/DirListActivity.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/ui/DirListActivity.java
@@ -45,6 +45,7 @@
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
+import android.widget.Toast;
import java.io.File;
import java.util.ArrayList;
@@ -69,6 +70,9 @@
private static final int MSG_LOADED_ITEMS = 0;
private static final int MSG_SHOW_PROGRESS_DIALOG = 1;
+ private static final CharSequence NO_RESPONSE_MESSAGE =
+ "No response from host when getting directory contents. Is the host server running?";
+
/** Initialized lazily before first sProgressDialog.show() */
private static ProgressDialog sProgressDialog;
@@ -349,13 +353,18 @@
@Override
public void handleMessage(Message msg) {
if (msg.what == MSG_LOADED_ITEMS) {
- setListAdapter(new DirListAdapter(DirListActivity.this,
- (ListItem[])msg.obj));
- delayedDialogHandler.removeMessages(MSG_SHOW_PROGRESS_DIALOG);
setTitle(shortenTitle(mCurrentDirPath));
+ delayedDialogHandler.removeMessages(MSG_SHOW_PROGRESS_DIALOG);
if (sProgressDialog != null) {
sProgressDialog.dismiss();
}
+ if (msg.obj == null) {
+ Toast.makeText(DirListActivity.this, NO_RESPONSE_MESSAGE,
+ Toast.LENGTH_LONG).show();
+ } else {
+ setListAdapter(new DirListAdapter(DirListActivity.this,
+ (ListItem[])msg.obj));
+ }
}
}
}).start();
@@ -389,15 +398,21 @@
List<ListItem> subDirs = new ArrayList<ListItem>();
List<ListItem> subFiles = new ArrayList<ListItem>();
- for (String dirRelativePath : FsUtils.getLayoutTestsDirContents(dirPath, false,
- true)) {
+ List<String> dirRelativePaths = FsUtils.getLayoutTestsDirContents(dirPath, false, true);
+ if (dirRelativePaths == null) {
+ return null;
+ }
+ for (String dirRelativePath : dirRelativePaths) {
if (FileFilter.isTestDir(new File(dirRelativePath).getName())) {
subDirs.add(new ListItem(dirRelativePath, true));
}
}
- for (String testRelativePath : FsUtils.getLayoutTestsDirContents(dirPath, false,
- false)) {
+ List<String> testRelativePaths = FsUtils.getLayoutTestsDirContents(dirPath, false, false);
+ if (testRelativePaths == null) {
+ return null;
+ }
+ for (String testRelativePath : testRelativePaths) {
if (FileFilter.isTestFile(new File(testRelativePath).getName())) {
subFiles.add(new ListItem(testRelativePath, false));
}
diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk
index 135a633..b27ce0e 100644
--- a/tools/layoutlib/Android.mk
+++ b/tools/layoutlib/Android.mk
@@ -25,15 +25,11 @@
# We need to process the framework classes.jar file, but we can't
# depend directly on it (private vars won't be inherited correctly).
# So, we depend on framework's BUILT file.
-built_framework_dep := \
- $(call intermediates-dir-for,JAVA_LIBRARIES,framework)/javalib.jar
-built_framework_classes := \
- $(call intermediates-dir-for,JAVA_LIBRARIES,framework)/classes.jar
+built_framework_dep := $(call java-lib-deps,framework)
+built_framework_classes := $(call java-lib-files,framework)
-built_core_dep := \
- $(call intermediates-dir-for,JAVA_LIBRARIES,core)/javalib.jar
-built_core_classes := \
- $(call intermediates-dir-for,JAVA_LIBRARIES,core)/classes.jar
+built_core_dep := $(call java-lib-deps,core)
+built_core_classes := $(call java-lib-files,core)
built_layoutlib_create_jar := $(call intermediates-dir-for, \
JAVA_LIBRARIES,layoutlib_create,HOST)/javalib.jar
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentResolver.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentResolver.java
index cfab90a..d89dba9 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentResolver.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContentResolver.java
@@ -43,6 +43,12 @@
}
@Override
+ public IContentProvider acquireExistingProvider(Context c, String name) {
+ // ignore
+ return null;
+ }
+
+ @Override
public boolean releaseProvider(IContentProvider icp) {
// ignore
return false;
diff --git a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestClassReplacement.java b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestClassReplacement.java
index e0dc55f..adb693d 100644
--- a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestClassReplacement.java
+++ b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/TestClassReplacement.java
@@ -17,6 +17,8 @@
package com.android.layoutlib.bridge;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
import junit.framework.TestCase;
@@ -26,7 +28,8 @@
// TODO: we want to test all the classes. For now only Paint passes the tests.
// final String[] classes = CreateInfo.RENAMED_CLASSES;
final String[] classes = new String[] {
- "android.graphics.Paint", "android.graphics._Original_Paint"
+ "android.graphics.Paint", "android.graphics._Original_Paint",
+ "android.graphics.Canvas", "android.graphics._Original_Canvas",
};
final int count = classes.length;
for (int i = 0 ; i < count ; i += 2) {
@@ -52,12 +55,21 @@
Method[] oldClassMethods = oldClass.getDeclaredMethods();
for (Method oldMethod : oldClassMethods) {
- // we ignore anything that starts with native
+ // we ignore anything that starts with native. This is because the class we are looking
+ // at has already been modified to remove the native modifiers.
if (oldMethod.getName().startsWith("native")) {
continue;
}
+
+ // or static and private
+ int privateStatic = Modifier.STATIC | Modifier.PRIVATE;
+ if ((oldMethod.getModifiers() & privateStatic) == privateStatic) {
+ continue;
+ }
+
boolean found = false;
for (Method newMethod : newClassMethods) {
+
if (compareMethods(newClass, newMethod, oldClass, oldMethod)) {
found = true;
break;
@@ -65,7 +77,31 @@
}
if (found == false) {
- fail(String.format("Unable to find %1$s", oldMethod.toGenericString()));
+ // compute a full class name that's long but not too long.
+ StringBuilder sb = new StringBuilder(oldMethod.getName() + "(");
+ Type[] params = oldMethod.getGenericParameterTypes();
+ for (int j = 0; j < params.length; j++) {
+ if (params[j] instanceof Class) {
+ Class theClass = (Class)params[j];
+ sb.append(theClass.getName());
+ int dimensions = 0;
+ while (theClass.isArray()) {
+ dimensions++;
+ theClass = theClass.getComponentType();
+ }
+ for (int i = 0; i < dimensions; i++) {
+ sb.append("[]");
+ }
+
+ } else {
+ sb.append(params[j].toString());
+ }
+ if (j < (params.length - 1))
+ sb.append(",");
+ }
+ sb.append(")");
+
+ fail(String.format("Missing %1$s.%2$s", newClass.getName(), sb.toString()));
}
}
diff --git a/services/java/com/android/server/sip/SipHelper.java b/voip/java/com/android/server/sip/SipHelper.java
similarity index 100%
rename from services/java/com/android/server/sip/SipHelper.java
rename to voip/java/com/android/server/sip/SipHelper.java
diff --git a/services/java/com/android/server/sip/SipService.java b/voip/java/com/android/server/sip/SipService.java
similarity index 98%
rename from services/java/com/android/server/sip/SipService.java
rename to voip/java/com/android/server/sip/SipService.java
index 3f43e1c..0ff5586 100644
--- a/services/java/com/android/server/sip/SipService.java
+++ b/voip/java/com/android/server/sip/SipService.java
@@ -40,6 +40,7 @@
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
@@ -90,12 +91,14 @@
private ConnectivityReceiver mConnectivityReceiver;
/**
- * Creates a {@code SipService} instance. Returns null if SIP API is not
- * supported.
+ * Starts the SIP service. Do nothing if the SIP API is not supported on the
+ * device.
*/
- public static SipService create(Context context) {
- return (SipManager.isApiSupported(context) ? new SipService(context)
- : null);
+ public static void start(Context context) {
+ if (SipManager.isApiSupported(context)) {
+ ServiceManager.addService("sip", new SipService(context));
+ Log.i(TAG, "SIP service started");
+ }
}
private SipService(Context context) {
diff --git a/services/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
similarity index 98%
rename from services/java/com/android/server/sip/SipSessionGroup.java
rename to voip/java/com/android/server/sip/SipSessionGroup.java
index 91677a2..4321d7b 100644
--- a/services/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -28,7 +28,6 @@
import android.net.sip.SipErrorCode;
import android.net.sip.SipProfile;
import android.net.sip.SipSession;
-import android.net.sip.SipSessionAdapter;
import android.text.TextUtils;
import android.util.Log;
@@ -82,7 +81,6 @@
private static final boolean DEBUG = true;
private static final boolean DEBUG_PING = DEBUG && false;
private static final String ANONYMOUS = "anonymous";
- private static final String SERVER_ERROR_PREFIX = "Response: ";
private static final int EXPIRY_TIME = 3600; // in seconds
private static final int CANCEL_CALL_TIMER = 3; // in seconds
@@ -960,6 +958,11 @@
int statusCode = response.getStatusCode();
switch (statusCode) {
case Response.RINGING:
+ case Response.CALL_IS_BEING_FORWARDED:
+ case Response.QUEUED:
+ case Response.SESSION_PROGRESS:
+ // feedback any provisional responses (except TRYING) as
+ // ring back for better UX
if (mState == SipSession.State.OUTGOING_CALL) {
mState = SipSession.State.OUTGOING_CALL_RING_BACK;
mProxy.onRingingBack(this);
@@ -1099,8 +1102,8 @@
}
private String createErrorMessage(Response response) {
- return String.format(SERVER_ERROR_PREFIX + "%s (%d)",
- response.getReasonPhrase(), response.getStatusCode());
+ return String.format("%s (%d)", response.getReasonPhrase(),
+ response.getStatusCode());
}
private void establishCall() {
@@ -1204,8 +1207,6 @@
return SipErrorCode.INVALID_REMOTE_URI;
} else if (exception instanceof IOException) {
return SipErrorCode.SOCKET_ERROR;
- } else if (message.startsWith(SERVER_ERROR_PREFIX)) {
- return SipErrorCode.SERVER_ERROR;
} else {
return SipErrorCode.CLIENT_ERROR;
}
diff --git a/services/java/com/android/server/sip/SipSessionListenerProxy.java b/voip/java/com/android/server/sip/SipSessionListenerProxy.java
similarity index 100%
rename from services/java/com/android/server/sip/SipSessionListenerProxy.java
rename to voip/java/com/android/server/sip/SipSessionListenerProxy.java
diff --git a/voip/jni/rtp/AudioGroup.cpp b/voip/jni/rtp/AudioGroup.cpp
index 81d4dfc..72c882b 100644
--- a/voip/jni/rtp/AudioGroup.cpp
+++ b/voip/jni/rtp/AudioGroup.cpp
@@ -461,18 +461,15 @@
EC_ENABLED = 3,
LAST_MODE = 3,
};
- int mMode;
+
AudioStream *mChain;
int mEventQueue;
volatile int mDtmfEvent;
+ int mMode;
+ int mSampleRate;
int mSampleCount;
int mDeviceSocket;
- AudioTrack mTrack;
- AudioRecord mRecord;
-
- bool networkLoop();
- bool deviceLoop();
class NetworkThread : public Thread
{
@@ -490,10 +487,7 @@
private:
AudioGroup *mGroup;
- bool threadLoop()
- {
- return mGroup->networkLoop();
- }
+ bool threadLoop();
};
sp<NetworkThread> mNetworkThread;
@@ -504,9 +498,6 @@
bool start()
{
- char c;
- while (recv(mGroup->mDeviceSocket, &c, 1, MSG_DONTWAIT) == 1);
-
if (run("Device", ANDROID_PRIORITY_AUDIO) != NO_ERROR) {
LOGE("cannot start device thread");
return false;
@@ -516,10 +507,7 @@
private:
AudioGroup *mGroup;
- bool threadLoop()
- {
- return mGroup->deviceLoop();
- }
+ bool threadLoop();
};
sp<DeviceThread> mDeviceThread;
};
@@ -539,8 +527,6 @@
{
mNetworkThread->requestExitAndWait();
mDeviceThread->requestExitAndWait();
- mTrack.stop();
- mRecord.stop();
close(mEventQueue);
close(mDeviceSocket);
while (mChain) {
@@ -559,40 +545,9 @@
return false;
}
+ mSampleRate = sampleRate;
mSampleCount = sampleCount;
- // Find out the frame count for AudioTrack and AudioRecord.
- int output = 0;
- int input = 0;
- if (AudioTrack::getMinFrameCount(&output, AudioSystem::VOICE_CALL,
- sampleRate) != NO_ERROR || output <= 0 ||
- AudioRecord::getMinFrameCount(&input, sampleRate,
- AudioSystem::PCM_16_BIT, 1) != NO_ERROR || input <= 0) {
- LOGE("cannot compute frame count");
- return false;
- }
- LOGD("reported frame count: output %d, input %d", output, input);
-
- if (output < sampleCount * 2) {
- output = sampleCount * 2;
- }
- if (input < sampleCount * 2) {
- input = sampleCount * 2;
- }
- LOGD("adjusted frame count: output %d, input %d", output, input);
-
- // Initialize AudioTrack and AudioRecord.
- if (mTrack.set(AudioSystem::VOICE_CALL, sampleRate, AudioSystem::PCM_16_BIT,
- AudioSystem::CHANNEL_OUT_MONO, output) != NO_ERROR ||
- mRecord.set(AUDIO_SOURCE_MIC, sampleRate, AudioSystem::PCM_16_BIT,
- AudioSystem::CHANNEL_IN_MONO, input) != NO_ERROR) {
- LOGE("cannot initialize audio device");
- return false;
- }
- LOGD("latency: output %d, input %d", mTrack.latency(), mRecord.latency());
-
- // TODO: initialize echo canceler here.
-
// Create device socket.
int pair[2];
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair)) {
@@ -610,13 +565,11 @@
return false;
}
- // Give device socket a reasonable timeout and buffer size.
+ // Give device socket a reasonable timeout.
timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 1000 * sampleCount / sampleRate * 500;
- if (setsockopt(pair[0], SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) ||
- setsockopt(pair[0], SOL_SOCKET, SO_RCVBUF, &output, sizeof(output)) ||
- setsockopt(pair[1], SOL_SOCKET, SO_SNDBUF, &output, sizeof(output))) {
+ if (setsockopt(pair[0], SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))) {
LOGE("setsockopt: %s", strerror(errno));
return false;
}
@@ -644,29 +597,10 @@
return true;
}
+ mDeviceThread->requestExitAndWait();
LOGD("group[%d] switches from mode %d to %d", mDeviceSocket, mMode, mode);
mMode = mode;
-
- mDeviceThread->requestExitAndWait();
- if (mode == ON_HOLD) {
- mTrack.stop();
- mRecord.stop();
- return true;
- }
-
- mTrack.start();
- if (mode == MUTED) {
- mRecord.stop();
- } else {
- mRecord.start();
- }
-
- if (!mDeviceThread->start()) {
- mTrack.stop();
- mRecord.stop();
- return false;
- }
- return true;
+ return (mode == ON_HOLD) || mDeviceThread->start();
}
bool AudioGroup::sendDtmf(int event)
@@ -741,15 +675,16 @@
return true;
}
-bool AudioGroup::networkLoop()
+bool AudioGroup::NetworkThread::threadLoop()
{
+ AudioStream *chain = mGroup->mChain;
int tick = elapsedRealtime();
int deadline = tick + 10;
int count = 0;
- for (AudioStream *stream = mChain; stream; stream = stream->mNext) {
+ for (AudioStream *stream = chain; stream; stream = stream->mNext) {
if (!stream->mTick || tick - stream->mTick >= 0) {
- stream->encode(tick, mChain);
+ stream->encode(tick, chain);
}
if (deadline - stream->mTick > 0) {
deadline = stream->mTick;
@@ -757,12 +692,12 @@
++count;
}
- if (mDtmfEvent != -1) {
- int event = mDtmfEvent;
- for (AudioStream *stream = mChain; stream; stream = stream->mNext) {
+ int event = mGroup->mDtmfEvent;
+ if (event != -1) {
+ for (AudioStream *stream = chain; stream; stream = stream->mNext) {
stream->sendDtmf(event);
}
- mDtmfEvent = -1;
+ mGroup->mDtmfEvent = -1;
}
deadline -= tick;
@@ -771,7 +706,7 @@
}
epoll_event events[count];
- count = epoll_wait(mEventQueue, events, count, deadline);
+ count = epoll_wait(mGroup->mEventQueue, events, count, deadline);
if (count == -1) {
LOGE("epoll_wait: %s", strerror(errno));
return false;
@@ -783,70 +718,125 @@
return true;
}
-bool AudioGroup::deviceLoop()
+bool AudioGroup::DeviceThread::threadLoop()
{
- int16_t output[mSampleCount];
+ int mode = mGroup->mMode;
+ int sampleRate = mGroup->mSampleRate;
+ int sampleCount = mGroup->mSampleCount;
+ int deviceSocket = mGroup->mDeviceSocket;
- if (recv(mDeviceSocket, output, sizeof(output), 0) <= 0) {
- memset(output, 0, sizeof(output));
- }
-
- int16_t input[mSampleCount];
- int toWrite = mSampleCount;
- int toRead = (mMode == MUTED) ? 0 : mSampleCount;
- int chances = 100;
-
- while (--chances > 0 && (toWrite > 0 || toRead > 0)) {
- if (toWrite > 0) {
- AudioTrack::Buffer buffer;
- buffer.frameCount = toWrite;
-
- status_t status = mTrack.obtainBuffer(&buffer, 1);
- if (status == NO_ERROR) {
- memcpy(buffer.i8, &output[mSampleCount - toWrite], buffer.size);
- toWrite -= buffer.frameCount;
- mTrack.releaseBuffer(&buffer);
- } else if (status != TIMED_OUT && status != WOULD_BLOCK) {
- LOGE("cannot write to AudioTrack");
- return false;
- }
- }
-
- if (toRead > 0) {
- AudioRecord::Buffer buffer;
- buffer.frameCount = mRecord.frameCount();
-
- status_t status = mRecord.obtainBuffer(&buffer, 1);
- if (status == NO_ERROR) {
- int count = ((int)buffer.frameCount < toRead) ?
- buffer.frameCount : toRead;
- memcpy(&input[mSampleCount - toRead], buffer.i8, count * 2);
- toRead -= count;
- if (buffer.frameCount < mRecord.frameCount()) {
- buffer.frameCount = count;
- }
- mRecord.releaseBuffer(&buffer);
- } else if (status != TIMED_OUT && status != WOULD_BLOCK) {
- LOGE("cannot read from AudioRecord");
- return false;
- }
- }
- }
-
- if (!chances) {
- LOGE("device loop timeout");
+ // Find out the frame count for AudioTrack and AudioRecord.
+ int output = 0;
+ int input = 0;
+ if (AudioTrack::getMinFrameCount(&output, AudioSystem::VOICE_CALL,
+ sampleRate) != NO_ERROR || output <= 0 ||
+ AudioRecord::getMinFrameCount(&input, sampleRate,
+ AudioSystem::PCM_16_BIT, 1) != NO_ERROR || input <= 0) {
+ LOGE("cannot compute frame count");
return false;
}
+ LOGD("reported frame count: output %d, input %d", output, input);
- if (mMode != MUTED) {
- if (mMode == NORMAL) {
- send(mDeviceSocket, input, sizeof(input), MSG_DONTWAIT);
- } else {
- // TODO: Echo canceller runs here.
- send(mDeviceSocket, input, sizeof(input), MSG_DONTWAIT);
+ if (output < sampleCount * 2) {
+ output = sampleCount * 2;
+ }
+ if (input < sampleCount * 2) {
+ input = sampleCount * 2;
+ }
+ LOGD("adjusted frame count: output %d, input %d", output, input);
+
+ // Initialize AudioTrack and AudioRecord.
+ AudioTrack track;
+ AudioRecord record;
+ if (track.set(AudioSystem::VOICE_CALL, sampleRate, AudioSystem::PCM_16_BIT,
+ AudioSystem::CHANNEL_OUT_MONO, output) != NO_ERROR ||
+ record.set(AUDIO_SOURCE_MIC, sampleRate, AudioSystem::PCM_16_BIT,
+ AudioSystem::CHANNEL_IN_MONO, input) != NO_ERROR) {
+ LOGE("cannot initialize audio device");
+ return false;
+ }
+ LOGD("latency: output %d, input %d", track.latency(), record.latency());
+
+ // TODO: initialize echo canceler here.
+
+ // Give device socket a reasonable buffer size.
+ setsockopt(deviceSocket, SOL_SOCKET, SO_RCVBUF, &output, sizeof(output));
+ setsockopt(deviceSocket, SOL_SOCKET, SO_SNDBUF, &output, sizeof(output));
+
+ // Drain device socket.
+ char c;
+ while (recv(deviceSocket, &c, 1, MSG_DONTWAIT) == 1);
+
+ // Start your engine!
+ track.start();
+ if (mode != MUTED) {
+ record.start();
+ }
+
+ while (!exitPending()) {
+ int16_t output[sampleCount];
+ if (recv(deviceSocket, output, sizeof(output), 0) <= 0) {
+ memset(output, 0, sizeof(output));
+ }
+
+ int16_t input[sampleCount];
+ int toWrite = sampleCount;
+ int toRead = (mode == MUTED) ? 0 : sampleCount;
+ int chances = 100;
+
+ while (--chances > 0 && (toWrite > 0 || toRead > 0)) {
+ if (toWrite > 0) {
+ AudioTrack::Buffer buffer;
+ buffer.frameCount = toWrite;
+
+ status_t status = track.obtainBuffer(&buffer, 1);
+ if (status == NO_ERROR) {
+ int offset = sampleCount - toWrite;
+ memcpy(buffer.i8, &output[offset], buffer.size);
+ toWrite -= buffer.frameCount;
+ track.releaseBuffer(&buffer);
+ } else if (status != TIMED_OUT && status != WOULD_BLOCK) {
+ LOGE("cannot write to AudioTrack");
+ break;
+ }
+ }
+
+ if (toRead > 0) {
+ AudioRecord::Buffer buffer;
+ buffer.frameCount = record.frameCount();
+
+ status_t status = record.obtainBuffer(&buffer, 1);
+ if (status == NO_ERROR) {
+ int count = ((int)buffer.frameCount < toRead) ?
+ buffer.frameCount : toRead;
+ memcpy(&input[sampleCount - toRead], buffer.i8, count * 2);
+ toRead -= count;
+ if (buffer.frameCount < record.frameCount()) {
+ buffer.frameCount = count;
+ }
+ record.releaseBuffer(&buffer);
+ } else if (status != TIMED_OUT && status != WOULD_BLOCK) {
+ LOGE("cannot read from AudioRecord");
+ break;
+ }
+ }
+ }
+
+ if (chances <= 0) {
+ LOGE("device loop timeout");
+ break;
+ }
+
+ if (mode != MUTED) {
+ if (mode == NORMAL) {
+ send(deviceSocket, input, sizeof(input), MSG_DONTWAIT);
+ } else {
+ // TODO: Echo canceller runs here.
+ send(deviceSocket, input, sizeof(input), MSG_DONTWAIT);
+ }
}
}
- return true;
+ return false;
}
//------------------------------------------------------------------------------