Merge "SIP: Feedback any provisional responses in addition to RING" into gingerbread
diff --git a/api/current.xml b/api/current.xml
index 876fe00..179c515 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -24488,6 +24488,623 @@
</parameter>
</method>
</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"
@@ -95347,623 +95964,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"
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/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 1bbf9ea..c01516f 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -67,7 +67,6 @@
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;
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 1f220d2..c6fef4f 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/content/Context.java b/core/java/android/content/Context.java
index 0100550..0dd2e4a 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1207,7 +1207,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
@@ -1256,7 +1256,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);
@@ -1539,7 +1539,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/res/res/drawable-hdpi/indicator_code_lock_point_area_green.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green.png
index 9fb43b8..c21b24e 100644
--- a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green.png
+++ b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_green.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red.png b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red.png
index e26a083..87007a3 100644
--- a/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red.png
+++ b/core/res/res/drawable-hdpi/indicator_code_lock_point_area_red.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_car_mode.png b/core/res/res/drawable-hdpi/stat_notify_car_mode.png
old mode 100755
new mode 100644
index 60c3778..e700d79
--- a/core/res/res/drawable-hdpi/stat_notify_car_mode.png
+++ b/core/res/res/drawable-hdpi/stat_notify_car_mode.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_email_generic.png b/core/res/res/drawable-hdpi/stat_notify_email_generic.png
index 87f0cd4..bc5fcab 100644
--- a/core/res/res/drawable-hdpi/stat_notify_email_generic.png
+++ b/core/res/res/drawable-hdpi/stat_notify_email_generic.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_error.png b/core/res/res/drawable-hdpi/stat_notify_error.png
old mode 100644
new mode 100755
index 37c8853..b3a18b3
--- a/core/res/res/drawable-hdpi/stat_notify_error.png
+++ b/core/res/res/drawable-hdpi/stat_notify_error.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_gmail.png b/core/res/res/drawable-hdpi/stat_notify_gmail.png
index 8a9140c..ea8beae 100644
--- a/core/res/res/drawable-hdpi/stat_notify_gmail.png
+++ b/core/res/res/drawable-hdpi/stat_notify_gmail.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_missed_call.png b/core/res/res/drawable-hdpi/stat_notify_missed_call.png
old mode 100755
new mode 100644
index d1173b4..3c19c93
--- a/core/res/res/drawable-hdpi/stat_notify_missed_call.png
+++ b/core/res/res/drawable-hdpi/stat_notify_missed_call.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_more.png b/core/res/res/drawable-hdpi/stat_notify_more.png
index 1c7f9db..f54b3d4 100755
--- a/core/res/res/drawable-hdpi/stat_notify_more.png
+++ b/core/res/res/drawable-hdpi/stat_notify_more.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_sdcard_usb.png b/core/res/res/drawable-hdpi/stat_notify_sdcard_usb.png
old mode 100644
new mode 100755
index a5e369e2..fb2b26a
--- a/core/res/res/drawable-hdpi/stat_notify_sdcard_usb.png
+++ b/core/res/res/drawable-hdpi/stat_notify_sdcard_usb.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_sync_error.png b/core/res/res/drawable-hdpi/stat_notify_sync_error.png
index 6e3b545..26b2446 100755
--- a/core/res/res/drawable-hdpi/stat_notify_sync_error.png
+++ b/core/res/res/drawable-hdpi/stat_notify_sync_error.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png
old mode 100755
new mode 100644
index e9405dd..0458124
--- a/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png
+++ b/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png
Binary files differ
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/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/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index e0321a5..3e17a7e 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -16,6 +16,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..47a385d 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;
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 8507afc..12022bd 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -639,7 +639,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
@@ -666,8 +666,6 @@
} else {
mAudioPlayer->resume();
}
-
- postCheckAudioStatusEvent_l();
}
if (mTimeSource == NULL && mAudioPlayer == NULL) {
@@ -1169,7 +1167,7 @@
return;
}
mAudioStatusEventPending = true;
- mQueue.postEventWithDelay(mCheckAudioStatusEvent, 100000ll);
+ mQueue.postEvent(mCheckAudioStatusEvent);
}
void AwesomePlayer::onCheckAudioStatus() {
@@ -1200,8 +1198,6 @@
mFlags |= FIRST_FRAME;
postStreamDoneEvent_l(finalStatus);
}
-
- postCheckAudioStatusEvent_l();
}
status_t AwesomePlayer::prepare() {
@@ -1662,5 +1658,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/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 1f3946c..600faca 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -92,6 +92,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/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/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 22cd8ff..34753e7 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -4218,29 +4218,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,
@@ -4333,7 +4379,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);
@@ -4367,7 +4413,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);
@@ -4535,7 +4581,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)) {