Merge change 21221 into eclair
* changes:
Modify svc power command so it pokes the wake lock when called. This will ensure screen is not asleep if stayon is requested.
diff --git a/Android.mk b/Android.mk
index a9caa20..2bc83b3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -88,8 +88,8 @@
core/java/android/backup/IBackupManager.aidl \
core/java/android/backup/IRestoreObserver.aidl \
core/java/android/backup/IRestoreSession.aidl \
+ core/java/android/bluetooth/IBluetooth.aidl \
core/java/android/bluetooth/IBluetoothA2dp.aidl \
- core/java/android/bluetooth/IBluetoothDevice.aidl \
core/java/android/bluetooth/IBluetoothHeadset.aidl \
core/java/android/bluetooth/IBluetoothPbap.aidl \
core/java/android/content/IContentService.aidl \
diff --git a/api/current.xml b/api/current.xml
index 8682b15..b704eb3 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -13463,6 +13463,23 @@
<parameter name="accountType" type="java.lang.String">
</parameter>
</method>
+<method name="getAccountRemovalAllowed"
+ return="android.os.Bundle"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="response" type="android.accounts.AccountAuthenticatorResponse">
+</parameter>
+<parameter name="account" type="android.accounts.Account">
+</parameter>
+<exception name="NetworkErrorException" type="android.accounts.NetworkErrorException">
+</exception>
+</method>
<method name="getAuthToken"
return="android.os.Bundle"
abstract="true"
@@ -13615,7 +13632,7 @@
visibility="public"
>
</field>
-<field name="mName"
+<field name="name"
type="java.lang.String"
transient="false"
volatile="false"
@@ -13625,7 +13642,7 @@
visibility="public"
>
</field>
-<field name="mType"
+<field name="type"
type="java.lang.String"
transient="false"
volatile="false"
@@ -13781,7 +13798,7 @@
visibility="public"
>
<method name="addAccount"
- return="android.accounts.Future2"
+ return="android.accounts.AccountManagerFuture<android.os.Bundle>"
abstract="false"
native="false"
synchronized="false"
@@ -13800,13 +13817,13 @@
</parameter>
<parameter name="activity" type="android.app.Activity">
</parameter>
-<parameter name="callback" type="android.accounts.Future2Callback">
+<parameter name="callback" type="android.accounts.AccountManagerCallback<android.os.Bundle>">
</parameter>
<parameter name="handler" type="android.os.Handler">
</parameter>
</method>
<method name="addAccountExplicitly"
- return="android.accounts.Future1<java.lang.Boolean>"
+ return="boolean"
abstract="false"
native="false"
synchronized="false"
@@ -13815,16 +13832,12 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="callback" type="android.accounts.Future1Callback<java.lang.Boolean>">
-</parameter>
<parameter name="account" type="android.accounts.Account">
</parameter>
<parameter name="password" type="java.lang.String">
</parameter>
<parameter name="extras" type="android.os.Bundle">
</parameter>
-<parameter name="handler" type="android.os.Handler">
-</parameter>
</method>
<method name="addOnAccountsUpdatedListener"
return="void"
@@ -13843,81 +13856,6 @@
<parameter name="updateImmediately" type="boolean">
</parameter>
</method>
-<method name="blockingAddAccountExplicitly"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="account" type="android.accounts.Account">
-</parameter>
-<parameter name="password" type="java.lang.String">
-</parameter>
-<parameter name="extras" type="android.os.Bundle">
-</parameter>
-</method>
-<method name="blockingClearPassword"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="account" type="android.accounts.Account">
-</parameter>
-</method>
-<method name="blockingGetAccounts"
- return="android.accounts.Account[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="blockingGetAccountsByType"
- return="android.accounts.Account[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="accountType" type="java.lang.String">
-</parameter>
-</method>
-<method name="blockingGetAccountsWithTypeAndFeatures"
- return="android.accounts.Account[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="type" type="java.lang.String">
-</parameter>
-<parameter name="features" type="java.lang.String[]">
-</parameter>
-<exception name="AuthenticatorException" type="android.accounts.AuthenticatorException">
-</exception>
-<exception name="IOException" type="java.io.IOException">
-</exception>
-<exception name="OperationCanceledException" type="android.accounts.OperationCanceledException">
-</exception>
-</method>
<method name="blockingGetAuthToken"
return="java.lang.String"
abstract="false"
@@ -13941,139 +13879,8 @@
<exception name="OperationCanceledException" type="android.accounts.OperationCanceledException">
</exception>
</method>
-<method name="blockingGetAuthenticatorTypes"
- return="android.accounts.AuthenticatorDescription[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="blockingGetPassword"
- return="java.lang.String"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="account" type="android.accounts.Account">
-</parameter>
-</method>
-<method name="blockingGetUserData"
- return="java.lang.String"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="account" type="android.accounts.Account">
-</parameter>
-<parameter name="key" type="java.lang.String">
-</parameter>
-</method>
-<method name="blockingInvalidateAuthToken"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="accountType" type="java.lang.String">
-</parameter>
-<parameter name="authToken" type="java.lang.String">
-</parameter>
-</method>
-<method name="blockingPeekAuthToken"
- return="java.lang.String"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="account" type="android.accounts.Account">
-</parameter>
-<parameter name="authTokenType" type="java.lang.String">
-</parameter>
-</method>
-<method name="blockingRemoveAccount"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="account" type="android.accounts.Account">
-</parameter>
-</method>
-<method name="blockingSetAuthToken"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="account" type="android.accounts.Account">
-</parameter>
-<parameter name="authTokenType" type="java.lang.String">
-</parameter>
-<parameter name="authToken" type="java.lang.String">
-</parameter>
-</method>
-<method name="blockingSetPassword"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="account" type="android.accounts.Account">
-</parameter>
-<parameter name="password" type="java.lang.String">
-</parameter>
-</method>
-<method name="blockingSetUserData"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="account" type="android.accounts.Account">
-</parameter>
-<parameter name="key" type="java.lang.String">
-</parameter>
-<parameter name="value" type="java.lang.String">
-</parameter>
-</method>
<method name="clearPassword"
- return="android.accounts.Future1<java.lang.Void>"
+ return="void"
abstract="false"
native="false"
synchronized="false"
@@ -14082,15 +13889,11 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="callback" type="android.accounts.Future1Callback<java.lang.Void>">
-</parameter>
<parameter name="account" type="android.accounts.Account">
</parameter>
-<parameter name="handler" type="android.os.Handler">
-</parameter>
</method>
<method name="confirmCredentials"
- return="android.accounts.Future2"
+ return="android.accounts.AccountManagerFuture<android.os.Bundle>"
abstract="false"
native="false"
synchronized="false"
@@ -14103,13 +13906,13 @@
</parameter>
<parameter name="activity" type="android.app.Activity">
</parameter>
-<parameter name="callback" type="android.accounts.Future2Callback">
+<parameter name="callback" type="android.accounts.AccountManagerCallback<android.os.Bundle>">
</parameter>
<parameter name="handler" type="android.os.Handler">
</parameter>
</method>
<method name="confirmPassword"
- return="android.accounts.Future1<java.lang.Boolean>"
+ return="android.accounts.AccountManagerFuture<java.lang.Boolean>"
abstract="false"
native="false"
synchronized="false"
@@ -14122,13 +13925,13 @@
</parameter>
<parameter name="password" type="java.lang.String">
</parameter>
-<parameter name="callback" type="android.accounts.Future1Callback<java.lang.Boolean>">
+<parameter name="callback" type="android.accounts.AccountManagerCallback<java.lang.Boolean>">
</parameter>
<parameter name="handler" type="android.os.Handler">
</parameter>
</method>
<method name="editProperties"
- return="android.accounts.Future2"
+ return="android.accounts.AccountManagerFuture<android.os.Bundle>"
abstract="false"
native="false"
synchronized="false"
@@ -14141,7 +13944,7 @@
</parameter>
<parameter name="activity" type="android.app.Activity">
</parameter>
-<parameter name="callback" type="android.accounts.Future2Callback">
+<parameter name="callback" type="android.accounts.AccountManagerCallback<android.os.Bundle>">
</parameter>
<parameter name="handler" type="android.os.Handler">
</parameter>
@@ -14160,7 +13963,7 @@
</parameter>
</method>
<method name="getAccounts"
- return="android.accounts.Future1<android.accounts.Account[]>"
+ return="android.accounts.Account[]"
abstract="false"
native="false"
synchronized="false"
@@ -14169,13 +13972,9 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="callback" type="android.accounts.Future1Callback<android.accounts.Account[]>">
-</parameter>
-<parameter name="handler" type="android.os.Handler">
-</parameter>
</method>
<method name="getAccountsByType"
- return="android.accounts.Future1<android.accounts.Account[]>"
+ return="android.accounts.Account[]"
abstract="false"
native="false"
synchronized="false"
@@ -14184,15 +13983,11 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="callback" type="android.accounts.Future1Callback<android.accounts.Account[]>">
-</parameter>
<parameter name="type" type="java.lang.String">
</parameter>
-<parameter name="handler" type="android.os.Handler">
-</parameter>
</method>
-<method name="getAccountsWithTypeAndFeatures"
- return="android.accounts.Future2"
+<method name="getAccountsByTypeAndFeatures"
+ return="android.accounts.AccountManagerFuture<android.accounts.Account[]>"
abstract="false"
native="false"
synchronized="false"
@@ -14205,13 +14000,13 @@
</parameter>
<parameter name="features" type="java.lang.String[]">
</parameter>
-<parameter name="callback" type="android.accounts.Future2Callback">
+<parameter name="callback" type="android.accounts.AccountManagerCallback<android.accounts.Account[]>">
</parameter>
<parameter name="handler" type="android.os.Handler">
</parameter>
</method>
<method name="getAuthToken"
- return="android.accounts.Future2"
+ return="android.accounts.AccountManagerFuture<android.os.Bundle>"
abstract="false"
native="false"
synchronized="false"
@@ -14228,13 +14023,13 @@
</parameter>
<parameter name="activity" type="android.app.Activity">
</parameter>
-<parameter name="callback" type="android.accounts.Future2Callback">
+<parameter name="callback" type="android.accounts.AccountManagerCallback<android.os.Bundle>">
</parameter>
<parameter name="handler" type="android.os.Handler">
</parameter>
</method>
<method name="getAuthToken"
- return="android.accounts.Future2"
+ return="android.accounts.AccountManagerFuture<android.os.Bundle>"
abstract="false"
native="false"
synchronized="false"
@@ -14249,7 +14044,7 @@
</parameter>
<parameter name="notifyAuthFailure" type="boolean">
</parameter>
-<parameter name="callback" type="android.accounts.Future2Callback">
+<parameter name="callback" type="android.accounts.AccountManagerCallback<android.os.Bundle>">
</parameter>
<parameter name="handler" type="android.os.Handler">
</parameter>
@@ -14276,13 +14071,13 @@
</parameter>
<parameter name="loginOptions" type="android.os.Bundle">
</parameter>
-<parameter name="callback" type="android.accounts.Future2Callback">
+<parameter name="callback" type="android.accounts.AccountManagerCallback<android.os.Bundle>">
</parameter>
<parameter name="handler" type="android.os.Handler">
</parameter>
</method>
<method name="getAuthenticatorTypes"
- return="android.accounts.Future1<android.accounts.AuthenticatorDescription[]>"
+ return="android.accounts.AuthenticatorDescription[]"
abstract="false"
native="false"
synchronized="false"
@@ -14291,13 +14086,9 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="callback" type="android.accounts.Future1Callback<android.accounts.AuthenticatorDescription[]>">
-</parameter>
-<parameter name="handler" type="android.os.Handler">
-</parameter>
</method>
<method name="getPassword"
- return="android.accounts.Future1<java.lang.String>"
+ return="java.lang.String"
abstract="false"
native="false"
synchronized="false"
@@ -14306,15 +14097,11 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="callback" type="android.accounts.Future1Callback<java.lang.String>">
-</parameter>
<parameter name="account" type="android.accounts.Account">
</parameter>
-<parameter name="handler" type="android.os.Handler">
-</parameter>
</method>
<method name="getUserData"
- return="android.accounts.Future1<java.lang.String>"
+ return="java.lang.String"
abstract="false"
native="false"
synchronized="false"
@@ -14323,17 +14110,13 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="callback" type="android.accounts.Future1Callback<java.lang.String>">
-</parameter>
<parameter name="account" type="android.accounts.Account">
</parameter>
<parameter name="key" type="java.lang.String">
</parameter>
-<parameter name="handler" type="android.os.Handler">
-</parameter>
</method>
<method name="invalidateAuthToken"
- return="android.accounts.Future1<java.lang.Void>"
+ return="void"
abstract="false"
native="false"
synchronized="false"
@@ -14342,17 +14125,13 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="callback" type="android.accounts.Future1Callback<java.lang.Void>">
-</parameter>
<parameter name="accountType" type="java.lang.String">
</parameter>
<parameter name="authToken" type="java.lang.String">
</parameter>
-<parameter name="handler" type="android.os.Handler">
-</parameter>
</method>
<method name="peekAuthToken"
- return="android.accounts.Future1<java.lang.String>"
+ return="java.lang.String"
abstract="false"
native="false"
synchronized="false"
@@ -14361,17 +14140,13 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="callback" type="android.accounts.Future1Callback<java.lang.String>">
-</parameter>
<parameter name="account" type="android.accounts.Account">
</parameter>
<parameter name="authTokenType" type="java.lang.String">
</parameter>
-<parameter name="handler" type="android.os.Handler">
-</parameter>
</method>
<method name="removeAccount"
- return="android.accounts.Future1<java.lang.Void>"
+ return="android.accounts.AccountManagerFuture<java.lang.Boolean>"
abstract="false"
native="false"
synchronized="false"
@@ -14380,10 +14155,10 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="callback" type="android.accounts.Future1Callback<java.lang.Void>">
-</parameter>
<parameter name="account" type="android.accounts.Account">
</parameter>
+<parameter name="callback" type="android.accounts.AccountManagerCallback<java.lang.Boolean>">
+</parameter>
<parameter name="handler" type="android.os.Handler">
</parameter>
</method>
@@ -14401,7 +14176,7 @@
</parameter>
</method>
<method name="setAuthToken"
- return="android.accounts.Future1<java.lang.Void>"
+ return="void"
abstract="false"
native="false"
synchronized="false"
@@ -14410,19 +14185,15 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="callback" type="android.accounts.Future1Callback<java.lang.Void>">
-</parameter>
<parameter name="account" type="android.accounts.Account">
</parameter>
<parameter name="authTokenType" type="java.lang.String">
</parameter>
<parameter name="authToken" type="java.lang.String">
</parameter>
-<parameter name="handler" type="android.os.Handler">
-</parameter>
</method>
<method name="setPassword"
- return="android.accounts.Future1<java.lang.Void>"
+ return="void"
abstract="false"
native="false"
synchronized="false"
@@ -14431,17 +14202,13 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="callback" type="android.accounts.Future1Callback<java.lang.Void>">
-</parameter>
<parameter name="account" type="android.accounts.Account">
</parameter>
<parameter name="password" type="java.lang.String">
</parameter>
-<parameter name="handler" type="android.os.Handler">
-</parameter>
</method>
<method name="setUserData"
- return="android.accounts.Future1<java.lang.Void>"
+ return="void"
abstract="false"
native="false"
synchronized="false"
@@ -14450,19 +14217,15 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="callback" type="android.accounts.Future1Callback<java.lang.Void>">
-</parameter>
<parameter name="account" type="android.accounts.Account">
</parameter>
<parameter name="key" type="java.lang.String">
</parameter>
<parameter name="value" type="java.lang.String">
</parameter>
-<parameter name="handler" type="android.os.Handler">
-</parameter>
</method>
<method name="updateCredentials"
- return="android.accounts.Future2"
+ return="android.accounts.AccountManagerFuture<android.os.Bundle>"
abstract="false"
native="false"
synchronized="false"
@@ -14479,12 +14242,117 @@
</parameter>
<parameter name="activity" type="android.app.Activity">
</parameter>
-<parameter name="callback" type="android.accounts.Future2Callback">
+<parameter name="callback" type="android.accounts.AccountManagerCallback<android.os.Bundle>">
</parameter>
<parameter name="handler" type="android.os.Handler">
</parameter>
</method>
</class>
+<interface name="AccountManagerCallback"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="run"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="future" type="android.accounts.AccountManagerFuture<V>">
+</parameter>
+</method>
+</interface>
+<interface name="AccountManagerFuture"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="java.util.concurrent.Future">
+</implements>
+<method name="get"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<exception name="ExecutionException" type="java.util.concurrent.ExecutionException">
+</exception>
+<exception name="InterruptedException" type="java.lang.InterruptedException">
+</exception>
+</method>
+<method name="get"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="timeout" type="long">
+</parameter>
+<parameter name="unit" type="java.util.concurrent.TimeUnit">
+</parameter>
+<exception name="ExecutionException" type="java.util.concurrent.ExecutionException">
+</exception>
+<exception name="InterruptedException" type="java.lang.InterruptedException">
+</exception>
+<exception name="TimeoutException" type="java.util.concurrent.TimeoutException">
+</exception>
+</method>
+<method name="getResult"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="AuthenticatorException" type="android.accounts.AuthenticatorException">
+</exception>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+<exception name="OperationCanceledException" type="android.accounts.OperationCanceledException">
+</exception>
+</method>
+<method name="getResult"
+ return="V"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="timeout" type="long">
+</parameter>
+<parameter name="unit" type="java.util.concurrent.TimeUnit">
+</parameter>
+<exception name="AuthenticatorException" type="android.accounts.AuthenticatorException">
+</exception>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+<exception name="OperationCanceledException" type="android.accounts.OperationCanceledException">
+</exception>
+</method>
+</interface>
<class name="AuthenticatorDescription"
extends="java.lang.Object"
abstract="false"
@@ -14952,6 +14820,17 @@
visibility="public"
>
</field>
+<field name="PASSWORD_KEY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""password""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="USERDATA_KEY"
type="java.lang.String"
transient="false"
@@ -14964,136 +14843,6 @@
>
</field>
</class>
-<interface name="Future1"
- abstract="true"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="java.util.concurrent.Future">
-</implements>
-<method name="getResult"
- return="V"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="OperationCanceledException" type="android.accounts.OperationCanceledException">
-</exception>
-</method>
-<method name="getResult"
- return="V"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="timeout" type="long">
-</parameter>
-<parameter name="unit" type="java.util.concurrent.TimeUnit">
-</parameter>
-<exception name="OperationCanceledException" type="android.accounts.OperationCanceledException">
-</exception>
-</method>
-</interface>
-<interface name="Future1Callback"
- abstract="true"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="run"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="future" type="android.accounts.Future1<V>">
-</parameter>
-</method>
-</interface>
-<interface name="Future2"
- abstract="true"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="java.util.concurrent.Future">
-</implements>
-<method name="getResult"
- return="android.os.Bundle"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="AuthenticatorException" type="android.accounts.AuthenticatorException">
-</exception>
-<exception name="IOException" type="java.io.IOException">
-</exception>
-<exception name="OperationCanceledException" type="android.accounts.OperationCanceledException">
-</exception>
-</method>
-<method name="getResult"
- return="android.os.Bundle"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="timeout" type="long">
-</parameter>
-<parameter name="unit" type="java.util.concurrent.TimeUnit">
-</parameter>
-<exception name="AuthenticatorException" type="android.accounts.AuthenticatorException">
-</exception>
-<exception name="IOException" type="java.io.IOException">
-</exception>
-<exception name="OperationCanceledException" type="android.accounts.OperationCanceledException">
-</exception>
-</method>
-</interface>
-<interface name="Future2Callback"
- abstract="true"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="run"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="future" type="android.accounts.Future2">
-</parameter>
-</method>
-</interface>
<interface name="IAccountAuthenticator"
abstract="true"
static="false"
@@ -15179,6 +14928,23 @@
<exception name="RemoteException" type="android.os.RemoteException">
</exception>
</method>
+<method name="getAccountRemovalAllowed"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="response" type="android.accounts.IAccountAuthenticatorResponse">
+</parameter>
+<parameter name="account" type="android.accounts.Account">
+</parameter>
+<exception name="RemoteException" type="android.os.RemoteException">
+</exception>
+</method>
<method name="getAuthToken"
return="void"
abstract="true"
@@ -17225,6 +16991,23 @@
<parameter name="get" type="boolean">
</parameter>
</method>
+<method name="triggerSearch"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="query" type="java.lang.String">
+</parameter>
+<parameter name="appSearchData" type="android.os.Bundle">
+</parameter>
+<parameter name="globalSearch" type="boolean">
+</parameter>
+</method>
<method name="unregisterForContextMenu"
return="void"
abstract="false"
@@ -23447,6 +23230,25 @@
visibility="public"
>
</method>
+<method name="triggerSearch"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="query" type="java.lang.String">
+</parameter>
+<parameter name="launchActivity" type="android.content.ComponentName">
+</parameter>
+<parameter name="appSearchData" type="android.os.Bundle">
+</parameter>
+<parameter name="globalSearch" type="boolean">
+</parameter>
+</method>
<field name="ACTION_KEY"
type="java.lang.String"
transient="false"
@@ -27266,6 +27068,21 @@
<parameter name="selectionArgs" type="java.lang.String[]">
</parameter>
</method>
+<method name="getIsSyncable"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="account" type="android.accounts.Account">
+</parameter>
+<parameter name="authority" type="java.lang.String">
+</parameter>
+</method>
<method name="getMasterSyncAutomatically"
return="boolean"
abstract="false"
@@ -27563,6 +27380,23 @@
<parameter name="extras" type="android.os.Bundle">
</parameter>
</method>
+<method name="setIsSyncable"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="account" type="android.accounts.Account">
+</parameter>
+<parameter name="authority" type="java.lang.String">
+</parameter>
+<parameter name="syncable" type="int">
+</parameter>
+</method>
<method name="setMasterSyncAutomatically"
return="void"
abstract="false"
@@ -35999,6 +35833,17 @@
visibility="public"
>
</field>
+<field name="isUserFacing"
+ type="boolean"
+ transient="false"
+ volatile="false"
+ value="true"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
</class>
<interface name="SyncStatusObserver"
abstract="true"
@@ -61065,6 +60910,27 @@
<parameter name="srcName" type="java.lang.String">
</parameter>
</method>
+<method name="createFromResourceStream"
+ return="android.graphics.drawable.Drawable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="value" type="android.util.TypedValue">
+</parameter>
+<parameter name="is" type="java.io.InputStream">
+</parameter>
+<parameter name="srcName" type="java.lang.String">
+</parameter>
+<parameter name="opts" type="android.graphics.BitmapFactory.Options">
+</parameter>
+</method>
<method name="createFromStream"
return="android.graphics.drawable.Drawable"
abstract="false"
@@ -144220,6 +144086,19 @@
<parameter name="o" type="android.view.MotionEvent">
</parameter>
</method>
+<method name="obtainNoHistory"
+ return="android.view.MotionEvent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="o" type="android.view.MotionEvent">
+</parameter>
+</method>
<method name="offsetLocation"
return="void"
abstract="false"
@@ -145267,7 +145146,7 @@
value="40"
static="true"
final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
</field>
@@ -145278,7 +145157,7 @@
value="16"
static="true"
final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
</field>
@@ -145628,7 +145507,7 @@
value="2"
static="true"
final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
</field>
@@ -145639,7 +145518,7 @@
value="1"
static="true"
final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
</field>
@@ -155054,7 +154933,7 @@
value="2"
static="true"
final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
</field>
@@ -155065,7 +154944,7 @@
value="1"
static="true"
final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
visibility="public"
>
</field>
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 5b904cb..99e513c 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -130,8 +130,7 @@
// create the native surface
sp<SurfaceControl> control = session()->createSurface(
- getpid(), 0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565,
- ISurfaceComposer::eGPU);
+ getpid(), 0, dinfo.w, dinfo.h, PIXEL_FORMAT_RGB_565);
session()->openTransaction();
control->setLayer(0x40000000);
session()->closeTransaction();
diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk
index e6d0503..4576b8e 100644
--- a/cmds/stagefright/Android.mk
+++ b/cmds/stagefright/Android.mk
@@ -10,8 +10,7 @@
LOCAL_C_INCLUDES:= \
frameworks/base/media/libstagefright \
- $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
- $(TOP)/external/opencore/android
+ $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
LOCAL_CFLAGS += -Wno-multichar
@@ -31,8 +30,7 @@
LOCAL_C_INCLUDES:= \
frameworks/base/media/libstagefright \
- $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
- $(TOP)/external/opencore/android
+ $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
LOCAL_CFLAGS += -Wno-multichar
@@ -52,8 +50,7 @@
#
# LOCAL_C_INCLUDES:= \
# frameworks/base/media/libstagefright \
-# $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include \
-# $(TOP)/external/opencore/android
+# $(TOP)/external/opencore/extern_libs_v2/khronos/openmax/include
#
# LOCAL_CFLAGS += -Wno-multichar
#
diff --git a/cmds/stagefright/record.cpp b/cmds/stagefright/record.cpp
index cd54958..cf2962b 100644
--- a/cmds/stagefright/record.cpp
+++ b/cmds/stagefright/record.cpp
@@ -25,6 +25,7 @@
#include <media/stagefright/MPEG4Writer.h>
#include <media/stagefright/MmapSource.h>
#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
#include <media/stagefright/OMXDecoder.h>
using namespace android;
@@ -32,18 +33,38 @@
class DummySource : public MediaSource {
public:
DummySource(int width, int height)
- : mSize((width * height * 3) / 2) {
+ : mWidth(width),
+ mHeight(height),
+ mSize((width * height * 3) / 2) {
mGroup.add_buffer(new MediaBuffer(mSize));
}
- virtual ::status_t getMaxSampleSize(size_t *max_size) {
- *max_size = mSize;
- return ::OK;
+ virtual sp<MetaData> getFormat() {
+ sp<MetaData> meta = new MetaData;
+ meta->setInt32(kKeyWidth, mWidth);
+ meta->setInt32(kKeyHeight, mHeight);
+ meta->setCString(kKeyMIMEType, "video/raw");
+
+ return meta;
}
- virtual ::status_t read(MediaBuffer **buffer) {
- ::status_t err = mGroup.acquire_buffer(buffer);
- if (err != ::OK) {
+ virtual status_t getMaxSampleSize(size_t *max_size) {
+ *max_size = mSize;
+ return OK;
+ }
+
+ virtual status_t start(MetaData *params) {
+ return OK;
+ }
+
+ virtual status_t stop() {
+ return OK;
+ }
+
+ virtual status_t read(
+ MediaBuffer **buffer, const MediaSource::ReadOptions *options) {
+ status_t err = mGroup.acquire_buffer(buffer);
+ if (err != OK) {
return err;
}
@@ -51,34 +72,34 @@
memset((*buffer)->data(), x, mSize);
(*buffer)->set_range(0, mSize);
- return ::OK;
+ return OK;
}
+protected:
+ virtual ~DummySource() {}
+
private:
MediaBufferGroup mGroup;
+ int mWidth, mHeight;
size_t mSize;
DummySource(const DummySource &);
DummySource &operator=(const DummySource &);
};
-int main(int argc, char **argv) {
- android::ProcessState::self()->startThreadPool();
+#define USE_OMX_CODEC 1
-#if 1
- if (argc != 2) {
- fprintf(stderr, "usage: %s filename\n", argv[0]);
- return 1;
- }
+sp<MediaSource> createSource(const char *filename) {
+ sp<MediaSource> source;
- MPEG4Extractor extractor(new MmapSource(argv[1]));
- int num_tracks;
- assert(extractor.countTracks(&num_tracks) == ::OK);
+ sp<MPEG4Extractor> extractor =
+ new MPEG4Extractor(new MmapSource(filename));
- MediaSource *source = NULL;
+ size_t num_tracks = extractor->countTracks();
+
sp<MetaData> meta;
- for (int i = 0; i < num_tracks; ++i) {
- meta = extractor.getTrackMetaData(i);
+ for (size_t i = 0; i < num_tracks; ++i) {
+ meta = extractor->getTrackMetaData(i);
assert(meta.get() != NULL);
const char *mime;
@@ -90,48 +111,75 @@
continue;
}
- if (extractor.getTrack(i, &source) != ::OK) {
- source = NULL;
- continue;
- }
+ source = extractor->getTrack(i);
break;
}
- if (source == NULL) {
- fprintf(stderr, "Unable to find a suitable video track.\n");
+ return source;
+}
+
+int main(int argc, char **argv) {
+ android::ProcessState::self()->startThreadPool();
+
+#if 1
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s filename\n", argv[0]);
return 1;
}
OMXClient client;
assert(client.connect() == android::OK);
- OMXDecoder *decoder = OMXDecoder::Create(&client, meta);
- decoder->setSource(source);
+#if 0
+ sp<MediaSource> source = createSource(argv[1]);
+
+ if (source == NULL) {
+ fprintf(stderr, "Unable to find a suitable video track.\n");
+ return 1;
+ }
+
+ sp<MetaData> meta = source->getFormat();
+
+#if USE_OMX_CODEC
+ sp<OMXCodec> decoder = OMXCodec::Create(
+ client.interface(), meta, false /* createEncoder */, source);
+#else
+ sp<OMXDecoder> decoder = OMXDecoder::Create(
+ &client, meta, false /* createEncoder */, source);
+#endif
int width, height;
bool success = meta->findInt32(kKeyWidth, &width);
success = success && meta->findInt32(kKeyHeight, &height);
assert(success);
+#else
+ int width = 320;
+ int height = 240;
+ sp<MediaSource> decoder = new DummySource(width, height);
+#endif
sp<MetaData> enc_meta = new MetaData;
- enc_meta->setCString(kKeyMIMEType, "video/3gpp");
- // enc_meta->setCString(kKeyMIMEType, "video/mp4v-es");
+ // enc_meta->setCString(kKeyMIMEType, "video/3gpp");
+ enc_meta->setCString(kKeyMIMEType, "video/mp4v-es");
enc_meta->setInt32(kKeyWidth, width);
enc_meta->setInt32(kKeyHeight, height);
- OMXDecoder *encoder =
- OMXDecoder::Create(&client, enc_meta, true /* createEncoder */);
-
- encoder->setSource(decoder);
- // encoder->setSource(meta, new DummySource(width, height));
+#if USE_OMX_CODEC
+ sp<OMXCodec> encoder =
+ OMXCodec::Create(
+ client.interface(), enc_meta, true /* createEncoder */, decoder);
+#else
+ sp<OMXDecoder> encoder = OMXDecoder::Create(
+ &client, enc_meta, true /* createEncoder */, decoder);
+#endif
#if 1
- MPEG4Writer writer("/sdcard/output.mp4");
- writer.addSource(enc_meta, encoder);
- writer.start();
+ sp<MPEG4Writer> writer = new MPEG4Writer("/sdcard/output.mp4");
+ writer->addSource(enc_meta, encoder);
+ writer->start();
sleep(20);
printf("stopping now.\n");
- writer.stop();
+ writer->stop();
#else
encoder->start();
@@ -146,16 +194,7 @@
encoder->stop();
#endif
- delete encoder;
- encoder = NULL;
-
- delete decoder;
- decoder = NULL;
-
client.disconnect();
-
- delete source;
- source = NULL;
#endif
#if 0
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 7e23574..b2de67a 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -16,9 +16,6 @@
#include <sys/time.h>
-#undef NDEBUG
-#include <assert.h>
-
#include <pthread.h>
#include <stdlib.h>
@@ -30,12 +27,15 @@
#include <media/stagefright/ESDS.h>
#include <media/stagefright/FileSource.h>
#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaPlayerImpl.h>
#include <media/stagefright/MediaExtractor.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MmapSource.h>
#include <media/stagefright/OMXClient.h>
+#include <media/stagefright/OMXCodec.h>
#include <media/stagefright/OMXDecoder.h>
#include "WaveWriter.h"
@@ -44,50 +44,236 @@
////////////////////////////////////////////////////////////////////////////////
-static bool convertToWav(
- OMXClient *client, const sp<MetaData> &meta, MediaSource *source) {
- printf("convertToWav\n");
+struct JPEGSource : public MediaSource {
+ // Assumes ownership of "source".
+ JPEGSource(const sp<DataSource> &source);
- OMXDecoder *decoder = OMXDecoder::Create(client, meta);
+ virtual status_t start(MetaData *params = NULL);
+ virtual status_t stop();
+ virtual sp<MetaData> getFormat();
- int32_t sampleRate;
- bool success = meta->findInt32(kKeySampleRate, &sampleRate);
- assert(success);
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options = NULL);
- int32_t numChannels;
- success = meta->findInt32(kKeyChannelCount, &numChannels);
- assert(success);
+protected:
+ virtual ~JPEGSource();
- const char *mime;
- success = meta->findCString(kKeyMIMEType, &mime);
- assert(success);
+private:
+ sp<DataSource> mSource;
+ MediaBufferGroup *mGroup;
+ bool mStarted;
+ off_t mSize;
+ int32_t mWidth, mHeight;
+ off_t mOffset;
- if (!strcasecmp("audio/3gpp", mime)) {
- numChannels = 1; // XXX
+ status_t parseJPEG();
+
+ JPEGSource(const JPEGSource &);
+ JPEGSource &operator=(const JPEGSource &);
+};
+
+JPEGSource::JPEGSource(const sp<DataSource> &source)
+ : mSource(source),
+ mGroup(NULL),
+ mStarted(false),
+ mSize(0),
+ mWidth(0),
+ mHeight(0),
+ mOffset(0) {
+ CHECK_EQ(parseJPEG(), OK);
+}
+
+JPEGSource::~JPEGSource() {
+ if (mStarted) {
+ stop();
+ }
+}
+
+status_t JPEGSource::start(MetaData *) {
+ if (mStarted) {
+ return UNKNOWN_ERROR;
}
- WaveWriter writer("/sdcard/Music/shoutcast.wav", numChannels, sampleRate);
+ if (mSource->getSize(&mSize) != OK) {
+ return UNKNOWN_ERROR;
+ }
- decoder->setSource(source);
- for (int i = 0; i < 100; ++i) {
- MediaBuffer *buffer;
+ mGroup = new MediaBufferGroup;
+ mGroup->add_buffer(new MediaBuffer(mSize));
- ::status_t err = decoder->read(&buffer);
- if (err != ::OK) {
- break;
- }
+ mOffset = 0;
- writer.Append((const char *)buffer->data() + buffer->range_offset(),
- buffer->range_length());
+ mStarted = true;
+
+ return OK;
+}
+status_t JPEGSource::stop() {
+ if (!mStarted) {
+ return UNKNOWN_ERROR;
+ }
+
+ delete mGroup;
+ mGroup = NULL;
+
+ mStarted = false;
+
+ return OK;
+}
+
+sp<MetaData> JPEGSource::getFormat() {
+ sp<MetaData> meta = new MetaData;
+ meta->setCString(kKeyMIMEType, "image/jpeg");
+ meta->setInt32(kKeyWidth, mWidth);
+ meta->setInt32(kKeyHeight, mHeight);
+
+ return meta;
+}
+
+status_t JPEGSource::read(
+ MediaBuffer **out, const ReadOptions *options) {
+ *out = NULL;
+
+ int64_t seekTimeUs;
+ if (options != NULL && options->getSeekTo(&seekTimeUs)) {
+ return UNKNOWN_ERROR;
+ }
+
+ MediaBuffer *buffer;
+ mGroup->acquire_buffer(&buffer);
+
+ ssize_t n = mSource->read_at(mOffset, buffer->data(), mSize - mOffset);
+
+ if (n <= 0) {
buffer->release();
buffer = NULL;
+
+ return UNKNOWN_ERROR;
}
- delete decoder;
- decoder = NULL;
+ buffer->set_range(0, n);
- return true;
+ mOffset += n;
+
+ *out = buffer;
+
+ return OK;
+}
+
+#define JPEG_SOF0 0xC0 /* nStart Of Frame N*/
+#define JPEG_SOF1 0xC1 /* N indicates which compression process*/
+#define JPEG_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use*/
+#define JPEG_SOF3 0xC3
+#define JPEG_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers*/
+#define JPEG_SOF6 0xC6
+#define JPEG_SOF7 0xC7
+#define JPEG_SOF9 0xC9
+#define JPEG_SOF10 0xCA
+#define JPEG_SOF11 0xCB
+#define JPEG_SOF13 0xCD
+#define JPEG_SOF14 0xCE
+#define JPEG_SOF15 0xCF
+#define JPEG_SOI 0xD8 /* nStart Of Image (beginning of datastream)*/
+#define JPEG_EOI 0xD9 /* End Of Image (end of datastream)*/
+#define JPEG_SOS 0xDA /* nStart Of Scan (begins compressed data)*/
+#define JPEG_JFIF 0xE0 /* Jfif marker*/
+#define JPEG_EXIF 0xE1 /* Exif marker*/
+#define JPEG_COM 0xFE /* COMment */
+#define JPEG_DQT 0xDB
+#define JPEG_DHT 0xC4
+#define JPEG_DRI 0xDD
+
+status_t JPEGSource::parseJPEG() {
+ mWidth = 0;
+ mHeight = 0;
+
+ off_t i = 0;
+
+ uint16_t soi;
+ if (!mSource->getUInt16(i, &soi)) {
+ return ERROR_IO;
+ }
+
+ i += 2;
+
+ if (soi != 0xffd8) {
+ return UNKNOWN_ERROR;
+ }
+
+ for (;;) {
+ uint8_t marker;
+ if (mSource->read_at(i++, &marker, 1) != 1) {
+ return ERROR_IO;
+ }
+
+ CHECK_EQ(marker, 0xff);
+
+ if (mSource->read_at(i++, &marker, 1) != 1) {
+ return ERROR_IO;
+ }
+
+ CHECK(marker != 0xff);
+
+ uint16_t chunkSize;
+ if (!mSource->getUInt16(i, &chunkSize)) {
+ return ERROR_IO;
+ }
+
+ i += 2;
+
+ if (chunkSize < 2) {
+ return UNKNOWN_ERROR;
+ }
+
+ switch (marker) {
+ case JPEG_SOS:
+ {
+ return (mWidth > 0 && mHeight > 0) ? OK : UNKNOWN_ERROR;
+ }
+
+ case JPEG_EOI:
+ {
+ return UNKNOWN_ERROR;
+ }
+
+ case JPEG_SOF0:
+ case JPEG_SOF1:
+ case JPEG_SOF3:
+ case JPEG_SOF5:
+ case JPEG_SOF6:
+ case JPEG_SOF7:
+ case JPEG_SOF9:
+ case JPEG_SOF10:
+ case JPEG_SOF11:
+ case JPEG_SOF13:
+ case JPEG_SOF14:
+ case JPEG_SOF15:
+ {
+ uint16_t width, height;
+ if (!mSource->getUInt16(i + 1, &height)
+ || !mSource->getUInt16(i + 3, &width)) {
+ return ERROR_IO;
+ }
+
+ mWidth = width;
+ mHeight = height;
+
+ i += chunkSize - 2;
+ break;
+ }
+
+ default:
+ {
+ // Skip chunk
+
+ i += chunkSize - 2;
+
+ break;
+ }
+ }
+ }
+
+ return OK;
}
////////////////////////////////////////////////////////////////////////////////
@@ -99,6 +285,48 @@
return (int64_t)tv.tv_usec + tv.tv_sec * 1000000;
}
+#define USE_OMX_CODEC 1
+
+static void playSource(OMXClient *client, const sp<MediaSource> &source) {
+ sp<MetaData> meta = source->getFormat();
+
+#if !USE_OMX_CODEC
+ sp<OMXDecoder> decoder = OMXDecoder::Create(
+ client, meta, false /* createEncoder */, source);
+#else
+ sp<OMXCodec> decoder = OMXCodec::Create(
+ client->interface(), meta, false /* createEncoder */, source);
+#endif
+
+ if (decoder == NULL) {
+ return;
+ }
+
+ decoder->start();
+
+ int64_t startTime = getNowUs();
+
+ int n = 0;
+ MediaBuffer *buffer;
+ status_t err;
+ while ((err = decoder->read(&buffer)) == OK) {
+ if ((++n % 16) == 0) {
+ printf(".");
+ fflush(stdout);
+ }
+
+ buffer->release();
+ buffer = NULL;
+ }
+ decoder->stop();
+ printf("\n");
+
+ int64_t delay = getNowUs() - startTime;
+ printf("avg. %.2f fps\n", n * 1E6 / delay);
+
+ printf("decoded a total of %d frame(s).\n", n);
+}
+
int main(int argc, char **argv) {
android::ProcessState::self()->startThreadPool();
@@ -108,10 +336,10 @@
sp<IBinder> binder = sm->getService(String16("media.player"));
sp<IMediaPlayerService> service = interface_cast<IMediaPlayerService>(binder);
- assert(service.get() != NULL);
+ CHECK(service.get() != NULL);
sp<IOMX> omx = service->createOMX();
- assert(omx.get() != NULL);
+ CHECK(omx.get() != NULL);
List<String8> list;
omx->list_nodes(&list);
@@ -128,82 +356,52 @@
--argc;
}
-#if 0
- MediaPlayerImpl player(argv[1]);
- player.play();
-
- sleep(10000);
-#else
DataSource::RegisterDefaultSniffers();
OMXClient client;
status_t err = client.connect();
- MmapSource *dataSource = new MmapSource(argv[1]);
- MediaExtractor *extractor = MediaExtractor::Create(dataSource);
- dataSource = NULL;
+ sp<MmapSource> dataSource = new MmapSource(argv[1]);
- int numTracks;
- err = extractor->countTracks(&numTracks);
+ bool isJPEG = false;
- sp<MetaData> meta;
- int i;
- for (i = 0; i < numTracks; ++i) {
- meta = extractor->getTrackMetaData(i);
-
- const char *mime;
- meta->findCString(kKeyMIMEType, &mime);
-
- if (audioOnly && !strncasecmp(mime, "audio/", 6)) {
- break;
- }
-
- if (!audioOnly && !strncasecmp(mime, "video/", 6)) {
- break;
- }
+ size_t len = strlen(argv[1]);
+ if (len >= 4 && !strcasecmp(argv[1] + len - 4, ".jpg")) {
+ isJPEG = true;
}
- OMXDecoder *decoder = OMXDecoder::Create(&client, meta);
+ sp<MediaSource> mediaSource;
- if (decoder != NULL) {
- MediaSource *source;
- err = extractor->getTrack(i, &source);
+ if (isJPEG) {
+ mediaSource = new JPEGSource(dataSource);
+ } else {
+ sp<MediaExtractor> extractor = MediaExtractor::Create(dataSource);
- decoder->setSource(source);
+ size_t numTracks = extractor->countTracks();
- decoder->start();
+ sp<MetaData> meta;
+ size_t i;
+ for (i = 0; i < numTracks; ++i) {
+ meta = extractor->getTrackMetaData(i);
- int64_t startTime = getNowUs();
+ const char *mime;
+ meta->findCString(kKeyMIMEType, &mime);
- int n = 0;
- MediaBuffer *buffer;
- while ((err = decoder->read(&buffer)) == OK) {
- if ((++n % 16) == 0) {
- printf(".");
- fflush(stdout);
+ if (audioOnly && !strncasecmp(mime, "audio/", 6)) {
+ break;
}
- buffer->release();
- buffer = NULL;
+ if (!audioOnly && !strncasecmp(mime, "video/", 6)) {
+ break;
+ }
}
- decoder->stop();
- printf("\n");
- int64_t delay = getNowUs() - startTime;
- printf("avg. %.2f fps\n", n * 1E6 / delay);
-
- delete decoder;
- decoder = NULL;
-
- delete source;
- source = NULL;
+ mediaSource = extractor->getTrack(i);
}
- delete extractor;
- extractor = NULL;
+ playSource(&client, mediaSource);
client.disconnect();
-#endif
return 0;
}
diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java
index 3ce3ca3..38ae962 100644
--- a/core/java/android/accounts/AbstractAccountAuthenticator.java
+++ b/core/java/android/accounts/AbstractAccountAuthenticator.java
@@ -188,6 +188,25 @@
response.onResult(result);
}
}
+
+ public void getAccountRemovalAllowed(IAccountAuthenticatorResponse response,
+ Account account) throws RemoteException {
+ checkBinderPermission();
+ try {
+ final Bundle result = AbstractAccountAuthenticator.this.getAccountRemovalAllowed(
+ new AccountAuthenticatorResponse(response), account);
+ if (result != null) {
+ response.onResult(result);
+ }
+ } catch (UnsupportedOperationException e) {
+ response.onError(Constants.ERROR_CODE_UNSUPPORTED_OPERATION,
+ "getAccountRemovalAllowed not supported");
+ return;
+ } catch (NetworkErrorException e) {
+ response.onError(Constants.ERROR_CODE_NETWORK_ERROR, e.getMessage());
+ return;
+ }
+ }
}
private void checkBinderPermission() {
@@ -238,4 +257,10 @@
Account account, String authTokenType, Bundle loginOptions);
public abstract Bundle hasFeatures(AccountAuthenticatorResponse response,
Account account, String[] features) throws NetworkErrorException;
+ public Bundle getAccountRemovalAllowed(AccountAuthenticatorResponse response,
+ Account account) throws NetworkErrorException {
+ final Bundle result = new Bundle();
+ result.putBoolean(Constants.BOOLEAN_RESULT_KEY, true);
+ return result;
+ }
}
diff --git a/core/java/android/accounts/Account.java b/core/java/android/accounts/Account.java
index 30c91b0..7b83a30 100644
--- a/core/java/android/accounts/Account.java
+++ b/core/java/android/accounts/Account.java
@@ -26,20 +26,20 @@
* suitable for use as the key of a {@link java.util.Map}
*/
public class Account implements Parcelable {
- public final String mName;
- public final String mType;
+ public final String name;
+ public final String type;
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof Account)) return false;
final Account other = (Account)o;
- return mName.equals(other.mName) && mType.equals(other.mType);
+ return name.equals(other.name) && type.equals(other.type);
}
public int hashCode() {
int result = 17;
- result = 31 * result + mName.hashCode();
- result = 31 * result + mType.hashCode();
+ result = 31 * result + name.hashCode();
+ result = 31 * result + type.hashCode();
return result;
}
@@ -50,13 +50,13 @@
if (TextUtils.isEmpty(type)) {
throw new IllegalArgumentException("the type must not be empty: " + type);
}
- mName = name;
- mType = type;
+ this.name = name;
+ this.type = type;
}
public Account(Parcel in) {
- mName = in.readString();
- mType = in.readString();
+ this.name = in.readString();
+ this.type = in.readString();
}
public int describeContents() {
@@ -64,8 +64,8 @@
}
public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(mName);
- dest.writeString(mType);
+ dest.writeString(name);
+ dest.writeString(type);
}
public static final Creator<Account> CREATOR = new Creator<Account>() {
@@ -79,6 +79,6 @@
};
public String toString() {
- return "Account {name=" + mName + ", type=" + mType + "}";
+ return "Account {name=" + name + ", type=" + type + "}";
}
}
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index 502abbb..9f70534 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -26,8 +26,6 @@
import android.os.Looper;
import android.os.RemoteException;
import android.os.Parcelable;
-import android.util.Config;
-import android.util.Log;
import java.io.IOException;
import java.util.concurrent.Callable;
@@ -80,258 +78,132 @@
return (AccountManager) context.getSystemService(Context.ACCOUNT_SERVICE);
}
- public String blockingGetPassword(Account account) {
- ensureNotOnMainThread();
+ public String getPassword(final Account account) {
try {
return mService.getPassword(account);
} catch (RemoteException e) {
- // if this happens the entire runtime will restart
+ // will never happen
throw new RuntimeException(e);
}
}
- public Future1<String> getPassword(final Future1Callback<String> callback,
- final Account account, final Handler handler) {
- return startAsFuture(callback, handler, new Callable<String>() {
- public String call() throws Exception {
- return blockingGetPassword(account);
- }
- });
- }
-
- public String blockingGetUserData(Account account, String key) {
- ensureNotOnMainThread();
+ public String getUserData(final Account account, final String key) {
try {
return mService.getUserData(account, key);
} catch (RemoteException e) {
- // if this happens the entire runtime will restart
+ // will never happen
throw new RuntimeException(e);
}
}
- public Future1<String> getUserData(Future1Callback<String> callback,
- final Account account, final String key, Handler handler) {
- return startAsFuture(callback, handler, new Callable<String>() {
- public String call() throws Exception {
- return blockingGetUserData(account, key);
- }
- });
- }
-
- public AuthenticatorDescription[] blockingGetAuthenticatorTypes() {
- ensureNotOnMainThread();
+ public AuthenticatorDescription[] getAuthenticatorTypes() {
try {
return mService.getAuthenticatorTypes();
} catch (RemoteException e) {
- // if this happens the entire runtime will restart
+ // will never happen
throw new RuntimeException(e);
}
}
- public Future1<AuthenticatorDescription[]> getAuthenticatorTypes(
- Future1Callback<AuthenticatorDescription[]> callback, Handler handler) {
- return startAsFuture(callback, handler, new Callable<AuthenticatorDescription[]>() {
- public AuthenticatorDescription[] call() throws Exception {
- return blockingGetAuthenticatorTypes();
- }
- });
- }
-
- public Account[] blockingGetAccounts() {
- ensureNotOnMainThread();
+ public Account[] getAccounts() {
try {
- return mService.getAccounts();
+ return mService.getAccounts(null);
} catch (RemoteException e) {
- // if this happens the entire runtime will restart
+ // won't ever happen
throw new RuntimeException(e);
}
}
- public Account[] blockingGetAccountsByType(String accountType) {
- ensureNotOnMainThread();
+ public Account[] getAccountsByType(String type) {
try {
- return mService.getAccountsByType(accountType);
+ return mService.getAccounts(type);
} catch (RemoteException e) {
- // if this happens the entire runtime will restart
+ // won't ever happen
throw new RuntimeException(e);
}
}
- public Future1<Account[]> getAccounts(Future1Callback<Account[]> callback, Handler handler) {
- return startAsFuture(callback, handler, new Callable<Account[]>() {
- public Account[] call() throws Exception {
- return blockingGetAccounts();
- }
- });
- }
-
- public Future1<Account[]> getAccountsByType(Future1Callback<Account[]> callback,
- final String type, Handler handler) {
- return startAsFuture(callback, handler, new Callable<Account[]>() {
- public Account[] call() throws Exception {
- return blockingGetAccountsByType(type);
- }
- });
- }
-
- public boolean blockingAddAccountExplicitly(Account account, String password, Bundle extras) {
- ensureNotOnMainThread();
+ public boolean addAccountExplicitly(Account account, String password, Bundle extras) {
try {
return mService.addAccount(account, password, extras);
} catch (RemoteException e) {
- // if this happens the entire runtime will restart
+ // won't ever happen
throw new RuntimeException(e);
}
}
- public Future1<Boolean> addAccountExplicitly(final Future1Callback<Boolean> callback,
- final Account account, final String password, final Bundle extras,
- final Handler handler) {
- return startAsFuture(callback, handler, new Callable<Boolean>() {
- public Boolean call() throws Exception {
- return blockingAddAccountExplicitly(account, password, extras);
+ public AccountManagerFuture<Boolean> removeAccount(final Account account,
+ AccountManagerCallback<Boolean> callback, Handler handler) {
+ return new Future2Task<Boolean>(handler, callback) {
+ public void doWork() throws RemoteException {
+ mService.removeAccount(mResponse, account);
}
- });
- }
-
- public void blockingRemoveAccount(Account account) {
- ensureNotOnMainThread();
- try {
- mService.removeAccount(account);
- } catch (RemoteException e) {
- // if this happens the entire runtime will restart
- }
- }
-
- public Future1<Void> removeAccount(Future1Callback<Void> callback, final Account account,
- final Handler handler) {
- return startAsFuture(callback, handler, new Callable<Void>() {
- public Void call() throws Exception {
- blockingRemoveAccount(account);
- return null;
+ public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
+ if (!bundle.containsKey(Constants.BOOLEAN_RESULT_KEY)) {
+ throw new AuthenticatorException("no result in response");
+ }
+ return bundle.getBoolean(Constants.BOOLEAN_RESULT_KEY);
}
- });
+ }.start();
}
- public void blockingInvalidateAuthToken(String accountType, String authToken) {
- ensureNotOnMainThread();
+ public void invalidateAuthToken(final String accountType, final String authToken) {
try {
mService.invalidateAuthToken(accountType, authToken);
} catch (RemoteException e) {
- // if this happens the entire runtime will restart
- }
- }
-
- public Future1<Void> invalidateAuthToken(Future1Callback<Void> callback,
- final String accountType, final String authToken, final Handler handler) {
- return startAsFuture(callback, handler, new Callable<Void>() {
- public Void call() throws Exception {
- blockingInvalidateAuthToken(accountType, authToken);
- return null;
- }
- });
- }
-
- public String blockingPeekAuthToken(Account account, String authTokenType) {
- ensureNotOnMainThread();
- try {
- return mService.peekAuthToken(account, authTokenType);
- } catch (RemoteException e) {
- // if this happens the entire runtime will restart
+ // won't ever happen
throw new RuntimeException(e);
}
}
- public Future1<String> peekAuthToken(Future1Callback<String> callback,
- final Account account, final String authTokenType, final Handler handler) {
- return startAsFuture(callback, handler, new Callable<String>() {
- public String call() throws Exception {
- return blockingPeekAuthToken(account, authTokenType);
- }
- });
+ public String peekAuthToken(final Account account, final String authTokenType) {
+ try {
+ return mService.peekAuthToken(account, authTokenType);
+ } catch (RemoteException e) {
+ // won't ever happen
+ throw new RuntimeException(e);
+ }
}
- public void blockingSetPassword(Account account, String password) {
- ensureNotOnMainThread();
+ public void setPassword(final Account account, final String password) {
try {
mService.setPassword(account, password);
} catch (RemoteException e) {
- // if this happens the entire runtime will restart
+ // won't ever happen
+ throw new RuntimeException(e);
}
}
- public Future1<Void> setPassword(Future1Callback<Void> callback,
- final Account account, final String password, final Handler handler) {
- return startAsFuture(callback, handler, new Callable<Void>() {
- public Void call() throws Exception {
- blockingSetPassword(account, password);
- return null;
- }
- });
- }
-
- public void blockingClearPassword(Account account) {
- ensureNotOnMainThread();
+ public void clearPassword(final Account account) {
try {
mService.clearPassword(account);
} catch (RemoteException e) {
- // if this happens the entire runtime will restart
+ // won't ever happen
+ throw new RuntimeException(e);
}
}
- public Future1<Void> clearPassword(final Future1Callback<Void> callback, final Account account,
- final Handler handler) {
- return startAsFuture(callback, handler, new Callable<Void>() {
- public Void call() throws Exception {
- blockingClearPassword(account);
- return null;
- }
- });
- }
-
- public void blockingSetUserData(Account account, String key, String value) {
- ensureNotOnMainThread();
+ public void setUserData(final Account account, final String key, final String value) {
try {
mService.setUserData(account, key, value);
} catch (RemoteException e) {
- // if this happens the entire runtime will restart
+ // won't ever happen
+ throw new RuntimeException(e);
}
}
- public Future1<Void> setUserData(Future1Callback<Void> callback,
- final Account account, final String key, final String value, final Handler handler) {
- return startAsFuture(callback, handler, new Callable<Void>() {
- public Void call() throws Exception {
- blockingSetUserData(account, key, value);
- return null;
- }
- });
- }
-
- public void blockingSetAuthToken(Account account, String authTokenType, String authToken) {
- ensureNotOnMainThread();
+ public void setAuthToken(Account account, final String authTokenType, final String authToken) {
try {
mService.setAuthToken(account, authTokenType, authToken);
} catch (RemoteException e) {
- // if this happens the entire runtime will restart
+ // won't ever happen
+ throw new RuntimeException(e);
}
}
- public Future1<Void> setAuthToken(Future1Callback<Void> callback,
- final Account account, final String authTokenType, final String authToken,
- final Handler handler) {
- return startAsFuture(callback, handler, new Callable<Void>() {
- public Void call() throws Exception {
- blockingSetAuthToken(account, authTokenType, authToken);
- return null;
- }
- });
- }
-
public String blockingGetAuthToken(Account account, String authTokenType,
boolean notifyAuthFailure)
throws OperationCanceledException, IOException, AuthenticatorException {
- ensureNotOnMainThread();
Bundle bundle = getAuthToken(account, authTokenType, notifyAuthFailure, null /* callback */,
null /* handler */).getResult();
return bundle.getString(Constants.AUTHTOKEN_KEY);
@@ -349,9 +221,9 @@
* @param loginOptions
* @param activity the activity to launch the login intent, if necessary, and to which
*/
- public Future2 getAuthToken(
+ public AccountManagerFuture<Bundle> getAuthToken(
final Account account, final String authTokenType, final Bundle loginOptions,
- final Activity activity, Future2Callback callback, Handler handler) {
+ final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
if (activity == null) throw new IllegalArgumentException("activity is null");
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
return new AmsTask(activity, handler, callback) {
@@ -363,9 +235,9 @@
}.start();
}
- public Future2 getAuthToken(
+ public AccountManagerFuture<Bundle> getAuthToken(
final Account account, final String authTokenType, final boolean notifyAuthFailure,
- Future2Callback callback, Handler handler) {
+ AccountManagerCallback<Bundle> callback, Handler handler) {
if (account == null) throw new IllegalArgumentException("account is null");
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
return new AmsTask(null, handler, callback) {
@@ -376,10 +248,10 @@
}.start();
}
- public Future2 addAccount(final String accountType,
+ public AccountManagerFuture<Bundle> addAccount(final String accountType,
final String authTokenType, final String[] requiredFeatures,
final Bundle addAccountOptions,
- final Activity activity, Future2Callback callback, Handler handler) {
+ final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
return new AmsTask(activity, handler, callback) {
public void doWork() throws RemoteException {
mService.addAcount(mResponse, accountType, authTokenType,
@@ -389,44 +261,45 @@
}
/** @deprecated use {@link #confirmCredentials} instead */
- public Future1<Boolean> confirmPassword(final Account account, final String password,
- Future1Callback<Boolean> callback, Handler handler) {
- return new AMSTaskBoolean(handler, callback) {
+ public AccountManagerFuture<Boolean> confirmPassword(final Account account, final String password,
+ AccountManagerCallback<Boolean> callback, Handler handler) {
+ return new Future2Task<Boolean>(handler, callback) {
public void doWork() throws RemoteException {
- mService.confirmPassword(response, account, password);
+ mService.confirmPassword(mResponse, account, password);
}
- };
- }
-
- public Account[] blockingGetAccountsWithTypeAndFeatures(String type, String[] features)
- throws AuthenticatorException, IOException, OperationCanceledException {
- Future2 future = getAccountsWithTypeAndFeatures(type, features,
- null /* callback */, null /* handler */);
- Bundle result = future.getResult();
- Parcelable[] accountsTemp = result.getParcelableArray(Constants.ACCOUNTS_KEY);
- if (accountsTemp == null) {
- throw new AuthenticatorException("accounts should not be null");
- }
- Account[] accounts = new Account[accountsTemp.length];
- for (int i = 0; i < accountsTemp.length; i++) {
- accounts[i] = (Account) accountsTemp[i];
- }
- return accounts;
- }
-
- public Future2 getAccountsWithTypeAndFeatures(
- final String type, final String[] features,
- Future2Callback callback, Handler handler) {
- if (type == null) throw new IllegalArgumentException("type is null");
- return new AmsTask(null /* activity */, handler, callback) {
- public void doWork() throws RemoteException {
- mService.getAccountsByTypeAndFeatures(mResponse, type, features);
+ public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
+ if (!bundle.containsKey(Constants.BOOLEAN_RESULT_KEY)) {
+ throw new AuthenticatorException("no result in response");
+ }
+ return bundle.getBoolean(Constants.BOOLEAN_RESULT_KEY);
}
}.start();
}
- public Future2 confirmCredentials(final Account account, final Activity activity,
- final Future2Callback callback,
+ public AccountManagerFuture<Account[]> getAccountsByTypeAndFeatures(
+ final String type, final String[] features,
+ AccountManagerCallback<Account[]> callback, Handler handler) {
+ if (type == null) throw new IllegalArgumentException("type is null");
+ return new Future2Task<Account[]>(handler, callback) {
+ public void doWork() throws RemoteException {
+ mService.getAccountsByFeatures(mResponse, type, features);
+ }
+ public Account[] bundleToResult(Bundle bundle) throws AuthenticatorException {
+ if (!bundle.containsKey(Constants.ACCOUNTS_KEY)) {
+ throw new AuthenticatorException("no result in response");
+ }
+ final Parcelable[] parcelables = bundle.getParcelableArray(Constants.ACCOUNTS_KEY);
+ Account[] descs = new Account[parcelables.length];
+ for (int i = 0; i < parcelables.length; i++) {
+ descs[i] = (Account) parcelables[i];
+ }
+ return descs;
+ }
+ }.start();
+ }
+
+ public AccountManagerFuture<Bundle> confirmCredentials(final Account account, final Activity activity,
+ final AccountManagerCallback<Bundle> callback,
final Handler handler) {
return new AmsTask(activity, handler, callback) {
public void doWork() throws RemoteException {
@@ -435,9 +308,9 @@
}.start();
}
- public Future2 updateCredentials(final Account account, final String authTokenType,
+ public AccountManagerFuture<Bundle> updateCredentials(final Account account, final String authTokenType,
final Bundle loginOptions, final Activity activity,
- final Future2Callback callback,
+ final AccountManagerCallback<Bundle> callback,
final Handler handler) {
return new AmsTask(activity, handler, callback) {
public void doWork() throws RemoteException {
@@ -447,8 +320,8 @@
}.start();
}
- public Future2 editProperties(final String accountType, final Activity activity,
- final Future2Callback callback,
+ public AccountManagerFuture<Bundle> editProperties(final String accountType, final Activity activity,
+ final AccountManagerCallback<Bundle> callback,
final Handler handler) {
return new AmsTask(activity, handler, callback) {
public void doWork() throws RemoteException {
@@ -471,8 +344,8 @@
}
}
- private void postToHandler(Handler handler, final Future2Callback callback,
- final Future2 future) {
+ private void postToHandler(Handler handler, final AccountManagerCallback<Bundle> callback,
+ final AccountManagerFuture<Bundle> future) {
handler = handler == null ? mMainHandler : handler;
handler.post(new Runnable() {
public void run() {
@@ -483,87 +356,24 @@
private void postToHandler(Handler handler, final OnAccountsUpdatedListener listener,
final Account[] accounts) {
- handler = handler == null ? mMainHandler : handler;
+ final Account[] accountsCopy = new Account[accounts.length];
+ // send a copy to make sure that one doesn't
+ // change what another sees
+ System.arraycopy(accounts, 0, accountsCopy, 0, accountsCopy.length);
+ handler = (handler == null) ? mMainHandler : handler;
handler.post(new Runnable() {
public void run() {
- listener.onAccountsUpdated(accounts);
+ listener.onAccountsUpdated(accountsCopy);
}
});
}
- private <V> void postToHandler(Handler handler, final Future1Callback<V> callback,
- final Future1<V> future) {
- handler = handler == null ? mMainHandler : handler;
- handler.post(new Runnable() {
- public void run() {
- callback.run(future);
- }
- });
- }
-
- private <V> Future1<V> startAsFuture(Future1Callback<V> callback, Handler handler,
- Callable<V> callable) {
- final FutureTaskWithCallback<V> task =
- new FutureTaskWithCallback<V>(callback, callable, handler);
- new Thread(task).start();
- return task;
- }
-
- private class FutureTaskWithCallback<V> extends FutureTask<V> implements Future1<V> {
- final Future1Callback<V> mCallback;
- final Handler mHandler;
-
- public FutureTaskWithCallback(Future1Callback<V> callback, Callable<V> callable,
- Handler handler) {
- super(callable);
- mCallback = callback;
- mHandler = handler;
- }
-
- protected void done() {
- if (mCallback != null) {
- postToHandler(mHandler, mCallback, this);
- }
- }
-
- public V internalGetResult(Long timeout, TimeUnit unit) throws OperationCanceledException {
- try {
- if (timeout == null) {
- return get();
- } else {
- return get(timeout, unit);
- }
- } catch (InterruptedException e) {
- // we will cancel the task below
- } catch (CancellationException e) {
- // we will cancel the task below
- } catch (TimeoutException e) {
- // we will cancel the task below
- } catch (ExecutionException e) {
- // this should never happen
- throw new IllegalStateException(e.getCause());
- } finally {
- cancel(true /* interruptIfRunning */);
- }
- throw new OperationCanceledException();
- }
-
- public V getResult() throws OperationCanceledException {
- return internalGetResult(null, null);
- }
-
- public V getResult(long timeout, TimeUnit unit) throws OperationCanceledException {
- return internalGetResult(null, null);
- }
- }
-
- private abstract class AmsTask extends FutureTask<Bundle> implements Future2 {
+ private abstract class AmsTask extends FutureTask<Bundle> implements AccountManagerFuture<Bundle> {
final IAccountManagerResponse mResponse;
final Handler mHandler;
- final Future2Callback mCallback;
+ final AccountManagerCallback<Bundle> mCallback;
final Activity mActivity;
- final Thread mThread;
- public AmsTask(Activity activity, Handler handler, Future2Callback callback) {
+ public AmsTask(Activity activity, Handler handler, AccountManagerCallback<Bundle> callback) {
super(new Callable<Bundle>() {
public Bundle call() throws Exception {
throw new IllegalStateException("this should never be called");
@@ -574,19 +384,14 @@
mCallback = callback;
mActivity = activity;
mResponse = new Response();
- mThread = new Thread(new Runnable() {
- public void run() {
- try {
- doWork();
- } catch (RemoteException e) {
- // never happens
- }
- }
- }, "AmsTask");
}
- public final Future2 start() {
- mThread.start();
+ public final AccountManagerFuture<Bundle> start() {
+ try {
+ doWork();
+ } catch (RemoteException e) {
+ setException(e);
+ }
return this;
}
@@ -594,6 +399,7 @@
private Bundle internalGetResult(Long timeout, TimeUnit unit)
throws OperationCanceledException, IOException, AuthenticatorException {
+ ensureNotOnMainThread();
try {
if (timeout == null) {
return get();
@@ -676,92 +482,50 @@
}
- private abstract class AMSTaskBoolean extends FutureTask<Boolean> implements Future1<Boolean> {
- final IAccountManagerResponse response;
+ private abstract class BaseFutureTask<T> extends FutureTask<T> {
+ final public IAccountManagerResponse mResponse;
final Handler mHandler;
- final Future1Callback<Boolean> mCallback;
- public AMSTaskBoolean(Handler handler, Future1Callback<Boolean> callback) {
- super(new Callable<Boolean>() {
- public Boolean call() throws Exception {
+
+ public BaseFutureTask(Handler handler) {
+ super(new Callable<T>() {
+ public T call() throws Exception {
throw new IllegalStateException("this should never be called");
}
});
-
mHandler = handler;
- mCallback = callback;
- response = new Response();
-
- new Thread(new Runnable() {
- public void run() {
- try {
- doWork();
- } catch (RemoteException e) {
- // never happens
- }
- }
- }).start();
+ mResponse = new Response();
}
public abstract void doWork() throws RemoteException;
+ public abstract T bundleToResult(Bundle bundle) throws AuthenticatorException;
- protected void done() {
- if (mCallback != null) {
- postToHandler(mHandler, mCallback, this);
- }
+ protected void postRunnableToHandler(Runnable runnable) {
+ Handler handler = (mHandler == null) ? mMainHandler : mHandler;
+ handler.post(runnable);
}
- private Boolean internalGetResult(Long timeout, TimeUnit unit) {
+ protected void startTask() {
try {
- if (timeout == null) {
- return get();
- } else {
- return get(timeout, unit);
- }
- } catch (InterruptedException e) {
- // fall through and cancel
- } catch (TimeoutException e) {
- // fall through and cancel
- } catch (CancellationException e) {
- return false;
- } catch (ExecutionException e) {
- final Throwable cause = e.getCause();
- if (cause instanceof IOException) {
- return false;
- } else if (cause instanceof UnsupportedOperationException) {
- return false;
- } else if (cause instanceof AuthenticatorException) {
- return false;
- } else if (cause instanceof RuntimeException) {
- throw (RuntimeException) cause;
- } else if (cause instanceof Error) {
- throw (Error) cause;
- } else {
- throw new IllegalStateException(cause);
- }
- } finally {
- cancel(true /* interrupt if running */);
+ doWork();
+ } catch (RemoteException e) {
+ setException(e);
}
- return false;
}
- public Boolean getResult() throws OperationCanceledException {
- return internalGetResult(null, null);
- }
-
- public Boolean getResult(long timeout, TimeUnit unit) throws OperationCanceledException {
- return internalGetResult(timeout, unit);
- }
-
- private class Response extends IAccountManagerResponse.Stub {
+ protected class Response extends IAccountManagerResponse.Stub {
public void onResult(Bundle bundle) {
try {
- if (bundle.containsKey(Constants.BOOLEAN_RESULT_KEY)) {
- set(bundle.getBoolean(Constants.BOOLEAN_RESULT_KEY));
+ T result = bundleToResult(bundle);
+ if (result == null) {
return;
}
+ set(result);
+ return;
} catch (ClassCastException e) {
// we will set the exception below
+ } catch (AuthenticatorException e) {
+ // we will set the exception below
}
onError(Constants.ERROR_CODE_INVALID_RESPONSE, "no result in response");
}
@@ -774,6 +538,76 @@
setException(convertErrorToException(code, message));
}
}
+ }
+
+ private abstract class Future2Task<T>
+ extends BaseFutureTask<T> implements AccountManagerFuture<T> {
+ final AccountManagerCallback<T> mCallback;
+ public Future2Task(Handler handler, AccountManagerCallback<T> callback) {
+ super(handler);
+ mCallback = callback;
+ }
+
+ protected void done() {
+ if (mCallback != null) {
+ postRunnableToHandler(new Runnable() {
+ public void run() {
+ mCallback.run(Future2Task.this);
+ }
+ });
+ }
+ }
+
+ public Future2Task<T> start() {
+ startTask();
+ return this;
+ }
+
+ private T internalGetResult(Long timeout, TimeUnit unit)
+ throws OperationCanceledException, IOException, AuthenticatorException {
+ ensureNotOnMainThread();
+ try {
+ if (timeout == null) {
+ return get();
+ } else {
+ return get(timeout, unit);
+ }
+ } catch (InterruptedException e) {
+ // fall through and cancel
+ } catch (TimeoutException e) {
+ // fall through and cancel
+ } catch (CancellationException e) {
+ // fall through and cancel
+ } catch (ExecutionException e) {
+ final Throwable cause = e.getCause();
+ if (cause instanceof IOException) {
+ throw (IOException) cause;
+ } else if (cause instanceof UnsupportedOperationException) {
+ throw new AuthenticatorException(cause);
+ } else if (cause instanceof AuthenticatorException) {
+ throw (AuthenticatorException) cause;
+ } else if (cause instanceof RuntimeException) {
+ throw (RuntimeException) cause;
+ } else if (cause instanceof Error) {
+ throw (Error) cause;
+ } else {
+ throw new IllegalStateException(cause);
+ }
+ } finally {
+ cancel(true /* interrupt if running */);
+ }
+ throw new OperationCanceledException();
+ }
+
+ public T getResult()
+ throws OperationCanceledException, IOException, AuthenticatorException {
+ return internalGetResult(null, null);
+ }
+
+ public T getResult(long timeout, TimeUnit unit)
+ throws OperationCanceledException, IOException, AuthenticatorException {
+ return internalGetResult(timeout, unit);
+ }
}
@@ -797,11 +631,12 @@
return new AuthenticatorException(message);
}
- private class GetAuthTokenByTypeAndFeaturesTask extends AmsTask implements Future2Callback {
+ private class GetAuthTokenByTypeAndFeaturesTask
+ extends AmsTask implements AccountManagerCallback<Bundle> {
GetAuthTokenByTypeAndFeaturesTask(final String accountType, final String authTokenType,
final String[] features, Activity activityForPrompting,
final Bundle addAccountOptions, final Bundle loginOptions,
- Future2Callback callback, Handler handler) {
+ AccountManagerCallback<Bundle> callback, Handler handler) {
super(activityForPrompting, handler, callback);
if (accountType == null) throw new IllegalArgumentException("account type is null");
mAccountType = accountType;
@@ -811,101 +646,100 @@
mLoginOptions = loginOptions;
mMyCallback = this;
}
- volatile Future2 mFuture = null;
+ volatile AccountManagerFuture<Bundle> mFuture = null;
final String mAccountType;
final String mAuthTokenType;
final String[] mFeatures;
final Bundle mAddAccountOptions;
final Bundle mLoginOptions;
- final Future2Callback mMyCallback;
+ final AccountManagerCallback<Bundle> mMyCallback;
public void doWork() throws RemoteException {
- getAccountsWithTypeAndFeatures(mAccountType, mFeatures, new Future2Callback() {
- public void run(Future2 future) {
- Bundle getAccountsResult;
- try {
- getAccountsResult = future.getResult();
- } catch (OperationCanceledException e) {
- setException(e);
- return;
- } catch (IOException e) {
- setException(e);
- return;
- } catch (AuthenticatorException e) {
- setException(e);
- return;
- }
-
- Parcelable[] accounts =
- getAccountsResult.getParcelableArray(Constants.ACCOUNTS_KEY);
- if (accounts.length == 0) {
- if (mActivity != null) {
- // no accounts, add one now. pretend that the user directly
- // made this request
- mFuture = addAccount(mAccountType, mAuthTokenType, mFeatures,
- mAddAccountOptions, mActivity, mMyCallback, mHandler);
- } else {
- // send result since we can't prompt to add an account
- Bundle result = new Bundle();
- result.putString(Constants.ACCOUNT_NAME_KEY, null);
- result.putString(Constants.ACCOUNT_TYPE_KEY, null);
- result.putString(Constants.AUTHTOKEN_KEY, null);
+ getAccountsByTypeAndFeatures(mAccountType, mFeatures,
+ new AccountManagerCallback<Account[]>() {
+ public void run(AccountManagerFuture<Account[]> future) {
+ Account[] accounts;
try {
- mResponse.onResult(result);
- } catch (RemoteException e) {
- // this will never happen
+ accounts = future.getResult();
+ } catch (OperationCanceledException e) {
+ setException(e);
+ return;
+ } catch (IOException e) {
+ setException(e);
+ return;
+ } catch (AuthenticatorException e) {
+ setException(e);
+ return;
}
- // we are done
- }
- } else if (accounts.length == 1) {
- // have a single account, return an authtoken for it
- if (mActivity == null) {
- mFuture = getAuthToken((Account) accounts[0], mAuthTokenType,
- false /* notifyAuthFailure */, mMyCallback, mHandler);
- } else {
- mFuture = getAuthToken((Account) accounts[0],
- mAuthTokenType, mLoginOptions,
- mActivity, mMyCallback, mHandler);
- }
- } else {
- if (mActivity != null) {
- IAccountManagerResponse chooseResponse =
- new IAccountManagerResponse.Stub() {
- public void onResult(Bundle value) throws RemoteException {
- Account account = new Account(
- value.getString(Constants.ACCOUNT_NAME_KEY),
- value.getString(Constants.ACCOUNT_TYPE_KEY));
- mFuture = getAuthToken(account, mAuthTokenType, mLoginOptions,
+
+ if (accounts.length == 0) {
+ if (mActivity != null) {
+ // no accounts, add one now. pretend that the user directly
+ // made this request
+ mFuture = addAccount(mAccountType, mAuthTokenType, mFeatures,
+ mAddAccountOptions, mActivity, mMyCallback, mHandler);
+ } else {
+ // send result since we can't prompt to add an account
+ Bundle result = new Bundle();
+ result.putString(Constants.ACCOUNT_NAME_KEY, null);
+ result.putString(Constants.ACCOUNT_TYPE_KEY, null);
+ result.putString(Constants.AUTHTOKEN_KEY, null);
+ try {
+ mResponse.onResult(result);
+ } catch (RemoteException e) {
+ // this will never happen
+ }
+ // we are done
+ }
+ } else if (accounts.length == 1) {
+ // have a single account, return an authtoken for it
+ if (mActivity == null) {
+ mFuture = getAuthToken(accounts[0], mAuthTokenType,
+ false /* notifyAuthFailure */, mMyCallback, mHandler);
+ } else {
+ mFuture = getAuthToken(accounts[0],
+ mAuthTokenType, mLoginOptions,
mActivity, mMyCallback, mHandler);
}
+ } else {
+ if (mActivity != null) {
+ IAccountManagerResponse chooseResponse =
+ new IAccountManagerResponse.Stub() {
+ public void onResult(Bundle value) throws RemoteException {
+ Account account = new Account(
+ value.getString(Constants.ACCOUNT_NAME_KEY),
+ value.getString(Constants.ACCOUNT_TYPE_KEY));
+ mFuture = getAuthToken(account, mAuthTokenType, mLoginOptions,
+ mActivity, mMyCallback, mHandler);
+ }
- public void onError(int errorCode, String errorMessage)
- throws RemoteException {
- mResponse.onError(errorCode, errorMessage);
+ public void onError(int errorCode, String errorMessage)
+ throws RemoteException {
+ mResponse.onError(errorCode, errorMessage);
+ }
+ };
+ // have many accounts, launch the chooser
+ Intent intent = new Intent();
+ intent.setClassName("android",
+ "android.accounts.ChooseAccountActivity");
+ intent.putExtra(Constants.ACCOUNTS_KEY, accounts);
+ intent.putExtra(Constants.ACCOUNT_MANAGER_RESPONSE_KEY,
+ new AccountManagerResponse(chooseResponse));
+ mActivity.startActivity(intent);
+ // the result will arrive via the IAccountManagerResponse
+ } else {
+ // send result since we can't prompt to select an account
+ Bundle result = new Bundle();
+ result.putString(Constants.ACCOUNTS_KEY, null);
+ try {
+ mResponse.onResult(result);
+ } catch (RemoteException e) {
+ // this will never happen
+ }
+ // we are done
}
- };
- // have many accounts, launch the chooser
- Intent intent = new Intent();
- intent.setClassName("android",
- "android.accounts.ChooseAccountActivity");
- intent.putExtra(Constants.ACCOUNTS_KEY, accounts);
- intent.putExtra(Constants.ACCOUNT_MANAGER_RESPONSE_KEY,
- new AccountManagerResponse(chooseResponse));
- mActivity.startActivity(intent);
- // the result will arrive via the IAccountManagerResponse
- } else {
- // send result since we can't prompt to select an account
- Bundle result = new Bundle();
- result.putString(Constants.ACCOUNTS_KEY, null);
- try {
- mResponse.onResult(result);
- } catch (RemoteException e) {
- // this will never happen
}
- // we are done
- }
- }
- }}, mHandler);
+ }}, mHandler);
}
@@ -915,7 +749,7 @@
// or to cause this to be canceled if mFuture isn't set.
// Once this is done then getAuthTokenByFeatures can be changed to return a Future2.
- public void run(Future2 future) {
+ public void run(AccountManagerFuture<Bundle> future) {
try {
set(future.get());
} catch (InterruptedException e) {
@@ -932,7 +766,7 @@
final String accountType, final String authTokenType, final String[] features,
final Activity activityForPrompting, final Bundle addAccountOptions,
final Bundle loginOptions,
- final Future2Callback callback, final Handler handler) {
+ final AccountManagerCallback<Bundle> callback, final Handler handler) {
if (accountType == null) throw new IllegalArgumentException("account type is null");
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
new GetAuthTokenByTypeAndFeaturesTask(accountType, authTokenType, features,
@@ -942,13 +776,6 @@
private final HashMap<OnAccountsUpdatedListener, Handler> mAccountsUpdatedListeners =
Maps.newHashMap();
- // These variable are only used from the LOGIN_ACCOUNTS_CHANGED_ACTION BroadcastReceiver
- // and its getAccounts() callback which are both invoked only on the main thread. As a
- // result we don't need to protect against concurrent accesses and any changes are guaranteed
- // to be visible when used. Basically, these two variables are thread-confined.
- private Future1<Account[]> mAccountsLookupFuture = null;
- private boolean mAccountLookupPending = false;
-
/**
* BroadcastReceiver that listens for the LOGIN_ACCOUNTS_CHANGED_ACTION intent
* so that it can read the updated list of accounts and send them to the listener
@@ -956,58 +783,14 @@
*/
private final BroadcastReceiver mAccountsChangedBroadcastReceiver = new BroadcastReceiver() {
public void onReceive(final Context context, final Intent intent) {
- if (mAccountsLookupFuture != null) {
- // an accounts lookup is already in progress,
- // don't bother starting another request
- mAccountLookupPending = true;
- return;
- }
- // initiate a read of the accounts
- mAccountsLookupFuture = getAccounts(new Future1Callback<Account[]>() {
- public void run(Future1<Account[]> future) {
- // clear the future so that future receives will try the lookup again
- mAccountsLookupFuture = null;
-
- // get the accounts array
- Account[] accounts;
- try {
- accounts = future.getResult();
- } catch (OperationCanceledException e) {
- // this should never happen, but if it does pretend we got another
- // accounts changed broadcast
- if (Config.LOGD) {
- Log.d(TAG, "the accounts lookup for listener notifications was "
- + "canceled, try again by simulating the receipt of "
- + "a LOGIN_ACCOUNTS_CHANGED_ACTION broadcast");
- }
- onReceive(context, intent);
- return;
- }
-
- // send the result to the listeners
- synchronized (mAccountsUpdatedListeners) {
- for (Map.Entry<OnAccountsUpdatedListener, Handler> entry :
- mAccountsUpdatedListeners.entrySet()) {
- Account[] accountsCopy = new Account[accounts.length];
- // send the listeners a copy to make sure that one doesn't
- // change what another sees
- System.arraycopy(accounts, 0, accountsCopy, 0, accountsCopy.length);
- postToHandler(entry.getValue(), entry.getKey(), accountsCopy);
- }
- }
-
- // If mAccountLookupPending was set when the account lookup finished it
- // means that we had previously ignored a LOGIN_ACCOUNTS_CHANGED_ACTION
- // intent because a lookup was already in progress. Now that we are done
- // with this lookup and notification pretend that another intent
- // was received by calling onReceive() directly.
- if (mAccountLookupPending) {
- mAccountLookupPending = false;
- onReceive(context, intent);
- return;
- }
+ final Account[] accounts = getAccounts();
+ // send the result to the listeners
+ synchronized (mAccountsUpdatedListeners) {
+ for (Map.Entry<OnAccountsUpdatedListener, Handler> entry :
+ mAccountsUpdatedListeners.entrySet()) {
+ postToHandler(entry.getValue(), entry.getKey(), accounts);
}
- }, mMainHandler);
+ }
}
};
@@ -1045,15 +828,7 @@
}
if (updateImmediately) {
- getAccounts(new Future1Callback<Account[]>() {
- public void run(Future1<Account[]> future) {
- try {
- listener.onAccountsUpdated(future.getResult());
- } catch (OperationCanceledException e) {
- // ignore
- }
- }
- }, handler);
+ postToHandler(handler, listener, getAccounts());
}
}
diff --git a/core/java/android/accounts/Future2Callback.java b/core/java/android/accounts/AccountManagerCallback.java
similarity index 87%
rename from core/java/android/accounts/Future2Callback.java
rename to core/java/android/accounts/AccountManagerCallback.java
index 7ef0c947..4aa7169 100644
--- a/core/java/android/accounts/Future2Callback.java
+++ b/core/java/android/accounts/AccountManagerCallback.java
@@ -15,6 +15,6 @@
*/
package android.accounts;
-public interface Future2Callback {
- void run(Future2 future);
+public interface AccountManagerCallback<V> {
+ void run(AccountManagerFuture<V> future);
}
\ No newline at end of file
diff --git a/core/java/android/accounts/AccountManagerFuture.java b/core/java/android/accounts/AccountManagerFuture.java
new file mode 100644
index 0000000..9939398
--- /dev/null
+++ b/core/java/android/accounts/AccountManagerFuture.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.accounts;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+import java.io.IOException;
+
+/**
+ * An extension of {@link java.util.concurrent.Future} that provides wrappers for {@link #get()}
+ * that handle the various
+ * exceptions that {@link #get()} may return and rethrows them as exceptions specific to
+ * {@link android.accounts.AccountManager}.
+ */
+public interface AccountManagerFuture<V> extends Future<V> {
+ /**
+ * Wrapper for {@link java.util.concurrent.Future#get()}. If the get() throws
+ * {@link InterruptedException} then the
+ * {@link AccountManagerFuture} is canceled and
+ * {@link android.accounts.OperationCanceledException} is thrown.
+ * @return the {@link android.os.Bundle} that is returned by get()
+ * @throws android.accounts.OperationCanceledException if get() throws the unchecked
+ * CancellationException
+ * or if the Future was interrupted.
+ */
+ V getResult() throws OperationCanceledException, IOException, AuthenticatorException;
+
+ /**
+ * Wrapper for {@link java.util.concurrent.Future#get()}. If the get() throws
+ * {@link InterruptedException} then the
+ * {@link AccountManagerFuture} is canceled and
+ * {@link android.accounts.OperationCanceledException} is thrown.
+ * @param timeout the maximum time to wait
+ * @param unit the time unit of the timeout argument
+ * @return the {@link android.os.Bundle} that is returned by
+ * {@link java.util.concurrent.Future#get()}
+ * @throws android.accounts.OperationCanceledException if get() throws the unchecked
+ * {@link java.util.concurrent.CancellationException} or if the {@link AccountManagerFuture}
+ * was interrupted.
+ */
+ V getResult(long timeout, TimeUnit unit)
+ throws OperationCanceledException, IOException, AuthenticatorException;
+
+ @Deprecated
+ V get() throws InterruptedException, ExecutionException;
+
+ @Deprecated
+ V get(long timeout, TimeUnit unit)
+ throws InterruptedException, ExecutionException, TimeoutException;
+}
\ No newline at end of file
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 0c941be..140c814 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -214,10 +214,48 @@
long identityToken = clearCallingIdentity();
try {
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
- Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_PASSWORD},
- ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
- new String[]{account.mName, account.mType}, null, null, null);
+ return readPasswordFromDatabase(account);
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
+ }
+
+ private String readPasswordFromDatabase(Account account) {
+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_PASSWORD},
+ ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
+ new String[]{account.name, account.type}, null, null, null);
+ try {
+ if (cursor.moveToNext()) {
+ return cursor.getString(0);
+ }
+ return null;
+ } finally {
+ cursor.close();
+ }
+ }
+
+ public String getUserData(Account account, String key) {
+ checkAuthenticateAccountsPermission(account);
+ long identityToken = clearCallingIdentity();
+ try {
+ return readUserDataFromDatabase(account, key);
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
+ }
+
+ private String readUserDataFromDatabase(Account account, String key) {
+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ db.beginTransaction();
+ try {
+ long accountId = getAccountId(db, account);
+ if (accountId < 0) {
+ return null;
+ }
+ Cursor cursor = db.query(TABLE_EXTRAS, new String[]{EXTRAS_VALUE},
+ EXTRAS_ACCOUNTS_ID + "=" + accountId + " AND " + EXTRAS_KEY + "=?",
+ new String[]{key}, null, null, null);
try {
if (cursor.moveToNext()) {
return cursor.getString(0);
@@ -227,37 +265,7 @@
cursor.close();
}
} finally {
- restoreCallingIdentity(identityToken);
- }
- }
-
- public String getUserData(Account account, String key) {
- checkAuthenticateAccountsPermission(account);
- long identityToken = clearCallingIdentity();
- try {
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
- db.beginTransaction();
- try {
- long accountId = getAccountId(db, account);
- if (accountId < 0) {
- return null;
- }
- Cursor cursor = db.query(TABLE_EXTRAS, new String[]{EXTRAS_VALUE},
- EXTRAS_ACCOUNTS_ID + "=" + accountId + " AND " + EXTRAS_KEY + "=?",
- new String[]{key}, null, null, null);
- try {
- if (cursor.moveToNext()) {
- return cursor.getString(0);
- }
- return null;
- } finally {
- cursor.close();
- }
- } finally {
- db.endTransaction();
- }
- } finally {
- restoreCallingIdentity(identityToken);
+ db.endTransaction();
}
}
@@ -280,39 +288,23 @@
}
}
- public Account[] getAccounts() {
- checkReadAccountsPermission();
- long identityToken = clearCallingIdentity();
- try {
- return getAccountsByType(null);
- } finally {
- restoreCallingIdentity(identityToken);
- }
- }
-
public Account[] getAccountsByType(String accountType) {
- checkReadAccountsPermission();
- long identityToken = clearCallingIdentity();
- try {
- SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
- final String selection = accountType == null ? null : (ACCOUNTS_TYPE + "=?");
- final String[] selectionArgs = accountType == null ? null : new String[]{accountType};
- Cursor cursor = db.query(TABLE_ACCOUNTS, ACCOUNT_NAME_TYPE_PROJECTION,
- selection, selectionArgs, null, null, null);
- try {
- int i = 0;
- Account[] accounts = new Account[cursor.getCount()];
- while (cursor.moveToNext()) {
- accounts[i] = new Account(cursor.getString(1), cursor.getString(2));
- i++;
- }
- return accounts;
- } finally {
- cursor.close();
+ final String selection = accountType == null ? null : (ACCOUNTS_TYPE + "=?");
+ final String[] selectionArgs = accountType == null ? null : new String[]{accountType};
+ Cursor cursor = db.query(TABLE_ACCOUNTS, ACCOUNT_NAME_TYPE_PROJECTION,
+ selection, selectionArgs, null, null, null);
+ try {
+ int i = 0;
+ Account[] accounts = new Account[cursor.getCount()];
+ while (cursor.moveToNext()) {
+ accounts[i] = new Account(cursor.getString(1), cursor.getString(2));
+ i++;
}
+ return accounts;
} finally {
- restoreCallingIdentity(identityToken);
+ cursor.close();
}
}
@@ -322,43 +314,47 @@
// fails if the account already exists
long identityToken = clearCallingIdentity();
try {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- db.beginTransaction();
- try {
- long numMatches = DatabaseUtils.longForQuery(db,
- "select count(*) from " + TABLE_ACCOUNTS
- + " WHERE " + ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
- new String[]{account.mName, account.mType});
- if (numMatches > 0) {
- return false;
- }
- ContentValues values = new ContentValues();
- values.put(ACCOUNTS_NAME, account.mName);
- values.put(ACCOUNTS_TYPE, account.mType);
- values.put(ACCOUNTS_PASSWORD, password);
- long accountId = db.insert(TABLE_ACCOUNTS, ACCOUNTS_NAME, values);
- if (accountId < 0) {
- return false;
- }
- if (extras != null) {
- for (String key : extras.keySet()) {
- final String value = extras.getString(key);
- if (insertExtra(db, accountId, key, value) < 0) {
- return false;
- }
- }
- }
- db.setTransactionSuccessful();
- sendAccountsChangedBroadcast();
- return true;
- } finally {
- db.endTransaction();
- }
+ return insertAccountIntoDatabase(account, password, extras);
} finally {
restoreCallingIdentity(identityToken);
}
}
+ private boolean insertAccountIntoDatabase(Account account, String password, Bundle extras) {
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ long numMatches = DatabaseUtils.longForQuery(db,
+ "select count(*) from " + TABLE_ACCOUNTS
+ + " WHERE " + ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
+ new String[]{account.name, account.type});
+ if (numMatches > 0) {
+ return false;
+ }
+ ContentValues values = new ContentValues();
+ values.put(ACCOUNTS_NAME, account.name);
+ values.put(ACCOUNTS_TYPE, account.type);
+ values.put(ACCOUNTS_PASSWORD, password);
+ long accountId = db.insert(TABLE_ACCOUNTS, ACCOUNTS_NAME, values);
+ if (accountId < 0) {
+ return false;
+ }
+ if (extras != null) {
+ for (String key : extras.keySet()) {
+ final String value = extras.getString(key);
+ if (insertExtra(db, accountId, key, value) < 0) {
+ return false;
+ }
+ }
+ }
+ db.setTransactionSuccessful();
+ sendAccountsChangedBroadcast();
+ return true;
+ } finally {
+ db.endTransaction();
+ }
+ }
+
private long insertExtra(SQLiteDatabase db, long accountId, String key, String value) {
ContentValues values = new ContentValues();
values.put(EXTRAS_KEY, key);
@@ -367,19 +363,61 @@
return db.insert(TABLE_EXTRAS, EXTRAS_KEY, values);
}
- public void removeAccount(Account account) {
+ public void removeAccount(IAccountManagerResponse response, Account account) {
checkManageAccountsPermission();
long identityToken = clearCallingIdentity();
try {
- final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
- new String[]{account.mName, account.mType});
- sendAccountsChangedBroadcast();
+ new RemoveAccountSession(response, account).bind();
} finally {
restoreCallingIdentity(identityToken);
}
}
+ private class RemoveAccountSession extends Session {
+ final Account mAccount;
+ public RemoveAccountSession(IAccountManagerResponse response, Account account) {
+ super(response, account.type, false /* expectActivityLaunch */);
+ mAccount = account;
+ }
+
+ protected String toDebugString(long now) {
+ return super.toDebugString(now) + ", removeAccount"
+ + ", account " + mAccount;
+ }
+
+ public void run() throws RemoteException {
+ mAuthenticator.getAccountRemovalAllowed(this, mAccount);
+ }
+
+ public void onResult(Bundle result) {
+ if (result != null && result.containsKey(Constants.BOOLEAN_RESULT_KEY)
+ && !result.containsKey(Constants.INTENT_KEY)) {
+ final boolean removalAllowed = result.getBoolean(Constants.BOOLEAN_RESULT_KEY);
+ if (removalAllowed) {
+ removeAccount(mAccount);
+ }
+ IAccountManagerResponse response = getResponseAndClose();
+ if (response != null) {
+ Bundle result2 = new Bundle();
+ result2.putBoolean(Constants.BOOLEAN_RESULT_KEY, removalAllowed);
+ try {
+ response.onResult(result2);
+ } catch (RemoteException e) {
+ // ignore
+ }
+ }
+ }
+ super.onResult(result);
+ }
+ }
+
+ private void removeAccount(Account account) {
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
+ new String[]{account.name, account.type});
+ sendAccountsChangedBroadcast();
+ }
+
public void invalidateAuthToken(String accountType, String authToken) {
checkManageAccountsPermission();
long identityToken = clearCallingIdentity();
@@ -398,6 +436,9 @@
}
private void invalidateAuthToken(SQLiteDatabase db, String accountType, String authToken) {
+ if (authToken == null || accountType == null) {
+ return;
+ }
Cursor cursor = db.rawQuery(
"SELECT " + TABLE_AUTHTOKENS + "." + AUTHTOKENS_ID
+ ", " + TABLE_ACCOUNTS + "." + ACCOUNTS_NAME
@@ -488,7 +529,7 @@
values.put(ACCOUNTS_PASSWORD, password);
mOpenHelper.getWritableDatabase().update(TABLE_ACCOUNTS, values,
ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
- new String[]{account.mName, account.mType});
+ new String[]{account.name, account.type});
sendAccountsChangedBroadcast();
} finally {
restoreCallingIdentity(identityToken);
@@ -509,40 +550,58 @@
}
}
+ private void sendResult(IAccountManagerResponse response, Bundle bundle) {
+ if (response != null) {
+ try {
+ response.onResult(bundle);
+ } catch (RemoteException e) {
+ // if the caller is dead then there is no one to care about remote
+ // exceptions
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "failure while notifying response", e);
+ }
+ }
+ }
+ }
+
public void setUserData(Account account, String key, String value) {
checkAuthenticateAccountsPermission(account);
long identityToken = clearCallingIdentity();
try {
- SQLiteDatabase db = mOpenHelper.getWritableDatabase();
- db.beginTransaction();
- try {
- long accountId = getAccountId(db, account);
- if (accountId < 0) {
- return;
- }
- long extrasId = getExtrasId(db, accountId, key);
- if (extrasId < 0 ) {
- extrasId = insertExtra(db, accountId, key, value);
- if (extrasId < 0) {
- return;
- }
- } else {
- ContentValues values = new ContentValues();
- values.put(EXTRAS_VALUE, value);
- if (1 != db.update(TABLE_EXTRAS, values, EXTRAS_ID + "=" + extrasId, null)) {
- return;
- }
-
- }
- db.setTransactionSuccessful();
- } finally {
- db.endTransaction();
- }
+ writeUserdataIntoDatabase(account, key, value);
} finally {
restoreCallingIdentity(identityToken);
}
}
+ private void writeUserdataIntoDatabase(Account account, String key, String value) {
+ SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ db.beginTransaction();
+ try {
+ long accountId = getAccountId(db, account);
+ if (accountId < 0) {
+ return;
+ }
+ long extrasId = getExtrasId(db, accountId, key);
+ if (extrasId < 0 ) {
+ extrasId = insertExtra(db, accountId, key, value);
+ if (extrasId < 0) {
+ return;
+ }
+ } else {
+ ContentValues values = new ContentValues();
+ values.put(EXTRAS_VALUE, value);
+ if (1 != db.update(TABLE_EXTRAS, values, EXTRAS_ID + "=" + extrasId, null)) {
+ return;
+ }
+
+ }
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ }
+
private void onResult(IAccountManagerResponse response, Bundle result) {
try {
response.onResult(result);
@@ -571,14 +630,14 @@
if (authToken != null) {
Bundle result = new Bundle();
result.putString(Constants.AUTHTOKEN_KEY, authToken);
- result.putString(Constants.ACCOUNT_NAME_KEY, account.mName);
- result.putString(Constants.ACCOUNT_TYPE_KEY, account.mType);
+ result.putString(Constants.ACCOUNT_NAME_KEY, account.name);
+ result.putString(Constants.ACCOUNT_TYPE_KEY, account.type);
onResult(response, result);
return;
}
}
- new Session(response, account.mType, expectActivityLaunch) {
+ new Session(response, account.type, expectActivityLaunch) {
protected String toDebugString(long now) {
if (loginOptions != null) loginOptions.keySet();
return super.toDebugString(now) + ", getAuthToken"
@@ -651,7 +710,7 @@
mContext.getText(R.string.permission_request_notification_subtitle);
n.setLatestEventInfo(mContext,
mContext.getText(R.string.permission_request_notification_title),
- String.format(subtitleFormatString.toString(), account.mName),
+ String.format(subtitleFormatString.toString(), account.name),
PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT));
((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
.notify(getCredentialPermissionNotificationId(account, authTokenType, uid), n);
@@ -661,9 +720,9 @@
AccountAuthenticatorResponse response, String authTokenType, String authTokenLabel) {
RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo =
mAuthenticatorCache.getServiceInfo(
- AuthenticatorDescription.newKey(account.mType));
+ AuthenticatorDescription.newKey(account.type));
if (serviceInfo == null) {
- throw new IllegalArgumentException("unknown account type: " + account.mType);
+ throw new IllegalArgumentException("unknown account type: " + account.type);
}
final Context authContext;
@@ -671,7 +730,7 @@
authContext = mContext.createPackageContext(
serviceInfo.type.packageName, 0);
} catch (PackageManager.NameNotFoundException e) {
- throw new IllegalArgumentException("unknown account type: " + account.mType);
+ throw new IllegalArgumentException("unknown account type: " + account.type);
}
Intent intent = new Intent(mContext, GrantCredentialsPermissionActivity.class);
@@ -750,7 +809,7 @@
checkManageAccountsPermission();
long identityToken = clearCallingIdentity();
try {
- new Session(response, account.mType, expectActivityLaunch) {
+ new Session(response, account.type, expectActivityLaunch) {
public void run() throws RemoteException {
mAuthenticator.confirmCredentials(this, account);
}
@@ -769,7 +828,7 @@
checkManageAccountsPermission();
long identityToken = clearCallingIdentity();
try {
- new Session(response, account.mType, false /* expectActivityLaunch */) {
+ new Session(response, account.type, false /* expectActivityLaunch */) {
public void run() throws RemoteException {
mAuthenticator.confirmPassword(this, account, password);
}
@@ -789,7 +848,7 @@
checkManageAccountsPermission();
long identityToken = clearCallingIdentity();
try {
- new Session(response, account.mType, expectActivityLaunch) {
+ new Session(response, account.type, expectActivityLaunch) {
public void run() throws RemoteException {
mAuthenticator.updateCredentials(this, account, authTokenType, loginOptions);
}
@@ -898,10 +957,21 @@
+ ", " + (mFeatures != null ? TextUtils.join(",", mFeatures) : null);
}
}
- public void getAccountsByTypeAndFeatures(IAccountManagerResponse response,
+
+ public Account[] getAccounts(String type) {
+ checkReadAccountsPermission();
+ long identityToken = clearCallingIdentity();
+ try {
+ return getAccountsByType(type);
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
+ }
+
+ public void getAccountsByFeatures(IAccountManagerResponse response,
String type, String[] features) {
checkReadAccountsPermission();
- if (type == null) {
+ if (features != null && type == null) {
if (response != null) {
try {
response.onError(Constants.ERROR_CODE_BAD_ARGUMENTS, "type is null");
@@ -913,6 +983,10 @@
}
long identityToken = clearCallingIdentity();
try {
+ if (features == null || features.length == 0) {
+ getAccountsByType(type);
+ return;
+ }
new GetAccountsByTypeAndFeatureSession(response, type, features).bind();
} finally {
restoreCallingIdentity(identityToken);
@@ -925,7 +999,7 @@
private long getAccountId(SQLiteDatabase db, Account account) {
Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_ID},
- "name=? AND type=?", new String[]{account.mName, account.mType}, null, null, null);
+ "name=? AND type=?", new String[]{account.name, account.type}, null, null, null);
try {
if (cursor.moveToNext()) {
return cursor.getLong(0);
@@ -1401,7 +1475,7 @@
}
private boolean permissionIsGranted(Account account, String authTokenType, int callerUid) {
- final boolean fromAuthenticator = hasAuthenticatorUid(account.mType, callerUid);
+ final boolean fromAuthenticator = hasAuthenticatorUid(account.type, callerUid);
final boolean hasExplicitGrants = hasExplicitlyGrantedPermission(account, authTokenType);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "checkGrantsOrCallingUidAgainstAuthenticator: caller uid "
@@ -1416,7 +1490,9 @@
for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo :
mAuthenticatorCache.getAllServices()) {
if (serviceInfo.type.type.equals(accountType)) {
- return serviceInfo.uid == callingUid;
+ return (serviceInfo.uid == callingUid) ||
+ (mContext.getPackageManager().checkSignatures(serviceInfo.uid, callingUid)
+ == PackageManager.SIGNATURE_MATCH);
}
}
return false;
@@ -1428,7 +1504,7 @@
}
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
String[] args = {String.valueOf(Binder.getCallingUid()), authTokenType,
- account.mName, account.mType};
+ account.name, account.type};
final boolean permissionGranted =
DatabaseUtils.longForQuery(db, COUNT_OF_MATCHING_GRANTS, args) != 0;
if (!permissionGranted && isDebuggableMonkeyBuild) {
@@ -1444,7 +1520,7 @@
private void checkCallingUidAgainstAuthenticator(Account account) {
final int uid = Binder.getCallingUid();
- if (!hasAuthenticatorUid(account.mType, uid)) {
+ if (!hasAuthenticatorUid(account.type, uid)) {
String msg = "caller uid " + uid + " is different than the authenticator's uid";
Log.w(TAG, msg);
throw new SecurityException(msg);
diff --git a/core/java/android/accounts/ChooseAccountActivity.java b/core/java/android/accounts/ChooseAccountActivity.java
index 83377f3..bd6f205 100644
--- a/core/java/android/accounts/ChooseAccountActivity.java
+++ b/core/java/android/accounts/ChooseAccountActivity.java
@@ -45,7 +45,7 @@
String[] mAccountNames = new String[mAccounts.length];
for (int i = 0; i < mAccounts.length; i++) {
- mAccountNames[i] = ((Account) mAccounts[i]).mName;
+ mAccountNames[i] = ((Account) mAccounts[i]).name;
}
// Use an existing ListAdapter that will map an array
@@ -59,8 +59,8 @@
Account account = (Account) mAccounts[position];
Log.d(TAG, "selected account " + account);
Bundle bundle = new Bundle();
- bundle.putString(Constants.ACCOUNT_NAME_KEY, account.mName);
- bundle.putString(Constants.ACCOUNT_TYPE_KEY, account.mType);
+ bundle.putString(Constants.ACCOUNT_NAME_KEY, account.name);
+ bundle.putString(Constants.ACCOUNT_TYPE_KEY, account.type);
mResult = bundle;
finish();
}
diff --git a/core/java/android/accounts/Constants.java b/core/java/android/accounts/Constants.java
index da8173f..8736f41 100644
--- a/core/java/android/accounts/Constants.java
+++ b/core/java/android/accounts/Constants.java
@@ -31,6 +31,7 @@
public static final String AUTHENTICATOR_TYPES_KEY = "authenticator_types";
public static final String USERDATA_KEY = "userdata";
public static final String AUTHTOKEN_KEY = "authtoken";
+ public static final String PASSWORD_KEY = "password";
public static final String ACCOUNT_NAME_KEY = "authAccount";
public static final String ACCOUNT_TYPE_KEY = "accountType";
public static final String ERROR_CODE_KEY = "errorCode";
diff --git a/core/java/android/accounts/Future1.java b/core/java/android/accounts/Future1.java
deleted file mode 100644
index 386cb6e..0000000
--- a/core/java/android/accounts/Future1.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.accounts;
-
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
-/**
- * An extension of {@link Future} that provides wrappers for {@link #get()} that handle the various
- * exceptions that {@link #get()} may return and rethrows them as exceptions specific to
- * {@link AccountManager}.
- */
-public interface Future1<V> extends Future<V> {
- /**
- * Wrapper for {@link Future#get()}. If the get() throws {@link InterruptedException} then the
- * {@link Future1} is canceled and {@link OperationCanceledException} is thrown.
- * @return the {@link android.os.Bundle} that is returned by get()
- * @throws OperationCanceledException if get() throws the unchecked CancellationException
- * or if the Future was interrupted.
- */
- V getResult() throws OperationCanceledException;
-
- /**
- * Wrapper for {@link Future#get()}. If the get() throws {@link InterruptedException} then the
- * {@link Future1} is canceled and {@link OperationCanceledException} is thrown.
- * @param timeout the maximum time to wait
- * @param unit the time unit of the timeout argument
- * @return the {@link android.os.Bundle} that is returned by {@link Future#get()}
- * @throws OperationCanceledException if get() throws the unchecked
- * {@link java.util.concurrent.CancellationException} or if the {@link Future1} was interrupted.
- */
- V getResult(long timeout, TimeUnit unit) throws OperationCanceledException;
-}
\ No newline at end of file
diff --git a/core/java/android/accounts/Future1Callback.java b/core/java/android/accounts/Future1Callback.java
deleted file mode 100644
index 886671ba..0000000
--- a/core/java/android/accounts/Future1Callback.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.accounts;
-
-public interface Future1Callback<V> {
- void run(Future1<V> future);
-}
diff --git a/core/java/android/accounts/Future2.java b/core/java/android/accounts/Future2.java
deleted file mode 100644
index b2ea84f..0000000
--- a/core/java/android/accounts/Future2.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.accounts;
-
-import android.os.Bundle;
-
-import java.io.IOException;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-
-/**
- * An extension of {@link Future} that provides wrappers for {@link #get()} that handle the various
- * exceptions that {@link #get()} may return and rethrows them as exceptions specific to
- * {@link AccountManager}.
- */
-public interface Future2 extends Future<Bundle> {
- /**
- * Wrapper for {@link Future#get()}. If the get() throws {@link InterruptedException} then the
- * {@link Future2} is canceled and {@link OperationCanceledException} is thrown.
- * @return the {@link android.os.Bundle} that is returned by {@link Future#get()}
- * @throws OperationCanceledException if get() throws the unchecked
- * {@link java.util.concurrent.CancellationException} or if the {@link Future2} was interrupted.
- * @throws IOException if the request was unable to complete due to a network error
- * @throws AuthenticatorException if there was an error communicating with the
- * {@link AbstractAccountAuthenticator}.
- */
- Bundle getResult()
- throws OperationCanceledException, IOException, AuthenticatorException;
-
- /**
- * Wrapper for {@link Future#get()}. If the get() throws {@link InterruptedException} then the
- * {@link Future2} is canceled and {@link OperationCanceledException} is thrown.
- * @param timeout the maximum time to wait
- * @param unit the time unit of the timeout argument
- * @return the {@link android.os.Bundle} that is returned by {@link Future#get()}
- * @throws OperationCanceledException if get() throws the unchecked
- * {@link java.util.concurrent.CancellationException} or if the {@link Future2} was interrupted.
- * @throws IOException if the request was unable to complete due to a network error
- * @throws AuthenticatorException if there was an error communicating with the
- * {@link AbstractAccountAuthenticator}.
- */
- Bundle getResult(long timeout, TimeUnit unit)
- throws OperationCanceledException, IOException, AuthenticatorException;
-}
diff --git a/core/java/android/accounts/GrantCredentialsPermissionActivity.java b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
index f92d43f..e06afb4 100644
--- a/core/java/android/accounts/GrantCredentialsPermissionActivity.java
+++ b/core/java/android/accounts/GrantCredentialsPermissionActivity.java
@@ -63,12 +63,12 @@
CharSequence grantCredentialsPermissionFormat = getResources().getText(
R.string.grant_credentials_permission_message_desc);
messageView.setText(String.format(grantCredentialsPermissionFormat.toString(),
- mAccount.mName, accountTypeLabel));
+ mAccount.name, accountTypeLabel));
} else {
CharSequence grantCredentialsPermissionFormat = getResources().getText(
R.string.grant_credentials_permission_message_with_authtokenlabel_desc);
messageView.setText(String.format(grantCredentialsPermissionFormat.toString(),
- authTokenLabel, mAccount.mName, accountTypeLabel));
+ authTokenLabel, mAccount.name, accountTypeLabel));
}
String[] packageLabels = new String[packages.length];
diff --git a/core/java/android/accounts/IAccountAuthenticator.aidl b/core/java/android/accounts/IAccountAuthenticator.aidl
index 7d4de39..48f053c 100644
--- a/core/java/android/accounts/IAccountAuthenticator.aidl
+++ b/core/java/android/accounts/IAccountAuthenticator.aidl
@@ -70,4 +70,9 @@
*/
void hasFeatures(in IAccountAuthenticatorResponse response, in Account account,
in String[] features);
+
+ /**
+ * Gets whether or not the account is allowed to be removed.
+ */
+ void getAccountRemovalAllowed(in IAccountAuthenticatorResponse response, in Account account);
}
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index 15ab4e8..411952b 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -21,6 +21,7 @@
import android.accounts.AuthenticatorDescription;
import android.os.Bundle;
+
/**
* Central application service that provides account management.
* @hide
@@ -29,10 +30,10 @@
String getPassword(in Account account);
String getUserData(in Account account, String key);
AuthenticatorDescription[] getAuthenticatorTypes();
- Account[] getAccounts();
- Account[] getAccountsByType(String accountType);
+ Account[] getAccounts(String accountType);
+ void getAccountsByFeatures(in IAccountManagerResponse response, String accountType, in String[] features);
boolean addAccount(in Account account, String password, in Bundle extras);
- void removeAccount(in Account account);
+ void removeAccount(in IAccountManagerResponse response, in Account account);
void invalidateAuthToken(String accountType, String authToken);
String peekAuthToken(in Account account, String authTokenType);
void setAuthToken(in Account account, String authTokenType, String authToken);
@@ -52,8 +53,6 @@
boolean expectActivityLaunch);
void confirmCredentials(in IAccountManagerResponse response, in Account account,
boolean expectActivityLaunch);
- void getAccountsByTypeAndFeatures(in IAccountManagerResponse response, String accountType,
- in String[] features);
/*
* @deprecated
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 2f79fe9..c05e042 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -2536,6 +2536,25 @@
}
/**
+ * Similar to {@link #startSearch}, but actually fires off the search query after invoking
+ * the search dialog. Made available for testing purposes.
+ *
+ * @param query The query to trigger. If empty, the request will be ignored.
+ * @param appSearchData An application can insert application-specific
+ * context here, in order to improve quality or specificity of its own
+ * searches. This data will be returned with SEARCH intent(s). Null if
+ * no extra data is required.
+ * @param globalSearch If false, this will only launch the search that has been specifically
+ * defined by the application (which is usually defined as a local search). If no default
+ * search is defined in the current application or activity, no search will be launched.
+ * If true, this will always launch a platform-global (e.g. web-based) search instead.
+ */
+ public void triggerSearch(String query, Bundle appSearchData, boolean globalSearch) {
+ ensureSearchManager();
+ mSearchManager.triggerSearch(query, getComponentName(), appSearchData, globalSearch);
+ }
+
+ /**
* Request that key events come to this activity. Use this if your
* activity has no views with focus, but the activity still wants
* a chance to process key events.
@@ -3256,7 +3275,7 @@
throw new IllegalArgumentException("no ident");
}
}
- mSearchManager.setIdent(ident);
+ mSearchManager.setIdent(ident, getComponentName());
}
@Override
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index a74fbe4..7c0d1d3 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -22,8 +22,8 @@
import org.xmlpull.v1.XmlPullParserException;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.IBluetoothDevice;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.IBluetooth;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -158,8 +158,6 @@
private static ConnectivityManager sConnectivityManager;
private static WifiManager sWifiManager;
private static LocationManager sLocationManager;
- private static boolean sIsBluetoothDeviceCached = false;
- private static BluetoothDevice sBluetoothDevice;
private static final HashMap<File, SharedPreferencesImpl> sSharedPrefs =
new HashMap<File, SharedPreferencesImpl>();
@@ -184,6 +182,8 @@
private StatusBarManager mStatusBarManager = null;
private TelephonyManager mTelephonyManager = null;
private ClipboardManager mClipboardManager = null;
+ private boolean mIsBluetoothAdapterCached = false;
+ private BluetoothAdapter mBluetoothAdapter;
private boolean mRestricted;
private final Object mSync = new Object();
@@ -830,7 +830,7 @@
} else if (SENSOR_SERVICE.equals(name)) {
return getSensorManager();
} else if (BLUETOOTH_SERVICE.equals(name)) {
- return getBluetoothDevice();
+ return getBluetoothAdapter();
} else if (VIBRATOR_SERVICE.equals(name)) {
return getVibrator();
} else if (STATUS_BAR_SERVICE.equals(name)) {
@@ -980,21 +980,16 @@
return mSearchManager;
}
- private BluetoothDevice getBluetoothDevice() {
- if (sIsBluetoothDeviceCached) {
- return sBluetoothDevice;
- }
- synchronized (sSync) {
+ private synchronized BluetoothAdapter getBluetoothAdapter() {
+ if (!mIsBluetoothAdapterCached) {
+ mIsBluetoothAdapterCached = true;
IBinder b = ServiceManager.getService(BLUETOOTH_SERVICE);
- if (b == null) {
- sBluetoothDevice = null;
- } else {
- IBluetoothDevice service = IBluetoothDevice.Stub.asInterface(b);
- sBluetoothDevice = new BluetoothDevice(service);
+ if (b != null) {
+ IBluetooth service = IBluetooth.Stub.asInterface(b);
+ mBluetoothAdapter = new BluetoothAdapter(service);
}
- sIsBluetoothDeviceCached = true;
}
- return sBluetoothDevice;
+ return mBluetoothAdapter;
}
private SensorManager getSensorManager() {
diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl
index bd72544..ed5dd3d 100644
--- a/core/java/android/app/ISearchManager.aidl
+++ b/core/java/android/app/ISearchManager.aidl
@@ -36,6 +36,17 @@
boolean globalSearch,
ISearchManagerCallback searchManagerCallback,
int ident);
+
+ void triggerSearch(in String query,
+ in ComponentName launchActivity,
+ in Bundle appSearchData,
+ ISearchManagerCallback searchManagerCallback,
+ boolean globalSearch,
+ int ident);
+
void stopSearch();
+
+
boolean isVisible();
+
}
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index b75bec2..8a9cca7 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -1120,7 +1120,7 @@
/**
* Launch a search for the text in the query text field.
*/
- protected void launchQuerySearch() {
+ public void launchQuerySearch() {
launchQuerySearch(KeyEvent.KEYCODE_UNKNOWN, null);
}
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 97d46f8..15a277c 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -29,6 +29,7 @@
import android.server.search.SearchableInfo;
import android.util.Log;
import android.view.KeyEvent;
+import android.text.TextUtils;
import java.util.List;
@@ -1622,7 +1623,17 @@
private final Context mContext;
+ /**
+ * compact representation of the activity associated with this search manager so
+ * we can say who we are when starting search. the search managerservice, in turn,
+ * uses this to properly handle the back stack.
+ */
private int mIdent;
+
+ /**
+ * The package associated with this seach manager.
+ */
+ private String mAssociatedPackage;
// package private since they are used by the inner class SearchManagerCallback
/* package */ final Handler mHandler;
@@ -1642,11 +1653,15 @@
return mIdent != 0;
}
- /*package*/ void setIdent(int ident) {
+ /*package*/ void setIdent(int ident, ComponentName component) {
if (mIdent != 0) {
throw new IllegalStateException("mIdent already set");
}
+ if (component == null) {
+ throw new IllegalArgumentException("component must be non-null");
+ }
mIdent = ident;
+ mAssociatedPackage = component.getPackageName();
}
/**
@@ -1696,12 +1711,55 @@
boolean globalSearch) {
if (mIdent == 0) throw new IllegalArgumentException(
"Called from outside of an Activity context");
+ if (!globalSearch && !mAssociatedPackage.equals(launchActivity.getPackageName())) {
+ Log.w(TAG, "invoking app search on a different package " +
+ "not associated with this search manager");
+ }
try {
// activate the search manager and start it up!
mService.startSearch(initialQuery, selectInitialQuery, launchActivity, appSearchData,
globalSearch, mSearchManagerCallback, mIdent);
} catch (RemoteException ex) {
- Log.e(TAG, "startSearch() failed: " + ex);
+ Log.e(TAG, "startSearch() failed.", ex);
+ }
+ }
+
+ /**
+ * Similar to {@link #startSearch} but actually fires off the search query after invoking
+ * the search dialog. Made available for testing purposes.
+ *
+ * @param query The query to trigger. If empty, request will be ignored.
+ * @param launchActivity The ComponentName of the activity that has launched this search.
+ * @param appSearchData An application can insert application-specific
+ * context here, in order to improve quality or specificity of its own
+ * searches. This data will be returned with SEARCH intent(s). Null if
+ * no extra data is required.
+ * @param globalSearch If false, this will only launch the search that has been specifically
+ * defined by the application (which is usually defined as a local search). If no default
+ * search is defined in the current application or activity, no search will be launched.
+ * If true, this will always launch a platform-global (e.g. web-based) search instead.
+ *
+ * @see #startSearch
+ */
+ public void triggerSearch(String query,
+ ComponentName launchActivity,
+ Bundle appSearchData,
+ boolean globalSearch) {
+ if (mIdent == 0) throw new IllegalArgumentException(
+ "Called from outside of an Activity context");
+ if (!mAssociatedPackage.equals(launchActivity.getPackageName())) {
+ throw new IllegalArgumentException("invoking app search on a different package " +
+ "not associated with this search manager");
+ }
+ if (query == null || TextUtils.getTrimmedLength(query) == 0) {
+ Log.w(TAG, "triggerSearch called with empty query, ignoring.");
+ return;
+ }
+ try {
+ mService.triggerSearch(query, launchActivity, appSearchData, mSearchManagerCallback,
+ globalSearch, mIdent);
+ } catch (RemoteException ex) {
+ Log.e(TAG, "triggerSearch() failed.", ex);
}
}
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index fd8776f..c5ca0a3 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -28,6 +28,7 @@
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.util.Log;
import android.view.ViewRoot;
import java.io.FileOutputStream;
@@ -82,7 +83,8 @@
try {
ParcelFileDescriptor fd = mService.getWallpaper(this);
if (fd != null) {
- Bitmap bm = BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor());
+ Bitmap bm = BitmapFactory.decodeFileDescriptor(
+ fd.getFileDescriptor(), null, null);
if (bm != null) {
// For now clear the density until we figure out how
// to deal with it for wallpapers.
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 2ea45d5..6e48b66 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -25,7 +25,10 @@
import android.os.IBinder;
import android.util.Log;
-import java.util.List;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+import java.util.HashSet;
/**
* Public API for controlling the Bluetooth A2DP Profile Service.
@@ -47,7 +50,7 @@
*
* @hide
*/
-public class BluetoothA2dp {
+public final class BluetoothA2dp {
private static final String TAG = "BluetoothA2dp";
private static final boolean DBG = false;
@@ -79,6 +82,7 @@
/** Default priority for a2dp devices that should not allow incoming
* connections */
public static final int PRIORITY_OFF = 0;
+
private final IBluetoothA2dp mService;
private final Context mContext;
@@ -89,6 +93,7 @@
*/
public BluetoothA2dp(Context c) {
mContext = c;
+
IBinder b = ServiceManager.getService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE);
if (b == null) {
throw new RuntimeException("Bluetooth A2DP service not available!");
@@ -99,14 +104,14 @@
/** Initiate a connection to an A2DP sink.
* Listen for SINK_STATE_CHANGED_ACTION to find out when the
* connection is completed.
- * @param address Remote BT address.
+ * @param device Remote BT device.
* @return Result code, negative indicates an immediate error.
* @hide
*/
- public int connectSink(String address) {
- if (DBG) log("connectSink(" + address + ")");
+ public int connectSink(BluetoothDevice device) {
+ if (DBG) log("connectSink(" + device + ")");
try {
- return mService.connectSink(address);
+ return mService.connectSink(device);
} catch (RemoteException e) {
Log.w(TAG, "", e);
return BluetoothError.ERROR_IPC;
@@ -116,14 +121,14 @@
/** Initiate disconnect from an A2DP sink.
* Listen for SINK_STATE_CHANGED_ACTION to find out when
* disconnect is completed.
- * @param address Remote BT address.
+ * @param device Remote BT device.
* @return Result code, negative indicates an immediate error.
* @hide
*/
- public int disconnectSink(String address) {
- if (DBG) log("disconnectSink(" + address + ")");
+ public int disconnectSink(BluetoothDevice device) {
+ if (DBG) log("disconnectSink(" + device + ")");
try {
- return mService.disconnectSink(address);
+ return mService.disconnectSink(device);
} catch (RemoteException e) {
Log.w(TAG, "", e);
return BluetoothError.ERROR_IPC;
@@ -131,24 +136,25 @@
}
/** Check if a specified A2DP sink is connected.
- * @param address Remote BT address.
+ * @param device Remote BT device.
* @return True if connected (or playing), false otherwise and on error.
* @hide
*/
- public boolean isSinkConnected(String address) {
- if (DBG) log("isSinkConnected(" + address + ")");
- int state = getSinkState(address);
+ public boolean isSinkConnected(BluetoothDevice device) {
+ if (DBG) log("isSinkConnected(" + device + ")");
+ int state = getSinkState(device);
return state == STATE_CONNECTED || state == STATE_PLAYING;
}
/** Check if any A2DP sink is connected.
- * @return a List of connected A2DP sinks, or null on error.
+ * @return a unmodifiable set of connected A2DP sinks, or null on error.
* @hide
*/
- public List<String> listConnectedSinks() {
- if (DBG) log("listConnectedSinks()");
+ public Set<BluetoothDevice> getConnectedSinks() {
+ if (DBG) log("getConnectedSinks()");
try {
- return mService.listConnectedSinks();
+ return Collections.unmodifiableSet(
+ new HashSet<BluetoothDevice>(Arrays.asList(mService.getConnectedSinks())));
} catch (RemoteException e) {
Log.w(TAG, "", e);
return null;
@@ -156,14 +162,14 @@
}
/** Get the state of an A2DP sink
- * @param address Remote BT address.
+ * @param device Remote BT device.
* @return State code, or negative on error
* @hide
*/
- public int getSinkState(String address) {
- if (DBG) log("getSinkState(" + address + ")");
+ public int getSinkState(BluetoothDevice device) {
+ if (DBG) log("getSinkState(" + device + ")");
try {
- return mService.getSinkState(address);
+ return mService.getSinkState(device);
} catch (RemoteException e) {
Log.w(TAG, "", e);
return BluetoothError.ERROR_IPC;
@@ -177,15 +183,15 @@
* Sinks with priority greater than zero will accept incoming connections
* (if no sink is currently connected).
* Priority for unpaired sink must be PRIORITY_NONE.
- * @param address Paired sink
+ * @param device Paired sink
* @param priority Integer priority, for example PRIORITY_AUTO or
* PRIORITY_NONE
* @return Result code, negative indicates an error
*/
- public int setSinkPriority(String address, int priority) {
- if (DBG) log("setSinkPriority(" + address + ", " + priority + ")");
+ public int setSinkPriority(BluetoothDevice device, int priority) {
+ if (DBG) log("setSinkPriority(" + device + ", " + priority + ")");
try {
- return mService.setSinkPriority(address, priority);
+ return mService.setSinkPriority(device, priority);
} catch (RemoteException e) {
Log.w(TAG, "", e);
return BluetoothError.ERROR_IPC;
@@ -194,13 +200,13 @@
/**
* Get priority of a2dp sink.
- * @param address Sink
+ * @param device Sink
* @return non-negative priority, or negative error code on error.
*/
- public int getSinkPriority(String address) {
- if (DBG) log("getSinkPriority(" + address + ")");
+ public int getSinkPriority(BluetoothDevice device) {
+ if (DBG) log("getSinkPriority(" + device + ")");
try {
- return mService.getSinkPriority(address);
+ return mService.getSinkPriority(device);
} catch (RemoteException e) {
Log.w(TAG, "", e);
return BluetoothError.ERROR_IPC;
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
new file mode 100644
index 0000000..d207540
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Set;
+import java.util.HashSet;
+
+/**
+ * Represents the local Bluetooth adapter.
+ *
+ * @hide
+ */
+public final class BluetoothAdapter {
+ private static final String TAG = "BluetoothAdapter";
+
+ public static final int BLUETOOTH_STATE_OFF = 0;
+ public static final int BLUETOOTH_STATE_TURNING_ON = 1;
+ public static final int BLUETOOTH_STATE_ON = 2;
+ public static final int BLUETOOTH_STATE_TURNING_OFF = 3;
+
+ /** Inquiry scan and page scan are both off.
+ * Device is neither discoverable nor connectable */
+ public static final int SCAN_MODE_NONE = 0;
+ /** Page scan is on, inquiry scan is off.
+ * Device is connectable, but not discoverable */
+ public static final int SCAN_MODE_CONNECTABLE = 1;
+ /** Page scan and inquiry scan are on.
+ * Device is connectable and discoverable */
+ public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 3;
+
+ public static final int RESULT_FAILURE = -1;
+ public static final int RESULT_SUCCESS = 0;
+
+ /* The user will be prompted to enter a pin */
+ public static final int PAIRING_VARIANT_PIN = 0;
+ /* The user will be prompted to enter a passkey */
+ public static final int PAIRING_VARIANT_PASSKEY = 1;
+ /* The user will be prompted to confirm the passkey displayed on the screen */
+ public static final int PAIRING_VARIANT_CONFIRMATION = 2;
+
+ private final IBluetooth mService;
+
+ /**
+ * Do not use this constructor. Use Context.getSystemService() instead.
+ * @hide
+ */
+ public BluetoothAdapter(IBluetooth service) {
+ if (service == null) {
+ throw new IllegalArgumentException("service is null");
+ }
+ mService = service;
+ }
+
+ /**
+ * Get the remote BluetoothDevice associated with the given MAC address.
+ * Bluetooth MAC address must be upper case, such as "00:11:22:33:AA:BB".
+ * @param address valid Bluetooth MAC address
+ */
+ public BluetoothDevice getRemoteDevice(String address) {
+ return new BluetoothDevice(address);
+ }
+
+ /**
+ * Is Bluetooth currently turned on.
+ *
+ * @return true if Bluetooth enabled, false otherwise.
+ */
+ public boolean isEnabled() {
+ try {
+ return mService.isEnabled();
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ return false;
+ }
+
+ /**
+ * Get the current state of Bluetooth.
+ *
+ * @return One of BLUETOOTH_STATE_ or BluetoothError.ERROR.
+ */
+ public int getBluetoothState() {
+ try {
+ return mService.getBluetoothState();
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ return BluetoothError.ERROR;
+ }
+
+ /**
+ * Enable the Bluetooth device.
+ * Turn on the underlying hardware.
+ * This is an asynchronous call,
+ * BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION can be used to check if
+ * and when the device is sucessfully enabled.
+ * @return false if we cannot enable the Bluetooth device. True does not
+ * imply the device was enabled, it only implies that so far there were no
+ * problems.
+ */
+ public boolean enable() {
+ try {
+ return mService.enable();
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ return false;
+ }
+
+ /**
+ * Disable the Bluetooth device.
+ * This turns off the underlying hardware.
+ *
+ * @return true if successful, false otherwise.
+ */
+ public boolean disable() {
+ try {
+ return mService.disable(true);
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ return false;
+ }
+
+ public String getAddress() {
+ try {
+ return mService.getAddress();
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ return null;
+ }
+
+ /**
+ * Get the friendly Bluetooth name of this device.
+ *
+ * This name is visible to remote Bluetooth devices. Currently it is only
+ * possible to retrieve the Bluetooth name when Bluetooth is enabled.
+ *
+ * @return the Bluetooth name, or null if there was a problem.
+ */
+ public String getName() {
+ try {
+ return mService.getName();
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ return null;
+ }
+
+ /**
+ * Set the friendly Bluetooth name of this device.
+ *
+ * This name is visible to remote Bluetooth devices. The Bluetooth Service
+ * is responsible for persisting this name.
+ *
+ * @param name the name to set
+ * @return true, if the name was successfully set. False otherwise.
+ */
+ public boolean setName(String name) {
+ try {
+ return mService.setName(name);
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ return false;
+ }
+
+ /**
+ * Get the current scan mode.
+ * Used to determine if the local device is connectable and/or discoverable
+ * @return Scan mode, one of SCAN_MODE_* or an error code
+ */
+ public int getScanMode() {
+ try {
+ return mService.getScanMode();
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ return BluetoothError.ERROR_IPC;
+ }
+
+ /**
+ * Set the current scan mode.
+ * Used to make the local device connectable and/or discoverable
+ * @param scanMode One of SCAN_MODE_*
+ */
+ public void setScanMode(int scanMode) {
+ try {
+ mService.setScanMode(scanMode);
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ }
+
+ public int getDiscoverableTimeout() {
+ try {
+ return mService.getDiscoverableTimeout();
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ return -1;
+ }
+
+ public void setDiscoverableTimeout(int timeout) {
+ try {
+ mService.setDiscoverableTimeout(timeout);
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ }
+
+ public boolean startDiscovery() {
+ try {
+ return mService.startDiscovery();
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ return false;
+ }
+
+ public void cancelDiscovery() {
+ try {
+ mService.cancelDiscovery();
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ }
+
+ public boolean isDiscovering() {
+ try {
+ return mService.isDiscovering();
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ return false;
+ }
+
+ /**
+ * List remote devices that are bonded (paired) to the local adapter.
+ *
+ * Bonding (pairing) is the process by which the user enters a pin code for
+ * the device, which generates a shared link key, allowing for
+ * authentication and encryption of future connections. In Android we
+ * require bonding before RFCOMM or SCO connections can be made to a remote
+ * device.
+ *
+ * This function lists which remote devices we have a link key for. It does
+ * not cause any RF transmission, and does not check if the remote device
+ * still has it's link key with us. If the other side no longer has its
+ * link key then the RFCOMM or SCO connection attempt will result in an
+ * error.
+ *
+ * This function does not check if the remote device is in range.
+ *
+ * Remote devices that have an in-progress bonding attempt are not
+ * returned.
+ *
+ * @return unmodifiable set of bonded devices, or null on error
+ */
+ public Set<BluetoothDevice> getBondedDevices() {
+ try {
+ return toDeviceSet(mService.listBonds());
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ return null;
+ }
+
+ /**
+ * Construct a listening, secure RFCOMM server socket.
+ * The remote device connecting to this socket will be authenticated and
+ * communication on this socket will be encrypted.
+ * Call #accept to retrieve connections to this socket.
+ * @return An RFCOMM BluetoothServerSocket
+ * @throws IOException On error, for example Bluetooth not available, or
+ * insufficient permissions.
+ */
+ public BluetoothServerSocket listenUsingRfcommOn(int port) throws IOException {
+ BluetoothServerSocket socket = new BluetoothServerSocket(
+ BluetoothSocket.TYPE_RFCOMM, true, true, port);
+ try {
+ socket.mSocket.bindListenNative();
+ } catch (IOException e) {
+ try {
+ socket.close();
+ } catch (IOException e2) { }
+ throw e;
+ }
+ return socket;
+ }
+
+ /**
+ * Construct an unencrypted, unauthenticated, RFCOMM server socket.
+ * Call #accept to retrieve connections to this socket.
+ * @return An RFCOMM BluetoothServerSocket
+ * @throws IOException On error, for example Bluetooth not available, or
+ * insufficient permissions.
+ */
+ public BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
+ BluetoothServerSocket socket = new BluetoothServerSocket(
+ BluetoothSocket.TYPE_RFCOMM, false, false, port);
+ try {
+ socket.mSocket.bindListenNative();
+ } catch (IOException e) {
+ try {
+ socket.close();
+ } catch (IOException e2) { }
+ throw e;
+ }
+ return socket;
+ }
+
+ /**
+ * Construct a SCO server socket.
+ * Call #accept to retrieve connections to this socket.
+ * @return A SCO BluetoothServerSocket
+ * @throws IOException On error, for example Bluetooth not available, or
+ * insufficient permissions.
+ */
+ public static BluetoothServerSocket listenUsingScoOn() throws IOException {
+ BluetoothServerSocket socket = new BluetoothServerSocket(
+ BluetoothSocket.TYPE_SCO, false, false, -1);
+ try {
+ socket.mSocket.bindListenNative();
+ } catch (IOException e) {
+ try {
+ socket.close();
+ } catch (IOException e2) { }
+ throw e;
+ }
+ return socket;
+ }
+
+ private Set<BluetoothDevice> toDeviceSet(String[] addresses) {
+ Set<BluetoothDevice> devices = new HashSet<BluetoothDevice>(addresses.length);
+ for (int i = 0; i < addresses.length; i++) {
+ devices.add(getRemoteDevice(addresses[i]));
+ }
+ return Collections.unmodifiableSet(devices);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothAudioGateway.java b/core/java/android/bluetooth/BluetoothAudioGateway.java
index f3afd2a..abd7723 100644
--- a/core/java/android/bluetooth/BluetoothAudioGateway.java
+++ b/core/java/android/bluetooth/BluetoothAudioGateway.java
@@ -9,24 +9,22 @@
/**
* Listen's for incoming RFCOMM connection for the headset / handsfree service.
*
- * This class is planned for deletion, in favor of a generic Rfcomm class.
+ * TODO: Use the new generic BluetoothSocket class instead of this legacy code
*
* @hide
*/
-public class BluetoothAudioGateway {
+public final class BluetoothAudioGateway {
private static final String TAG = "BT Audio Gateway";
private static final boolean DBG = false;
private int mNativeData;
static { classInitNative(); }
- private BluetoothDevice mBluetooth;
-
/* in */
private int mHandsfreeAgRfcommChannel = -1;
private int mHeadsetAgRfcommChannel = -1;
- /* out */
+ /* out - written by native code */
private String mConnectingHeadsetAddress;
private int mConnectingHeadsetRfcommChannel; /* -1 when not connected */
private int mConnectingHeadsetSocketFd;
@@ -35,17 +33,18 @@
private int mConnectingHandsfreeSocketFd;
private int mTimeoutRemainingMs; /* in/out */
+ private final BluetoothAdapter mAdapter;
+
public static final int DEFAULT_HF_AG_CHANNEL = 10;
public static final int DEFAULT_HS_AG_CHANNEL = 11;
- public BluetoothAudioGateway(BluetoothDevice bluetooth) {
- this(bluetooth, DEFAULT_HF_AG_CHANNEL, DEFAULT_HS_AG_CHANNEL);
+ public BluetoothAudioGateway(BluetoothAdapter adapter) {
+ this(adapter, DEFAULT_HF_AG_CHANNEL, DEFAULT_HS_AG_CHANNEL);
}
- public BluetoothAudioGateway(BluetoothDevice bluetooth,
- int handsfreeAgRfcommChannel,
- int headsetAgRfcommChannel) {
- mBluetooth = bluetooth;
+ public BluetoothAudioGateway(BluetoothAdapter adapter, int handsfreeAgRfcommChannel,
+ int headsetAgRfcommChannel) {
+ mAdapter = adapter;
mHandsfreeAgRfcommChannel = handsfreeAgRfcommChannel;
mHeadsetAgRfcommChannel = headsetAgRfcommChannel;
initializeNativeDataNative();
@@ -58,18 +57,17 @@
private Handler mCallback;
public class IncomingConnectionInfo {
- IncomingConnectionInfo(BluetoothDevice bluetooth, String address, int socketFd,
- int rfcommChan) {
- mBluetooth = bluetooth;
- mAddress = address;
+ public BluetoothAdapter mAdapter;
+ public BluetoothDevice mRemoteDevice;
+ public int mSocketFd;
+ public int mRfcommChan;
+ IncomingConnectionInfo(BluetoothAdapter adapter, BluetoothDevice remoteDevice,
+ int socketFd, int rfcommChan) {
+ mAdapter = adapter;
+ mRemoteDevice = remoteDevice;
mSocketFd = socketFd;
mRfcommChan = rfcommChan;
}
-
- public BluetoothDevice mBluetooth;
- public String mAddress;
- public int mSocketFd;
- public int mRfcommChan;
}
public static final int MSG_INCOMING_HEADSET_CONNECTION = 100;
@@ -111,12 +109,11 @@
mConnectingHeadsetRfcommChannel);
Message msg = Message.obtain(mCallback);
msg.what = MSG_INCOMING_HEADSET_CONNECTION;
- msg.obj =
- new IncomingConnectionInfo(
- mBluetooth,
- mConnectingHeadsetAddress,
- mConnectingHeadsetSocketFd,
- mConnectingHeadsetRfcommChannel);
+ msg.obj = new IncomingConnectionInfo(
+ mAdapter,
+ mAdapter.getRemoteDevice(mConnectingHeadsetAddress),
+ mConnectingHeadsetSocketFd,
+ mConnectingHeadsetRfcommChannel);
msg.sendToTarget();
}
if (mConnectingHandsfreeRfcommChannel >= 0) {
@@ -126,12 +123,11 @@
Message msg = Message.obtain();
msg.setTarget(mCallback);
msg.what = MSG_INCOMING_HANDSFREE_CONNECTION;
- msg.obj =
- new IncomingConnectionInfo(
- mBluetooth,
- mConnectingHandsfreeAddress,
- mConnectingHandsfreeSocketFd,
- mConnectingHandsfreeRfcommChannel);
+ msg.obj = new IncomingConnectionInfo(
+ mAdapter,
+ mAdapter.getRemoteDevice(mConnectingHandsfreeAddress),
+ mConnectingHandsfreeSocketFd,
+ mConnectingHandsfreeRfcommChannel);
msg.sendToTarget();
}
}
diff --git a/core/java/android/accounts/Future2Callback.java b/core/java/android/bluetooth/BluetoothDevice.aidl
similarity index 86%
copy from core/java/android/accounts/Future2Callback.java
copy to core/java/android/bluetooth/BluetoothDevice.aidl
index 7ef0c947..daae74d 100644
--- a/core/java/android/accounts/Future2Callback.java
+++ b/core/java/android/bluetooth/BluetoothDevice.aidl
@@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.accounts;
-public interface Future2Callback {
- void run(Future2 future);
-}
\ No newline at end of file
+package android.bluetooth;
+
+parcelable BluetoothDevice;
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index a64c6d72..27b2849 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * 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.
@@ -16,39 +16,25 @@
package android.bluetooth;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.util.Log;
+import java.io.IOException;
import java.io.UnsupportedEncodingException;
/**
- * The Android Bluetooth API is not finalized, and *will* change. Use at your
- * own risk.
+ * Represents a remote Bluetooth device.
*
- * Manages the local Bluetooth device. Scan for devices, create bondings,
- * power up and down the adapter.
- *
+ * TODO: unhide
* @hide
*/
-public class BluetoothDevice {
-
- public static final int BLUETOOTH_STATE_OFF = 0;
- public static final int BLUETOOTH_STATE_TURNING_ON = 1;
- public static final int BLUETOOTH_STATE_ON = 2;
- public static final int BLUETOOTH_STATE_TURNING_OFF = 3;
-
- /** Inquiry scan and page scan are both off.
- * Device is neither discoverable nor connectable */
- public static final int SCAN_MODE_NONE = 0;
- /** Page scan is on, inquiry scan is off.
- * Device is connectable, but not discoverable */
- public static final int SCAN_MODE_CONNECTABLE = 1;
- /** Page scan and inquiry scan are on.
- * Device is connectable and discoverable */
- public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 3;
-
- public static final int RESULT_FAILURE = -1;
- public static final int RESULT_SUCCESS = 0;
+public final class BluetoothDevice implements Parcelable {
+ private static final String TAG = "BluetoothDevice";
/** We do not have a link key for the remote device, and are therefore not
* bonded */
@@ -81,84 +67,81 @@
/* The user will be prompted to confirm the passkey displayed on the screen */
public static final int PAIRING_VARIANT_CONFIRMATION = 2;
+ private static final int ADDRESS_LENGTH = 17;
- private static final String TAG = "BluetoothDevice";
+ private static IBluetooth sService; /* Guarenteed constant after first object constructed */
- private final IBluetoothDevice mService;
+ private final String mAddress;
+
/**
- * @hide - hide this because it takes a parameter of type
- * IBluetoothDevice, which is a System private class.
- * Also note that Context.getSystemService is a factory that
- * returns a BlueToothDevice. That is the right way to get
- * a BluetoothDevice.
+ * Create a new BluetoothDevice
+ * Bluetooth MAC address must be upper case, such as "00:11:22:33:AA:BB",
+ * and is validated in this constructor.
+ * @param address valid Bluetooth MAC address
+ * @throws RuntimeException Bluetooth is not available on this platform
+ * @throws IllegalArgumentException address is invalid
+ * @hide
*/
- public BluetoothDevice(IBluetoothDevice service) {
- mService = service;
+ /*package*/ BluetoothDevice(String address) {
+ synchronized (BluetoothDevice.class) {
+ if (sService == null) {
+ IBinder b = ServiceManager.getService(Context.BLUETOOTH_SERVICE);
+ if (b == null) {
+ throw new RuntimeException("Bluetooth service not available");
+ }
+ sService = IBluetooth.Stub.asInterface(b);
+ }
+ }
+
+ if (!checkBluetoothAddress(address)) {
+ throw new IllegalArgumentException(address + " is not a valid Bluetooth address");
+ }
+
+ mAddress = address;
}
- /**
- * Is Bluetooth currently turned on.
- *
- * @return true if Bluetooth enabled, false otherwise.
- */
- public boolean isEnabled() {
- try {
- return mService.isEnabled();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof BluetoothDevice) {
+ return mAddress.equals(((BluetoothDevice)o).getAddress());
+ }
return false;
}
- /**
- * Get the current state of Bluetooth.
- *
- * @return One of BLUETOOTH_STATE_ or BluetoothError.ERROR.
- */
- public int getBluetoothState() {
- try {
- return mService.getBluetoothState();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return BluetoothError.ERROR;
+ @Override
+ public int hashCode() {
+ return mAddress.hashCode();
}
- /**
- * Enable the Bluetooth device.
- * Turn on the underlying hardware.
- * This is an asynchronous call,
- * BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION can be used to check if
- * and when the device is sucessfully enabled.
- * @return false if we cannot enable the Bluetooth device. True does not
- * imply the device was enabled, it only implies that so far there were no
- * problems.
- */
- public boolean enable() {
- try {
- return mService.enable();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
+ @Override
+ public String toString() {
+ return mAddress;
}
- /**
- * Disable the Bluetooth device.
- * This turns off the underlying hardware.
- *
- * @return true if successful, false otherwise.
- */
- public boolean disable() {
- try {
- return mService.disable(true);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Parcelable.Creator<BluetoothDevice> CREATOR =
+ new Parcelable.Creator<BluetoothDevice>() {
+ public BluetoothDevice createFromParcel(Parcel in) {
+ return new BluetoothDevice(in.readString());
+ }
+ public BluetoothDevice[] newArray(int size) {
+ return new BluetoothDevice[size];
+ }
+ };
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mAddress);
}
public String getAddress() {
- try {
- return mService.getAddress();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
+ return mAddress;
}
/**
- * Get the friendly Bluetooth name of this device.
+ * Get the friendly Bluetooth name of this remote device.
*
* This name is visible to remote Bluetooth devices. Currently it is only
* possible to retrieve the Bluetooth name when Bluetooth is enabled.
@@ -167,98 +150,12 @@
*/
public String getName() {
try {
- return mService.getName();
+ return sService.getRemoteName(mAddress);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return null;
}
/**
- * Set the friendly Bluetooth name of this device.
- *
- * This name is visible to remote Bluetooth devices. The Bluetooth Service
- * is responsible for persisting this name.
- *
- * @param name the name to set
- * @return true, if the name was successfully set. False otherwise.
- */
- public boolean setName(String name) {
- try {
- return mService.setName(name);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
-
- /**
- * Get the current scan mode.
- * Used to determine if the local device is connectable and/or discoverable
- * @return Scan mode, one of SCAN_MODE_* or an error code
- */
- public int getScanMode() {
- try {
- return mService.getScanMode();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return BluetoothError.ERROR_IPC;
- }
-
- /**
- * Set the current scan mode.
- * Used to make the local device connectable and/or discoverable
- * @param scanMode One of SCAN_MODE_*
- */
- public void setScanMode(int scanMode) {
- try {
- mService.setScanMode(scanMode);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- }
-
- public int getDiscoverableTimeout() {
- try {
- return mService.getDiscoverableTimeout();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return -1;
- }
- public void setDiscoverableTimeout(int timeout) {
- try {
- mService.setDiscoverableTimeout(timeout);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- }
-
- public boolean startDiscovery() {
- try {
- return mService.startDiscovery();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
-
- public void cancelDiscovery() {
- try {
- mService.cancelDiscovery();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- }
-
- public boolean isDiscovering() {
- try {
- return mService.isDiscovering();
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
-
- /**
- * Removes the remote device and the pairing information associated
- * with it.
- *
- * @param address the Bluetooth hardware address you want to disconnect.
- * @return true if the device was disconnected, false otherwise and on
- * error.
- */
- public boolean removeBond(String address) {
- try {
- return mService.removeBond(address);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return false;
- }
-
- /**
* Create a bonding with a remote bluetooth device.
*
* This is an asynchronous call. The result of this bonding attempt can be
@@ -268,9 +165,9 @@
* @return false If there was an immediate problem creating the bonding,
* true otherwise.
*/
- public boolean createBond(String address) {
+ public boolean createBond() {
try {
- return mService.createBond(address);
+ return sService.createBond(mAddress);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
@@ -278,41 +175,25 @@
/**
* Cancel an in-progress bonding request started with createBond.
*/
- public boolean cancelBondProcess(String address) {
+ public boolean cancelBondProcess() {
try {
- return mService.cancelBondProcess(address);
+ return sService.cancelBondProcess(mAddress);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
/**
- * List remote devices that are bonded (paired) to the local device.
+ * Removes the remote device and the pairing information associated
+ * with it.
*
- * Bonding (pairing) is the process by which the user enters a pin code for
- * the device, which generates a shared link key, allowing for
- * authentication and encryption of future connections. In Android we
- * require bonding before RFCOMM or SCO connections can be made to a remote
- * device.
- *
- * This function lists which remote devices we have a link key for. It does
- * not cause any RF transmission, and does not check if the remote device
- * still has it's link key with us. If the other side no longer has its
- * link key then the RFCOMM or SCO connection attempt will result in an
- * error.
- *
- * This function does not check if the remote device is in range.
- *
- * Remote devices that have an in-progress bonding attempt are not
- * returned.
- *
- * @return bluetooth hardware addresses of remote devices that are
- * bonded. Array size is 0 if no devices are bonded. Null on error.
+ * @return true if the device was disconnected, false otherwise and on
+ * error.
*/
- public String[] listBonds() {
+ public boolean removeBond() {
try {
- return mService.listBonds();
+ return sService.removeBond(mAddress);
} catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
+ return false;
}
/**
@@ -325,70 +206,103 @@
* @param address Bluetooth hardware address of the remote device to check.
* @return Result code
*/
- public int getBondState(String address) {
+ public int getBondState() {
try {
- return mService.getBondState(address);
+ return sService.getBondState(mAddress);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return BluetoothError.ERROR_IPC;
}
- public String getRemoteName(String address) {
+ public int getBluetoothClass() {
try {
- return mService.getRemoteName(address);
- } catch (RemoteException e) {Log.e(TAG, "", e);}
- return null;
- }
-
- public int getRemoteClass(String address) {
- try {
- return mService.getRemoteClass(address);
+ return sService.getRemoteClass(mAddress);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return BluetoothError.ERROR_IPC;
}
- public String[] getRemoteUuids(String address) {
+ public String[] getUuids() {
try {
- return mService.getRemoteUuids(address);
+ return sService.getRemoteUuids(mAddress);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return null;
}
- public int getRemoteServiceChannel(String address, String uuid) {
+ public int getServiceChannel(String uuid) {
try {
- return mService.getRemoteServiceChannel(address, uuid);
+ return sService.getRemoteServiceChannel(mAddress, uuid);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return BluetoothError.ERROR_IPC;
}
- public boolean setPin(String address, byte[] pin) {
+ public boolean setPin(byte[] pin) {
try {
- return mService.setPin(address, pin);
+ return sService.setPin(mAddress, pin);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
- public boolean setPasskey(String address, int passkey) {
+ public boolean setPasskey(int passkey) {
try {
- return mService.setPasskey(address, passkey);
+ return sService.setPasskey(mAddress, passkey);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
- public boolean setPairingConfirmation(String address, boolean confirm) {
+ public boolean setPairingConfirmation(boolean confirm) {
try {
- return mService.setPairingConfirmation(address, confirm);
+ return sService.setPairingConfirmation(mAddress, confirm);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
- public boolean cancelPairingUserInput(String address) {
+ public boolean cancelPairingUserInput() {
try {
- return mService.cancelPairingUserInput(address);
+ return sService.cancelPairingUserInput(mAddress);
} catch (RemoteException e) {Log.e(TAG, "", e);}
return false;
}
/**
+ * Construct a secure RFCOMM socket ready to start an outgoing connection.
+ * Call #connect on the returned #BluetoothSocket to begin the connection.
+ * The remote device will be authenticated and communication on this socket
+ * will be encrypted.
+ * @param port remote port
+ * @return an RFCOMM BluetoothSocket
+ * @throws IOException on error, for example Bluetooth not available, or
+ * insufficient permissions.
+ */
+ public BluetoothSocket createRfcommSocket(int port) throws IOException {
+ return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, port);
+ }
+
+ /**
+ * Construct an insecure RFCOMM socket ready to start an outgoing
+ * connection.
+ * Call #connect on the returned #BluetoothSocket to begin the connection.
+ * The remote device will not be authenticated and communication on this
+ * socket will not be encrypted.
+ * @param port remote port
+ * @return An RFCOMM BluetoothSocket
+ * @throws IOException On error, for example Bluetooth not available, or
+ * insufficient permissions.
+ */
+ public BluetoothSocket createInsecureRfcommSocket(int port) throws IOException {
+ return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, port);
+ }
+
+ /**
+ * Construct a SCO socket ready to start an outgoing connection.
+ * Call #connect on the returned #BluetoothSocket to begin the connection.
+ * @return a SCO BluetoothSocket
+ * @throws IOException on error, for example Bluetooth not available, or
+ * insufficient permissions.
+ */
+ public BluetoothSocket createScoSocket() throws IOException {
+ return new BluetoothSocket(BluetoothSocket.TYPE_SCO, -1, true, true, this, -1);
+ }
+
+ /**
* Check that a pin is valid and convert to byte array.
*
* Bluetooth pin's are 1 to 16 bytes of UTF8 characters.
@@ -413,7 +327,6 @@
return pinBytes;
}
- private static final int ADDRESS_LENGTH = 17;
/** Sanity check a bluetooth address, such as "00:43:A8:23:10:F0" */
public static boolean checkBluetoothAddress(String address) {
if (address == null || address.length() != ADDRESS_LENGTH) {
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index fe1e09a..0e3d2bb 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -49,7 +49,7 @@
*
* @hide
*/
-public class BluetoothHeadset {
+public final class BluetoothHeadset {
private static final String TAG = "BluetoothHeadset";
private static final boolean DBG = false;
@@ -163,16 +163,16 @@
}
/**
- * Get the Bluetooth address of the current headset.
- * @return The Bluetooth address, or null if not in connected or connecting
+ * Get the BluetoothDevice for the current headset.
+ * @return current headset, or null if not in connected or connecting
* state, or if this proxy object is not connected to the Headset
* service.
*/
- public String getHeadsetAddress() {
- if (DBG) log("getHeadsetAddress()");
+ public BluetoothDevice getCurrentHeadset() {
+ if (DBG) log("getCurrentHeadset()");
if (mService != null) {
try {
- return mService.getHeadsetAddress();
+ return mService.getCurrentHeadset();
} catch (RemoteException e) {Log.e(TAG, e.toString());}
} else {
Log.w(TAG, "Proxy not attached to service");
@@ -185,19 +185,19 @@
* Request to initiate a connection to a headset.
* This call does not block. Fails if a headset is already connecting
* or connected.
- * Initiates auto-connection if address is null. Tries to connect to all
+ * Initiates auto-connection if device is null. Tries to connect to all
* devices with priority greater than PRIORITY_AUTO in descending order.
- * @param address The Bluetooth Address to connect to, or null to
- * auto-connect to the last connected headset.
- * @return False if there was a problem initiating the connection
- * procedure, and no further HEADSET_STATE_CHANGED intents
- * will be expected.
+ * @param device device to connect to, or null to auto-connect last connected
+ * headset
+ * @return false if there was a problem initiating the connection
+ * procedure, and no further HEADSET_STATE_CHANGED intents
+ * will be expected.
*/
- public boolean connectHeadset(String address) {
- if (DBG) log("connectHeadset(" + address + ")");
+ public boolean connectHeadset(BluetoothDevice device) {
+ if (DBG) log("connectHeadset(" + device + ")");
if (mService != null) {
try {
- if (mService.connectHeadset(address)) {
+ if (mService.connectHeadset(device)) {
return true;
}
} catch (RemoteException e) {Log.e(TAG, e.toString());}
@@ -213,11 +213,11 @@
* connecting). Returns false if not connected, or if this proxy object
* if not currently connected to the headset service.
*/
- public boolean isConnected(String address) {
- if (DBG) log("isConnected(" + address + ")");
+ public boolean isConnected(BluetoothDevice device) {
+ if (DBG) log("isConnected(" + device + ")");
if (mService != null) {
try {
- return mService.isConnected(address);
+ return mService.isConnected(device);
} catch (RemoteException e) {Log.e(TAG, e.toString());}
} else {
Log.w(TAG, "Proxy not attached to service");
@@ -295,16 +295,16 @@
* auto-connected.
* Incoming connections are ignored regardless of priority if there is
* already a headset connected.
- * @param address Paired headset
+ * @param device paired headset
* @param priority Integer priority, for example PRIORITY_AUTO or
* PRIORITY_NONE
- * @return True if successful, false if there was some error.
+ * @return true if successful, false if there was some error
*/
- public boolean setPriority(String address, int priority) {
- if (DBG) log("setPriority(" + address + ", " + priority + ")");
+ public boolean setPriority(BluetoothDevice device, int priority) {
+ if (DBG) log("setPriority(" + device + ", " + priority + ")");
if (mService != null) {
try {
- return mService.setPriority(address, priority);
+ return mService.setPriority(device, priority);
} catch (RemoteException e) {Log.e(TAG, e.toString());}
} else {
Log.w(TAG, "Proxy not attached to service");
@@ -315,14 +315,14 @@
/**
* Get priority of headset.
- * @param address Headset
- * @return non-negative priority, or negative error code on error.
+ * @param device headset
+ * @return non-negative priority, or negative error code on error
*/
- public int getPriority(String address) {
- if (DBG) log("getPriority(" + address + ")");
+ public int getPriority(BluetoothDevice device) {
+ if (DBG) log("getPriority(" + device + ")");
if (mService != null) {
try {
- return mService.getPriority(address);
+ return mService.getPriority(device);
} catch (RemoteException e) {Log.e(TAG, e.toString());}
} else {
Log.w(TAG, "Proxy not attached to service");
diff --git a/core/java/android/bluetooth/BluetoothIntent.java b/core/java/android/bluetooth/BluetoothIntent.java
index d6c79b4..2a0de61 100644
--- a/core/java/android/bluetooth/BluetoothIntent.java
+++ b/core/java/android/bluetooth/BluetoothIntent.java
@@ -31,8 +31,8 @@
public interface BluetoothIntent {
public static final String SCAN_MODE =
"android.bluetooth.intent.SCAN_MODE";
- public static final String ADDRESS =
- "android.bluetooth.intent.ADDRESS";
+ public static final String DEVICE =
+ "android.bluetooth.intent.DEVICE";
public static final String NAME =
"android.bluetooth.intent.NAME";
public static final String ALIAS =
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index 5782644..645e241 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -73,11 +73,11 @@
/** There was an error trying to obtain the state */
public static final int STATE_ERROR = -1;
- /** No Pce currently connected */
+ /** No client currently connected */
public static final int STATE_DISCONNECTED = 0;
/** Connection attempt in progress */
public static final int STATE_CONNECTING = 1;
- /** A Pce is currently connected */
+ /** Client is currently connected */
public static final int STATE_CONNECTED = 2;
public static final int RESULT_FAILURE = 0;
@@ -159,16 +159,16 @@
}
/**
- * Get the Bluetooth address of the current Pce.
- * @return The Bluetooth address, or null if not in connected or connecting
- * state, or if this proxy object is not connected to the Pbap
- * service.
+ * Get the currently connected remote Bluetooth device (PCE).
+ * @return The remote Bluetooth device, or null if not in connected or
+ * connecting state, or if this proxy object is not connected to
+ * the Pbap service.
*/
- public String getPceAddress() {
- if (DBG) log("getPceAddress()");
+ public BluetoothDevice getClient() {
+ if (DBG) log("getClient()");
if (mService != null) {
try {
- return mService.getPceAddress();
+ return mService.getClient();
} catch (RemoteException e) {Log.e(TAG, e.toString());}
} else {
Log.w(TAG, "Proxy not attached to service");
@@ -178,15 +178,15 @@
}
/**
- * Returns true if the specified Pcs is connected (does not include
- * connecting). Returns false if not connected, or if this proxy object
- * if not currently connected to the Pbap service.
+ * Returns true if the specified Bluetooth device is connected (does not
+ * include connecting). Returns false if not connected, or if this proxy
+ * object is not currently connected to the Pbap service.
*/
- public boolean isConnected(String address) {
- if (DBG) log("isConnected(" + address + ")");
+ public boolean isConnected(BluetoothDevice device) {
+ if (DBG) log("isConnected(" + device + ")");
if (mService != null) {
try {
- return mService.isConnected(address);
+ return mService.isConnected(device);
} catch (RemoteException e) {Log.e(TAG, e.toString());}
} else {
Log.w(TAG, "Proxy not attached to service");
@@ -196,15 +196,15 @@
}
/**
- * Disconnects the current Pce. Currently this call blocks, it may soon
- * be made asynchornous. Returns false if this proxy object is
+ * Disconnects the current Pbap client (PCE). Currently this call blocks,
+ * it may soon be made asynchornous. Returns false if this proxy object is
* not currently connected to the Pbap service.
*/
- public boolean disconnectPce() {
- if (DBG) log("disconnectPce()");
+ public boolean disconnect() {
+ if (DBG) log("disconnect()");
if (mService != null) {
try {
- mService.disconnectPce();
+ mService.disconnect();
return true;
} catch (RemoteException e) {Log.e(TAG, e.toString());}
} else {
diff --git a/core/java/android/bluetooth/BluetoothServerSocket.java b/core/java/android/bluetooth/BluetoothServerSocket.java
index f3baeab..8be300b 100644
--- a/core/java/android/bluetooth/BluetoothServerSocket.java
+++ b/core/java/android/bluetooth/BluetoothServerSocket.java
@@ -33,72 +33,7 @@
* @hide
*/
public final class BluetoothServerSocket implements Closeable {
- private final BluetoothSocket mSocket;
-
- /**
- * Construct a listening, secure RFCOMM server socket.
- * The remote device connecting to this socket will be authenticated and
- * communication on this socket will be encrypted.
- * Call #accept to retrieve connections to this socket.
- * @return An RFCOMM BluetoothServerSocket
- * @throws IOException On error, for example Bluetooth not available, or
- * insufficient permissions.
- */
- public static BluetoothServerSocket listenUsingRfcommOn(int port) throws IOException {
- BluetoothServerSocket socket = new BluetoothServerSocket(
- BluetoothSocket.TYPE_RFCOMM, true, true, port);
- try {
- socket.mSocket.bindListenNative();
- } catch (IOException e) {
- try {
- socket.close();
- } catch (IOException e2) { }
- throw e;
- }
- return socket;
- }
-
- /**
- * Construct an unencrypted, unauthenticated, RFCOMM server socket.
- * Call #accept to retrieve connections to this socket.
- * @return An RFCOMM BluetoothServerSocket
- * @throws IOException On error, for example Bluetooth not available, or
- * insufficient permissions.
- */
- public static BluetoothServerSocket listenUsingInsecureRfcommOn(int port) throws IOException {
- BluetoothServerSocket socket = new BluetoothServerSocket(
- BluetoothSocket.TYPE_RFCOMM, false, false, port);
- try {
- socket.mSocket.bindListenNative();
- } catch (IOException e) {
- try {
- socket.close();
- } catch (IOException e2) { }
- throw e;
- }
- return socket;
- }
-
- /**
- * Construct a SCO server socket.
- * Call #accept to retrieve connections to this socket.
- * @return A SCO BluetoothServerSocket
- * @throws IOException On error, for example Bluetooth not available, or
- * insufficient permissions.
- */
- public static BluetoothServerSocket listenUsingScoOn() throws IOException {
- BluetoothServerSocket socket = new BluetoothServerSocket(
- BluetoothSocket.TYPE_SCO, false, false, -1);
- try {
- socket.mSocket.bindListenNative();
- } catch (IOException e) {
- try {
- socket.close();
- } catch (IOException e2) { }
- throw e;
- }
- return socket;
- }
+ /*package*/ final BluetoothSocket mSocket;
/**
* Construct a socket for incoming connections.
@@ -109,7 +44,7 @@
* @throws IOException On error, for example Bluetooth not available, or
* insufficient priveleges
*/
- private BluetoothServerSocket(int type, boolean auth, boolean encrypt, int port)
+ /*package*/ BluetoothServerSocket(int type, boolean auth, boolean encrypt, int port)
throws IOException {
mSocket = new BluetoothSocket(type, -1, auth, encrypt, null, port);
}
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index de1f326..dda2cef 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -42,6 +42,7 @@
private final int mType; /* one of TYPE_RFCOMM etc */
private final int mPort; /* RFCOMM channel or L2CAP psm */
+ private final BluetoothDevice mDevice; /* remote device */
private final String mAddress; /* remote address */
private final boolean mAuth;
private final boolean mEncrypt;
@@ -51,68 +52,27 @@
private int mSocketData; /* used by native code only */
/**
- * Construct a secure RFCOMM socket ready to start an outgoing connection.
- * Call #connect on the returned #BluetoothSocket to begin the connection.
- * The remote device will be authenticated and communication on this socket
- * will be encrypted.
- * @param address remote Bluetooth address that this socket can connect to
- * @param port remote port
- * @return an RFCOMM BluetoothSocket
- * @throws IOException on error, for example Bluetooth not available, or
- * insufficient permissions.
- */
- public static BluetoothSocket createRfcommSocket(String address, int port)
- throws IOException {
- return new BluetoothSocket(TYPE_RFCOMM, -1, true, true, address, port);
- }
-
- /**
- * Construct an insecure RFCOMM socket ready to start an outgoing
- * connection.
- * Call #connect on the returned #BluetoothSocket to begin the connection.
- * The remote device will not be authenticated and communication on this
- * socket will not be encrypted.
- * @param address remote Bluetooth address that this socket can connect to
- * @param port remote port
- * @return An RFCOMM BluetoothSocket
- * @throws IOException On error, for example Bluetooth not available, or
- * insufficient permissions.
- */
- public static BluetoothSocket createInsecureRfcommSocket(String address, int port)
- throws IOException {
- return new BluetoothSocket(TYPE_RFCOMM, -1, false, false, address, port);
- }
-
- /**
- * Construct a SCO socket ready to start an outgoing connection.
- * Call #connect on the returned #BluetoothSocket to begin the connection.
- * @param address remote Bluetooth address that this socket can connect to
- * @return a SCO BluetoothSocket
- * @throws IOException on error, for example Bluetooth not available, or
- * insufficient permissions.
- */
- public static BluetoothSocket createScoSocket(String address, int port)
- throws IOException {
- return new BluetoothSocket(TYPE_SCO, -1, true, true, address, port);
- }
-
- /**
- * Construct a Bluetooth.
+ * Construct a BluetoothSocket.
* @param type type of socket
* @param fd fd to use for connected socket, or -1 for a new socket
* @param auth require the remote device to be authenticated
* @param encrypt require the connection to be encrypted
- * @param address remote Bluetooth address that this socket can connect to
+ * @param device remote device that this socket can connect to
* @param port remote port
* @throws IOException On error, for example Bluetooth not available, or
* insufficient priveleges
*/
- /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address,
- int port) throws IOException {
+ /*package*/ BluetoothSocket(int type, int fd, boolean auth, boolean encrypt,
+ BluetoothDevice device, int port) throws IOException {
mType = type;
mAuth = auth;
mEncrypt = encrypt;
- mAddress = address;
+ mDevice = device;
+ if (device == null) {
+ mAddress = null;
+ } else {
+ mAddress = device.getAddress();
+ }
mPort = port;
if (fd == -1) {
initSocketNative();
@@ -123,6 +83,22 @@
mOutputStream = new BluetoothOutputStream(this);
}
+ /**
+ * Construct a BluetoothSocket from address.
+ * @param type type of socket
+ * @param fd fd to use for connected socket, or -1 for a new socket
+ * @param auth require the remote device to be authenticated
+ * @param encrypt require the connection to be encrypted
+ * @param address remote device that this socket can connect to
+ * @param port remote port
+ * @throws IOException On error, for example Bluetooth not available, or
+ * insufficient priveleges
+ */
+ private BluetoothSocket(int type, int fd, boolean auth, boolean encrypt, String address,
+ int port) throws IOException {
+ this(type, fd, auth, encrypt, new BluetoothDevice(address), port);
+ }
+
@Override
protected void finalize() throws Throwable {
try {
@@ -154,12 +130,12 @@
}
/**
- * Return the address we are connecting, or connected, to.
- * @return Bluetooth address, or null if this socket has not yet attempted
+ * Return the remote device we are connecting, or connected, to.
+ * @return remote device, or null if this socket has not yet attempted
* or established a connection.
*/
- public String getAddress() {
- return mAddress;
+ public BluetoothDevice getRemoteDevice() {
+ return mDevice;
}
/**
diff --git a/core/java/android/bluetooth/HeadsetBase.java b/core/java/android/bluetooth/HeadsetBase.java
index f987ffd..29cf41d 100644
--- a/core/java/android/bluetooth/HeadsetBase.java
+++ b/core/java/android/bluetooth/HeadsetBase.java
@@ -31,7 +31,7 @@
*
* @hide
*/
-public class HeadsetBase {
+public final class HeadsetBase {
private static final String TAG = "Bluetooth HeadsetBase";
private static final boolean DBG = false;
@@ -42,8 +42,9 @@
private static int sAtInputCount = 0; /* TODO: Consider not using a static variable */
- private final BluetoothDevice mBluetooth;
- private final String mAddress;
+ private final BluetoothAdapter mAdapter;
+ private final BluetoothDevice mRemoteDevice;
+ private final String mAddress; // for native code
private final int mRfcommChannel;
private int mNativeData;
private Thread mEventThread;
@@ -73,12 +74,13 @@
private native void cleanupNativeDataNative();
- public HeadsetBase(PowerManager pm, BluetoothDevice bluetooth, String address,
- int rfcommChannel) {
+ public HeadsetBase(PowerManager pm, BluetoothAdapter adapter, BluetoothDevice device,
+ int rfcommChannel) {
mDirection = DIRECTION_OUTGOING;
mConnectTimestamp = System.currentTimeMillis();
- mBluetooth = bluetooth;
- mAddress = address;
+ mAdapter = adapter;
+ mRemoteDevice = device;
+ mAddress = device.getAddress();
mRfcommChannel = rfcommChannel;
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "HeadsetBase");
mWakeLock.setReferenceCounted(false);
@@ -88,12 +90,13 @@
}
/* Create from an already exisiting rfcomm connection */
- public HeadsetBase(PowerManager pm, BluetoothDevice bluetooth, String address, int socketFd,
- int rfcommChannel, Handler handler) {
+ public HeadsetBase(PowerManager pm, BluetoothAdapter adapter, BluetoothDevice device,
+ int socketFd, int rfcommChannel, Handler handler) {
mDirection = DIRECTION_INCOMING;
mConnectTimestamp = System.currentTimeMillis();
- mBluetooth = bluetooth;
- mAddress = address;
+ mAdapter = adapter;
+ mRemoteDevice = device;
+ mAddress = device.getAddress();
mRfcommChannel = rfcommChannel;
mEventThreadHandler = handler;
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "HeadsetBase");
@@ -252,12 +255,8 @@
return mEventThread != null;
}
- public String getAddress() {
- return mAddress;
- }
-
- public String getName() {
- return mBluetooth.getRemoteName(mAddress);
+ public BluetoothDevice getRemoteDevice() {
+ return mRemoteDevice;
}
public int getDirection() {
diff --git a/core/java/android/bluetooth/IBluetoothDevice.aidl b/core/java/android/bluetooth/IBluetooth.aidl
similarity index 98%
rename from core/java/android/bluetooth/IBluetoothDevice.aidl
rename to core/java/android/bluetooth/IBluetooth.aidl
index a78752b..9e05a87 100644
--- a/core/java/android/bluetooth/IBluetoothDevice.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -21,7 +21,7 @@
*
* {@hide}
*/
-interface IBluetoothDevice
+interface IBluetooth
{
boolean isEnabled();
int getBluetoothState();
diff --git a/core/java/android/bluetooth/IBluetoothA2dp.aidl b/core/java/android/bluetooth/IBluetoothA2dp.aidl
index 55ff27f..e6c6be2 100644
--- a/core/java/android/bluetooth/IBluetoothA2dp.aidl
+++ b/core/java/android/bluetooth/IBluetoothA2dp.aidl
@@ -16,16 +16,18 @@
package android.bluetooth;
+import android.bluetooth.BluetoothDevice;
+
/**
* System private API for Bluetooth A2DP service
*
* {@hide}
*/
interface IBluetoothA2dp {
- int connectSink(in String address);
- int disconnectSink(in String address);
- List<String> listConnectedSinks();
- int getSinkState(in String address);
- int setSinkPriority(in String address, int priority);
- int getSinkPriority(in String address);
+ int connectSink(in BluetoothDevice device);
+ int disconnectSink(in BluetoothDevice device);
+ BluetoothDevice[] getConnectedSinks(); // change to Set<> once AIDL supports
+ int getSinkState(in BluetoothDevice device);
+ int setSinkPriority(in BluetoothDevice device, int priority);
+ int getSinkPriority(in BluetoothDevice device);
}
diff --git a/core/java/android/bluetooth/IBluetoothHeadset.aidl b/core/java/android/bluetooth/IBluetoothHeadset.aidl
index 5f42fd6..6cccd50 100644
--- a/core/java/android/bluetooth/IBluetoothHeadset.aidl
+++ b/core/java/android/bluetooth/IBluetoothHeadset.aidl
@@ -16,6 +16,8 @@
package android.bluetooth;
+import android.bluetooth.BluetoothDevice;
+
/**
* System private API for Bluetooth Headset service
*
@@ -23,13 +25,13 @@
*/
interface IBluetoothHeadset {
int getState();
- String getHeadsetAddress();
- boolean connectHeadset(in String address);
+ BluetoothDevice getCurrentHeadset();
+ boolean connectHeadset(in BluetoothDevice device);
void disconnectHeadset();
- boolean isConnected(in String address);
+ boolean isConnected(in BluetoothDevice device);
boolean startVoiceRecognition();
boolean stopVoiceRecognition();
- boolean setPriority(in String address, int priority);
- int getPriority(in String address);
+ boolean setPriority(in BluetoothDevice device, int priority);
+ int getPriority(in BluetoothDevice device);
int getBatteryUsageHint();
}
diff --git a/core/java/android/bluetooth/IBluetoothPbap.aidl b/core/java/android/bluetooth/IBluetoothPbap.aidl
index 06cdb7b..7cc77d1 100644
--- a/core/java/android/bluetooth/IBluetoothPbap.aidl
+++ b/core/java/android/bluetooth/IBluetoothPbap.aidl
@@ -16,6 +16,8 @@
package android.bluetooth;
+import android.bluetooth.BluetoothDevice;
+
/**
* System private API for Bluetooth pbap service
*
@@ -23,8 +25,8 @@
*/
interface IBluetoothPbap {
int getState();
- String getPceAddress();
- boolean connectPce(in String address);
- void disconnectPce();
- boolean isConnected(in String address);
+ BluetoothDevice getClient();
+ boolean connect(in BluetoothDevice device);
+ void disconnect();
+ boolean isConnected(in BluetoothDevice device);
}
diff --git a/core/java/android/content/AbstractSyncableContentProvider.java b/core/java/android/content/AbstractSyncableContentProvider.java
index 218f501..808f30c 100644
--- a/core/java/android/content/AbstractSyncableContentProvider.java
+++ b/core/java/android/content/AbstractSyncableContentProvider.java
@@ -170,7 +170,7 @@
// AbstractGDataSyncAdapter, which will put acore into a crash loop
ArrayList<Account> gaiaAccounts = new ArrayList<Account>();
for (Account acct: accounts) {
- if (acct.mType.equals("com.google.GAIA")) {
+ if (acct.type.equals("com.google.GAIA")) {
gaiaAccounts.add(acct);
}
}
@@ -693,7 +693,7 @@
if (!accounts.containsKey(account)) {
int numDeleted;
numDeleted = db.delete(table, "_sync_account=? AND _sync_account_type=?",
- new String[]{account.mName, account.mType});
+ new String[]{account.name, account.type});
if (Config.LOGV) {
Log.v(TAG, "deleted " + numDeleted
+ " records from table " + table
@@ -726,7 +726,7 @@
// remove the data in the synced tables
for (String table : tables) {
db.delete(table, SYNC_ACCOUNT_WHERE_CLAUSE,
- new String[]{account.mName, account.mType});
+ new String[]{account.name, account.type});
}
db.setTransactionSuccessful();
} finally {
diff --git a/core/java/android/content/AbstractTableMerger.java b/core/java/android/content/AbstractTableMerger.java
index a3daa01e..9545fd7f 100644
--- a/core/java/android/content/AbstractTableMerger.java
+++ b/core/java/android/content/AbstractTableMerger.java
@@ -174,7 +174,7 @@
Cursor diffsCursor = null;
try {
// load the local database entries, so we can merge them with the server
- final String[] accountSelectionArgs = new String[]{account.mName, account.mType};
+ final String[] accountSelectionArgs = new String[]{account.name, account.type};
localCursor = mDb.query(mTable, syncDirtyProjection,
SELECT_MARKED, accountSelectionArgs, null, null,
mTable + "." + _SYNC_ID);
@@ -487,7 +487,7 @@
try {
if (deleteBySyncId) {
selectionArgs = new String[]{diffsCursor.getString(serverSyncIdColumn),
- account.mName, account.mType};
+ account.name, account.type};
c = mDb.query(mTable, new String[]{BaseColumns._ID}, SELECT_BY_SYNC_ID_AND_ACCOUNT,
selectionArgs, null, null, null);
} else {
@@ -534,7 +534,7 @@
SyncableContentProvider clientDiffs = mergeResult.tempContentProvider;
if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "generating client updates");
- final String[] accountSelectionArgs = new String[]{account.mName, account.mType};
+ final String[] accountSelectionArgs = new String[]{account.name, account.type};
// Generate the client updates and insertions
// Create a cursor for dirty records
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 98ed098..bf1a442 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1012,6 +1012,31 @@
}
/**
+ * Check if this account/provider is syncable.
+ * @return >0 if it is syncable, 0 if not, and <0 if the state isn't known yet.
+ */
+ public static int getIsSyncable(Account account, String authority) {
+ try {
+ return getContentService().getIsSyncable(account, authority);
+ } catch (RemoteException e) {
+ throw new RuntimeException("the ContentService should always be reachable", e);
+ }
+ }
+
+ /**
+ * Set whether this account/provider is syncable.
+ * @param syncable >0 denotes syncable, 0 means not syncable, <0 means unknown
+ */
+ public static void setIsSyncable(Account account, String authority, int syncable) {
+ try {
+ getContentService().setIsSyncable(account, authority, syncable);
+ } catch (RemoteException e) {
+ // exception ignored; if this is thrown then it means the runtime is in the midst of
+ // being restarted
+ }
+ }
+
+ /**
* Gets the master auto-sync setting that applies to all the providers and accounts.
* If this is false then the per-provider auto-sync setting is ignored.
*
diff --git a/core/java/android/content/ContentService.java b/core/java/android/content/ContentService.java
index 7a1ad2b..c4d8aaf 100644
--- a/core/java/android/content/ContentService.java
+++ b/core/java/android/content/ContentService.java
@@ -272,6 +272,37 @@
}
}
+ public int getIsSyncable(Account account, String providerName) {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
+ "no permission to read the sync settings");
+ long identityToken = clearCallingIdentity();
+ try {
+ SyncManager syncManager = getSyncManager();
+ if (syncManager != null) {
+ return syncManager.getSyncStorageEngine().getIsSyncable(
+ account, providerName);
+ }
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
+ return -1;
+ }
+
+ public void setIsSyncable(Account account, String providerName, int syncable) {
+ mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
+ "no permission to write the sync settings");
+ long identityToken = clearCallingIdentity();
+ try {
+ SyncManager syncManager = getSyncManager();
+ if (syncManager != null) {
+ syncManager.getSyncStorageEngine().setIsSyncable(
+ account, providerName, syncable);
+ }
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
+ }
+
public boolean getMasterSyncAutomatically() {
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
"no permission to read the sync settings");
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index dbe6fb0..8ab67c5 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1144,10 +1144,10 @@
public static final String SENSOR_SERVICE = "sensor";
/**
* Use with {@link #getSystemService} to retrieve a {@link
- * android.bluetooth.BluetoothDevice} for interacting with Bluetooth.
+ * android.bluetooth.BluetoothAdapter} for using Bluetooth.
*
* @see #getSystemService
- * @see android.bluetooth.BluetoothDevice
+ * @see android.bluetooth.BluetoothAdapter
* @hide
*/
public static final String BLUETOOTH_SERVICE = "bluetooth";
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index 658a5bc..b0f14c1 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -54,6 +54,18 @@
*/
void setSyncAutomatically(in Account account, String providerName, boolean sync);
+ /**
+ * Check if this account/provider is syncable.
+ * @return >0 if it is syncable, 0 if not, and <0 if the state isn't known yet.
+ */
+ int getIsSyncable(in Account account, String providerName);
+
+ /**
+ * Set whether this account/provider is syncable.
+ * @param syncable, >0 denotes syncable, 0 means not syncable, <0 means unknown
+ */
+ void setIsSyncable(in Account account, String providerName, int syncable);
+
void setMasterSyncAutomatically(boolean flag);
boolean getMasterSyncAutomatically();
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index f9b082f..a3517f8 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1838,6 +1838,14 @@
*/
public static final String CATEGORY_FRAMEWORK_INSTRUMENTATION_TEST =
"android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST";
+
+ /**
+ * Broadcast Action: The phone was docked or undocked. Includes the extra
+ * field {@link #EXTRA_DOCK_STATE}, containing the current dock state.
+ * @hide
+ */
+ public static final String ACTION_DOCK_EVENT = "android.intent.action.DOCK_EVENT";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Standard extra data keys.
@@ -1960,6 +1968,37 @@
public static final String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT";
/**
+ * Used as an int extra field in {@link android.content.Intent#ACTION_DOCK_EVENT}
+ * intents to request the dock state. Possible values are
+ * {@link android.content.Intent#ACTION_DOCK_STATE_UNDOCKED},
+ * {@link android.content.Intent#ACTION_DOCK_STATE_DESK}, or
+ * {@link android.content.Intent#ACTION_DOCK_STATE_CAR}.
+ * @hide
+ */
+ public static final String EXTRA_DOCK_STATE = "android.intent.extra.DOCK_STATE";
+
+ /**
+ * Used as an int value for {@link android.content.Intent#EXTRA_DOCK_STATE}
+ * to represent that the phone is not in any dock.
+ * @hide
+ */
+ public static final int EXTRA_DOCK_STATE_UNDOCKED = 0;
+
+ /**
+ * Used as an int value for {@link android.content.Intent#EXTRA_DOCK_STATE}
+ * to represent that the phone is in a desk dock.
+ * @hide
+ */
+ public static final int EXTRA_DOCK_STATE_DESK = 1;
+
+ /**
+ * Used as an int value for {@link android.content.Intent#EXTRA_DOCK_STATE}
+ * to represent that the phone is in a car dock.
+ * @hide
+ */
+ public static final int EXTRA_DOCK_STATE_CAR = 2;
+
+ /**
* Used as a parcelable extra field in {@link #ACTION_APP_ERROR}, containing
* the bug report.
*
diff --git a/core/java/android/content/SyncAdapterType.java b/core/java/android/content/SyncAdapterType.java
index 5a96003..d3f8230 100644
--- a/core/java/android/content/SyncAdapterType.java
+++ b/core/java/android/content/SyncAdapterType.java
@@ -27,6 +27,7 @@
public class SyncAdapterType implements Parcelable {
public final String authority;
public final String accountType;
+ public final boolean isUserFacing = true; // TODO: implement logic to set this
public SyncAdapterType(String authority, String accountType) {
if (TextUtils.isEmpty(authority)) {
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index d54e260..f50fd74 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -589,22 +589,21 @@
// if the url was specified then replace the list of authorities with just this authority
// or clear it if this authority isn't syncable
if (requestedAuthority != null) {
- final boolean isSyncable = syncableAuthorities.contains(requestedAuthority);
+ final boolean hasSyncAdapter = syncableAuthorities.contains(requestedAuthority);
syncableAuthorities.clear();
- if (isSyncable) syncableAuthorities.add(requestedAuthority);
+ if (hasSyncAdapter) syncableAuthorities.add(requestedAuthority);
}
for (String authority : syncableAuthorities) {
for (Account account : accounts) {
- if (mSyncAdapters.getServiceInfo(new SyncAdapterType(authority, account.mType))
+ boolean isSyncable = mSyncStorageEngine.getIsSyncable(account, authority) > 0;
+ if (!isSyncable) {
+ continue;
+ }
+ if (mSyncAdapters.getServiceInfo(new SyncAdapterType(authority, account.type))
!= null) {
scheduleSyncOperation(
new SyncOperation(account, source, authority, extras, delay));
- // TODO: remove this when Calendar supports multiple accounts. Until then
- // pretend that only the first account exists when syncing calendar.
- if ("calendar".equals(authority)) {
- break;
- }
}
}
}
@@ -1094,8 +1093,8 @@
for (int i=0; i<N; i++) {
SyncStorageEngine.PendingOperation op = ops.get(i);
pw.print(" #"); pw.print(i); pw.print(": account=");
- pw.print(op.account.mName); pw.print(":");
- pw.print(op.account.mType); pw.print(" authority=");
+ pw.print(op.account.name); pw.print(":");
+ pw.print(op.account.type); pw.print(" authority=");
pw.println(op.authority);
if (op.extras != null && op.extras.size() > 0) {
sb.setLength(0);
@@ -1125,8 +1124,8 @@
processedAccounts.add(curAccount);
- pw.print(" Account "); pw.print(authority.account.mName);
- pw.print(" "); pw.print(authority.account.mType);
+ pw.print(" Account "); pw.print(authority.account.name);
+ pw.print(" "); pw.print(authority.account.type);
pw.println(":");
for (int j=i; j<N; j++) {
status = statuses.get(j);
@@ -1248,9 +1247,9 @@
= mSyncStorageEngine.getAuthority(item.authorityId);
pw.print(" #"); pw.print(i+1); pw.print(": ");
if (authority != null) {
- pw.print(authority.account.mName);
+ pw.print(authority.account.name);
pw.print(":");
- pw.print(authority.account.mType);
+ pw.print(authority.account.type);
pw.print(" ");
pw.print(authority.authority);
} else {
@@ -1589,9 +1588,11 @@
final boolean syncAutomatically =
mSyncStorageEngine.getSyncAutomatically(op.account, op.authority)
&& mSyncStorageEngine.getMasterSyncAutomatically();
+ boolean isSyncable =
+ mSyncStorageEngine.getIsSyncable(op.account, op.authority) > 0;
boolean syncAllowed =
manualSync || (backgroundDataUsageAllowed && syncAutomatically);
- if (!syncAllowed) {
+ if (!syncAllowed || !isSyncable) {
if (isLoggable) {
Log.v(TAG, "runStateIdle: sync off, dropping " + op);
}
@@ -1636,7 +1637,7 @@
// connect to the sync adapter
SyncAdapterType syncAdapterType = new SyncAdapterType(op.authority,
- op.account.mType);
+ op.account.type);
RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
mSyncAdapters.getServiceInfo(syncAdapterType);
if (syncAdapterInfo == null) {
diff --git a/core/java/android/content/SyncStateContentProviderHelper.java b/core/java/android/content/SyncStateContentProviderHelper.java
index dc728ec..64bbe25 100644
--- a/core/java/android/content/SyncStateContentProviderHelper.java
+++ b/core/java/android/content/SyncStateContentProviderHelper.java
@@ -172,7 +172,7 @@
*/
public void copySyncState(SQLiteDatabase dbSrc, SQLiteDatabase dbDest,
Account account) {
- final String[] whereArgs = new String[]{account.mName, account.mType};
+ final String[] whereArgs = new String[]{account.name, account.type};
Cursor c = dbSrc.query(SYNC_STATE_TABLE,
new String[]{"_sync_account", "_sync_account_type", "data"},
ACCOUNT_WHERE, whereArgs, null, null, null);
@@ -209,7 +209,7 @@
public void discardSyncData(SQLiteDatabase db, Account account) {
if (account != null) {
- db.delete(SYNC_STATE_TABLE, ACCOUNT_WHERE, new String[]{account.mName, account.mType});
+ db.delete(SYNC_STATE_TABLE, ACCOUNT_WHERE, new String[]{account.name, account.type});
} else {
db.delete(SYNC_STATE_TABLE, null, null);
}
@@ -220,7 +220,7 @@
*/
public byte[] readSyncDataBytes(SQLiteDatabase db, Account account) {
Cursor c = db.query(SYNC_STATE_TABLE, null, ACCOUNT_WHERE,
- new String[]{account.mName, account.mType}, null, null, null);
+ new String[]{account.name, account.type}, null, null, null);
try {
if (c.moveToFirst()) {
return c.getBlob(c.getColumnIndexOrThrow("data"));
@@ -238,6 +238,6 @@
ContentValues values = new ContentValues();
values.put("data", data);
db.update(SYNC_STATE_TABLE, values, ACCOUNT_WHERE,
- new String[]{account.mName, account.mType});
+ new String[]{account.name, account.type});
}
}
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index 8cc0642..2647962 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -155,12 +155,15 @@
final String authority;
final int ident;
boolean enabled;
+ int syncable;
AuthorityInfo(Account account, String authority, int ident) {
this.account = account;
this.authority = authority;
this.ident = ident;
enabled = SYNC_ENABLED_DEFAULT;
+ // TODO: change the default to -1 when the syncadapters are changed to set this
+ syncable = 1;
}
}
@@ -392,6 +395,44 @@
reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
}
+ public int getIsSyncable(Account account, String providerName) {
+ synchronized (mAuthorities) {
+ if (account != null) {
+ AuthorityInfo authority = getAuthorityLocked(account, providerName,
+ "getIsSyncable");
+ if (authority == null) {
+ return -1;
+ }
+ return authority.syncable;
+ }
+
+ int i = mAuthorities.size();
+ while (i > 0) {
+ i--;
+ AuthorityInfo authority = mAuthorities.get(i);
+ if (authority.authority.equals(providerName)) {
+ return authority.syncable;
+ }
+ }
+ return -1;
+ }
+ }
+
+ public void setIsSyncable(Account account, String providerName, int syncable) {
+ int oldState;
+ synchronized (mAuthorities) {
+ AuthorityInfo authority = getOrCreateAuthorityLocked(account, providerName, -1, false);
+ oldState = authority.syncable;
+ authority.syncable = syncable;
+ writeAccountInfoLocked();
+ }
+
+ if (oldState <= 0 && syncable > 0) {
+ mContext.getContentResolver().requestSync(account, providerName, new Bundle());
+ }
+ reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+ }
+
public void setMasterSyncAutomatically(boolean flag) {
boolean old;
synchronized (mAuthorities) {
@@ -1064,10 +1105,12 @@
null, "authority");
String enabled = parser.getAttributeValue(
null, "enabled");
- AuthorityInfo authority = mAuthorities.get(id);
+ String syncable = parser.getAttributeValue(null, "syncable");
+ AuthorityInfo authority = mAuthorities.get(id);
if (DEBUG_FILE) Log.v(TAG, "Adding authority: account="
+ accountName + " auth=" + authorityName
- + " enabled=" + enabled);
+ + " enabled=" + enabled
+ + " syncable=" + syncable);
if (authority == null) {
if (DEBUG_FILE) Log.v(TAG, "Creating entry");
authority = getOrCreateAuthorityLocked(
@@ -1077,10 +1120,19 @@
if (authority != null) {
authority.enabled = enabled == null
|| Boolean.parseBoolean(enabled);
+ if ("unknown".equals(syncable)) {
+ authority.syncable = -1;
+ } else {
+ authority.syncable =
+ (syncable == null || Boolean.parseBoolean(enabled))
+ ? 1
+ : 0;
+ }
} else {
Log.w(TAG, "Failure adding authority: account="
+ accountName + " auth=" + authorityName
- + " enabled=" + enabled);
+ + " enabled=" + enabled
+ + " syncable=" + syncable);
}
}
}
@@ -1127,12 +1179,17 @@
AuthorityInfo authority = mAuthorities.get(i);
out.startTag(null, "authority");
out.attribute(null, "id", Integer.toString(authority.ident));
- out.attribute(null, "account", authority.account.mName);
- out.attribute(null, "type", authority.account.mType);
+ out.attribute(null, "account", authority.account.name);
+ out.attribute(null, "type", authority.account.type);
out.attribute(null, "authority", authority.authority);
if (!authority.enabled) {
out.attribute(null, "enabled", "false");
}
+ if (authority.syncable < 0) {
+ out.attribute(null, "syncable", "unknown");
+ } else if (authority.syncable == 0) {
+ out.attribute(null, "syncable", "false");
+ }
out.endTag(null, "authority");
}
@@ -1268,6 +1325,7 @@
AuthorityInfo authority = mAuthorities.get(i);
if (authority.authority.equals(provider)) {
authority.enabled = value == null || Boolean.parseBoolean(value);
+ authority.syncable = 1;
}
}
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 2354519..7d412a7 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -23,6 +23,7 @@
import org.xmlpull.v1.XmlPullParserException;
import android.content.pm.ApplicationInfo;
+import android.graphics.BitmapFactory;
import android.graphics.Movie;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ColorDrawable;
@@ -1707,7 +1708,8 @@
InputStream is = mAssets.openNonAsset(
value.assetCookie, file, AssetManager.ACCESS_BUFFER);
// System.out.println("Opened file " + file + ": " + is);
- dr = Drawable.createFromResourceStream(this, value, is, file);
+ dr = Drawable.createFromResourceStream(this, value, is,
+ file, null);
is.close();
// System.out.println("Created stream: " + dr);
} catch (Exception e) {
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 6b00900..da1115d 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -49,7 +49,6 @@
private String mApnType;
private boolean mEnabled;
- private boolean mTeardownRequested;
/**
* Create a new MobileDataStateTracker
@@ -66,7 +65,6 @@
TelephonyManager.getDefault().getNetworkTypeName());
mApnType = apnType;
mPhoneService = null;
- mTeardownRequested = false;
if(netType == ConnectivityManager.TYPE_MOBILE) {
mEnabled = true;
} else {
@@ -81,7 +79,9 @@
"net.eth0.dns3",
"net.eth0.dns4",
"net.gprs.dns1",
- "net.gprs.dns2"};
+ "net.gprs.dns2",
+ "net.ppp0.dns1",
+ "net.ppp0.dns2"};
}
@@ -160,9 +160,9 @@
switch (state) {
case DISCONNECTED:
- if(mTeardownRequested) {
+ if(isTeardownRequested()) {
mEnabled = false;
- mTeardownRequested = false;
+ setTeardownRequested(false);
}
setDetailedState(DetailedState.DISCONNECTED, reason, apnName);
@@ -277,7 +277,7 @@
*/
@Override
public boolean teardown() {
- mTeardownRequested = true;
+ setTeardownRequested(true);
return (setEnableApn(mApnType, false) != Phone.APN_REQUEST_FAILED);
}
@@ -286,7 +286,7 @@
*/
public boolean reconnect() {
mEnabled = true;
- mTeardownRequested = false;
+ setTeardownRequested(false);
mEnabled = (setEnableApn(mApnType, true) !=
Phone.APN_REQUEST_FAILED);
return mEnabled;
diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/Calendar.java
index 489d936..fab3f3d 100644
--- a/core/java/android/provider/Calendar.java
+++ b/core/java/android/provider/Calendar.java
@@ -174,7 +174,7 @@
return Calendar.Calendars.delete(cr,
Calendar.Calendars._SYNC_ACCOUNT + "=? AND "
+ Calendar.Calendars._SYNC_ACCOUNT_TYPE + "=?",
- new String[] {account.mName, account.mType});
+ new String[] {account.name, account.type});
}
/**
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 7a1a9e4..11cb87f 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1360,6 +1360,14 @@
* <P>Type: INTEGER</P>
*/
public static final String DELETED = "deleted";
+
+ /**
+ * Whether this group should be synced if the SYNC_EVERYTHING settings
+ * is false for this group's account.
+ * <p>
+ * Type: INTEGER (boolean)
+ */
+ public static final String SHOULD_SYNC = "should_sync";
}
/**
diff --git a/core/java/android/provider/Im.java b/core/java/android/provider/Im.java
index b11abe8..b1cf648 100644
--- a/core/java/android/provider/Im.java
+++ b/core/java/android/provider/Im.java
@@ -1620,6 +1620,9 @@
/** specifies the last heartbeat interval received from the server */
public static final String SETTING_HEARTBEAT_INTERVAL = "heartbeat_interval";
+ /** specifiy the JID resource used for Google Talk connection */
+ public static final String SETTING_JID_RESOURCE = "jid_resource";
+
/**
* Used for reliable message queue (RMQ). This is for storing the last rmq id received
* from the GTalk server
@@ -1861,6 +1864,14 @@
putLongValue(contentResolver, providerId, SETTING_HEARTBEAT_INTERVAL, interval);
}
+ /**
+ * A convenience method to set the jid resource.
+ */
+ public static void setJidResource(ContentResolver contentResolver,
+ long providerId, String jidResource) {
+ putStringValue(contentResolver, providerId, SETTING_JID_RESOURCE, jidResource);
+ }
+
public static class QueryMap extends ContentQueryMap {
private ContentResolver mContentResolver;
private long mProviderId;
@@ -2047,6 +2058,23 @@
}
/**
+ * Set the JID resource.
+ *
+ * @param jidResource the jid resource to be stored.
+ */
+ public void setJidResource(String jidResource) {
+ ProviderSettings.setJidResource(mContentResolver, mProviderId, jidResource);
+ }
+ /**
+ * Get the JID resource used for the Google Talk connection
+ *
+ * @return the JID resource stored.
+ */
+ public String getJidResource() {
+ return getString(SETTING_JID_RESOURCE, null);
+ }
+
+ /**
* Convenience function for retrieving a single settings value
* as a boolean.
*
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 85a2041..d3e4c4c 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -413,8 +413,6 @@
private static final String TAG = "Settings";
- private static String sJidResource = null;
-
public static class SettingNotFoundException extends AndroidException {
public SettingNotFoundException(String msg) {
super(msg);
@@ -3622,42 +3620,6 @@
}
/**
- * Returns the GTalk JID resource associated with this device.
- *
- * @return String the JID resource of the device. It uses the device IMEI in the computation
- * of the JID resource. If IMEI is not ready (i.e. telephony module not ready), we'll return
- * an empty string.
- * @hide
- */
- // TODO: we shouldn't not have a permenant Jid resource, as that's an easy target for
- // spams. We should change it once a while, like when we resubscribe to the subscription feeds
- // server.
- // (also, should this live in GTalkService?)
- public static synchronized String getJidResource() {
- if (sJidResource != null) {
- return sJidResource;
- }
-
- MessageDigest digest;
- try {
- digest = MessageDigest.getInstance("SHA-1");
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException("this should never happen");
- }
-
- String deviceId = TelephonyManager.getDefault().getDeviceId();
- if (TextUtils.isEmpty(deviceId)) {
- return "";
- }
-
- byte[] hashedDeviceId = digest.digest(deviceId.getBytes());
- String id = new String(Base64.encodeBase64(hashedDeviceId), 0, 12);
- id = id.replaceAll("/", "_");
- sJidResource = JID_RESOURCE_PREFIX + id;
- return sJidResource;
- }
-
- /**
* Returns the device ID that we should use when connecting to the mobile gtalk server.
* This is a string like "android-0x1242", where the hex string is the Android ID obtained
* from the GoogleLoginService.
diff --git a/core/java/android/provider/SubscribedFeeds.java b/core/java/android/provider/SubscribedFeeds.java
index f94b442..8e9f402 100644
--- a/core/java/android/provider/SubscribedFeeds.java
+++ b/core/java/android/provider/SubscribedFeeds.java
@@ -119,8 +119,8 @@
String authority, String service) {
ContentValues values = new ContentValues();
values.put(SubscribedFeeds.Feeds.FEED, feed);
- values.put(SubscribedFeeds.Feeds._SYNC_ACCOUNT, account.mName);
- values.put(SubscribedFeeds.Feeds._SYNC_ACCOUNT_TYPE, account.mType);
+ values.put(SubscribedFeeds.Feeds._SYNC_ACCOUNT, account.name);
+ values.put(SubscribedFeeds.Feeds._SYNC_ACCOUNT_TYPE, account.type);
values.put(SubscribedFeeds.Feeds.AUTHORITY, authority);
values.put(SubscribedFeeds.Feeds.SERVICE, service);
return resolver.insert(SubscribedFeeds.Feeds.CONTENT_URI, values);
@@ -134,7 +134,7 @@
where.append(" AND " + SubscribedFeeds.Feeds.FEED + "=?");
where.append(" AND " + SubscribedFeeds.Feeds.AUTHORITY + "=?");
return resolver.delete(SubscribedFeeds.Feeds.CONTENT_URI,
- where.toString(), new String[] {account.mName, account.mType, feed, authority});
+ where.toString(), new String[] {account.name, account.type, feed, authority});
}
public static int deleteFeeds(ContentResolver resolver,
@@ -144,7 +144,7 @@
where.append(" AND " + SubscribedFeeds.Feeds._SYNC_ACCOUNT_TYPE + "=?");
where.append(" AND " + SubscribedFeeds.Feeds.AUTHORITY + "=?");
return resolver.delete(SubscribedFeeds.Feeds.CONTENT_URI,
- where.toString(), new String[] {account.mName, account.mType, authority});
+ where.toString(), new String[] {account.name, account.type, authority});
}
/**
diff --git a/core/java/android/provider/SyncStateContract.java b/core/java/android/provider/SyncStateContract.java
index 7927e28..5c93af0 100644
--- a/core/java/android/provider/SyncStateContract.java
+++ b/core/java/android/provider/SyncStateContract.java
@@ -71,7 +71,7 @@
public static byte[] get(ContentProviderClient provider, Uri uri,
Account account) throws RemoteException {
Cursor c = provider.query(uri, DATA_PROJECTION, SELECT_BY_ACCOUNT,
- new String[]{account.mName, account.mType}, null);
+ new String[]{account.name, account.type}, null);
try {
if (c.moveToNext()) {
return c.getBlob(c.getColumnIndexOrThrow(Columns.DATA));
@@ -96,8 +96,8 @@
Account account, byte[] data) throws RemoteException {
ContentValues values = new ContentValues();
values.put(Columns.DATA, data);
- values.put(Columns.ACCOUNT_NAME, account.mName);
- values.put(Columns.ACCOUNT_TYPE, account.mType);
+ values.put(Columns.ACCOUNT_NAME, account.name);
+ values.put(Columns.ACCOUNT_TYPE, account.type);
provider.insert(uri, values);
}
@@ -116,8 +116,8 @@
values.put(Columns.DATA, data);
return ContentProviderOperation
.newInsert(uri)
- .withValue(Columns.ACCOUNT_NAME, account.mName)
- .withValue(Columns.ACCOUNT_TYPE, account.mType)
+ .withValue(Columns.ACCOUNT_NAME, account.name)
+ .withValue(Columns.ACCOUNT_TYPE, account.type)
.withValues(values)
.build();
}
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index 96ce9d6..d9fcb53 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -23,6 +23,7 @@
package android.server;
import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothError;
import android.bluetooth.BluetoothIntent;
@@ -40,9 +41,9 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.ArrayList;
import java.util.HashMap;
-import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
import java.util.UUID;
public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
@@ -67,26 +68,27 @@
private static int mSinkCount;
-
private final Context mContext;
private final IntentFilter mIntentFilter;
- private HashMap<String, Integer> mAudioDevices;
+ private HashMap<BluetoothDevice, Integer> mAudioDevices;
private final AudioManager mAudioManager;
- private final BluetoothDeviceService mBluetoothService;
+ private final BluetoothService mBluetoothService;
+ private final BluetoothAdapter mAdapter;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
- String address = intent.getStringExtra(BluetoothIntent.ADDRESS);
+ BluetoothDevice device =
+ intent.getParcelableExtra(BluetoothIntent.DEVICE);
if (action.equals(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION)) {
int state = intent.getIntExtra(BluetoothIntent.BLUETOOTH_STATE,
BluetoothError.ERROR);
switch (state) {
- case BluetoothDevice.BLUETOOTH_STATE_ON:
+ case BluetoothAdapter.BLUETOOTH_STATE_ON:
onBluetoothEnable();
break;
- case BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF:
+ case BluetoothAdapter.BLUETOOTH_STATE_TURNING_OFF:
onBluetoothDisable();
break;
}
@@ -95,28 +97,28 @@
BluetoothError.ERROR);
switch(bondState) {
case BluetoothDevice.BOND_BONDED:
- setSinkPriority(address, BluetoothA2dp.PRIORITY_AUTO);
+ setSinkPriority(device, BluetoothA2dp.PRIORITY_AUTO);
break;
case BluetoothDevice.BOND_BONDING:
case BluetoothDevice.BOND_NOT_BONDED:
- setSinkPriority(address, BluetoothA2dp.PRIORITY_OFF);
+ setSinkPriority(device, BluetoothA2dp.PRIORITY_OFF);
break;
}
} else if (action.equals(BluetoothIntent.REMOTE_DEVICE_CONNECTED_ACTION)) {
- if (getSinkPriority(address) > BluetoothA2dp.PRIORITY_OFF &&
- isSinkDevice(address)) {
+ if (getSinkPriority(device) > BluetoothA2dp.PRIORITY_OFF &&
+ isSinkDevice(device)) {
// This device is a preferred sink. Make an A2DP connection
// after a delay. We delay to avoid connection collisions,
// and to give other profiles such as HFP a chance to
// connect first.
- Message msg = Message.obtain(mHandler, MESSAGE_CONNECT_TO, address);
+ Message msg = Message.obtain(mHandler, MESSAGE_CONNECT_TO, device);
mHandler.sendMessageDelayed(msg, 6000);
}
}
}
};
- public BluetoothA2dpService(Context context, BluetoothDeviceService bluetoothService) {
+ public BluetoothA2dpService(Context context, BluetoothService bluetoothService) {
mContext = context;
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
@@ -130,12 +132,14 @@
throw new RuntimeException("Could not init BluetoothA2dpService");
}
+ mAdapter = (BluetoothAdapter) context.getSystemService(Context.BLUETOOTH_SERVICE);
+
mIntentFilter = new IntentFilter(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION);
mIntentFilter.addAction(BluetoothIntent.BOND_STATE_CHANGED_ACTION);
mIntentFilter.addAction(BluetoothIntent.REMOTE_DEVICE_CONNECTED_ACTION);
mContext.registerReceiver(mReceiver, mIntentFilter);
- mAudioDevices = new HashMap<String, Integer>();
+ mAudioDevices = new HashMap<BluetoothDevice, Integer>();
if (mBluetoothService.isEnabled())
onBluetoothEnable();
@@ -155,18 +159,18 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_CONNECT_TO:
- String address = (String)msg.obj;
+ BluetoothDevice device = (BluetoothDevice) msg.obj;
// check bluetooth is still on, device is still preferred, and
// nothing is currently connected
if (mBluetoothService.isEnabled() &&
- getSinkPriority(address) > BluetoothA2dp.PRIORITY_OFF &&
+ getSinkPriority(device) > BluetoothA2dp.PRIORITY_OFF &&
lookupSinksMatchingStates(new int[] {
BluetoothA2dp.STATE_CONNECTING,
BluetoothA2dp.STATE_CONNECTED,
BluetoothA2dp.STATE_PLAYING,
BluetoothA2dp.STATE_DISCONNECTING}).size() == 0) {
- log("Auto-connecting A2DP to sink " + address);
- connectSink(address);
+ log("Auto-connecting A2DP to sink " + device);
+ connectSink(device);
}
break;
}
@@ -185,8 +189,8 @@
return -1;
}
- private boolean isSinkDevice(String address) {
- String uuids[] = mBluetoothService.getRemoteUuids(address);
+ private boolean isSinkDevice(BluetoothDevice device) {
+ String uuids[] = mBluetoothService.getRemoteUuids(device.getAddress());
UUID uuid;
if (uuids != null) {
for (String deviceUuid: uuids) {
@@ -199,11 +203,11 @@
return false;
}
- private synchronized boolean addAudioSink (String address) {
- String path = mBluetoothService.getObjectPathFromAddress(address);
+ private synchronized boolean addAudioSink (BluetoothDevice device) {
+ String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
String propValues[] = (String []) getSinkPropertiesNative(path);
if (propValues == null) {
- Log.e(TAG, "Error while getting AudioSink properties for device: " + address);
+ Log.e(TAG, "Error while getting AudioSink properties for device: " + device);
return false;
}
Integer state = null;
@@ -214,8 +218,8 @@
break;
}
}
- mAudioDevices.put(address, state);
- handleSinkStateChange(address, BluetoothA2dp.STATE_DISCONNECTED, state);
+ mAudioDevices.put(device, state);
+ handleSinkStateChange(device, BluetoothA2dp.STATE_DISCONNECTED, state);
return true;
}
@@ -226,6 +230,7 @@
String [] paths = devices.split(",");
for (String path: paths) {
String address = mBluetoothService.getAddressFromObjectPath(path);
+ BluetoothDevice device = mAdapter.getRemoteDevice(address);
String []uuids = mBluetoothService.getRemoteUuids(address);
if (uuids != null)
for (String uuid: uuids) {
@@ -233,7 +238,7 @@
if (BluetoothUuid.isAudioSink(remoteUuid) ||
BluetoothUuid.isAudioSource(remoteUuid) ||
BluetoothUuid.isAdvAudioDist(remoteUuid)) {
- addAudioSink(address);
+ addAudioSink(device);
break;
}
}
@@ -244,36 +249,34 @@
private synchronized void onBluetoothDisable() {
if (!mAudioDevices.isEmpty()) {
- String [] addresses = new String[mAudioDevices.size()];
- addresses = mAudioDevices.keySet().toArray(addresses);
- for (String address : addresses) {
- int state = getSinkState(address);
+ BluetoothDevice[] devices = new BluetoothDevice[mAudioDevices.size()];
+ devices = mAudioDevices.keySet().toArray(devices);
+ for (BluetoothDevice device : devices) {
+ int state = getSinkState(device);
switch (state) {
case BluetoothA2dp.STATE_CONNECTING:
case BluetoothA2dp.STATE_CONNECTED:
case BluetoothA2dp.STATE_PLAYING:
- disconnectSinkNative(mBluetoothService.getObjectPathFromAddress(address));
- handleSinkStateChange(address,state, BluetoothA2dp.STATE_DISCONNECTED);
+ disconnectSinkNative(mBluetoothService.getObjectPathFromAddress(
+ device.getAddress()));
+ handleSinkStateChange(device, state, BluetoothA2dp.STATE_DISCONNECTED);
break;
case BluetoothA2dp.STATE_DISCONNECTING:
- handleSinkStateChange(address, BluetoothA2dp.STATE_DISCONNECTING,
- BluetoothA2dp.STATE_DISCONNECTED);
+ handleSinkStateChange(device, BluetoothA2dp.STATE_DISCONNECTING,
+ BluetoothA2dp.STATE_DISCONNECTED);
break;
}
}
mAudioDevices.clear();
}
- mAudioManager.setParameters(BLUETOOTH_ENABLED+"=false");
+ mAudioManager.setParameters(BLUETOOTH_ENABLED + "=false");
}
- public synchronized int connectSink(String address) {
+ public synchronized int connectSink(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH_ADMIN permission");
- if (DBG) log("connectSink(" + address + ")");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return BluetoothError.ERROR;
- }
+ if (DBG) log("connectSink(" + device + ")");
// ignore if there are any active sinks
if (lookupSinksMatchingStates(new int[] {
@@ -284,10 +287,10 @@
return BluetoothError.ERROR;
}
- if (mAudioDevices.get(address) == null && !addAudioSink(address))
+ if (mAudioDevices.get(device) == null && !addAudioSink(device))
return BluetoothError.ERROR;
- int state = mAudioDevices.get(address);
+ int state = mAudioDevices.get(device);
switch (state) {
case BluetoothA2dp.STATE_CONNECTED:
@@ -298,7 +301,7 @@
return BluetoothError.SUCCESS;
}
- String path = mBluetoothService.getObjectPathFromAddress(address);
+ String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
if (path == null)
return BluetoothError.ERROR;
@@ -309,19 +312,17 @@
return BluetoothError.SUCCESS;
}
- public synchronized int disconnectSink(String address) {
+ public synchronized int disconnectSink(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH_ADMIN permission");
- if (DBG) log("disconnectSink(" + address + ")");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return BluetoothError.ERROR;
- }
- String path = mBluetoothService.getObjectPathFromAddress(address);
+ if (DBG) log("disconnectSink(" + device + ")");
+
+ String path = mBluetoothService.getObjectPathFromAddress(device.getAddress());
if (path == null) {
return BluetoothError.ERROR;
}
- switch (getSinkState(address)) {
+ switch (getSinkState(device)) {
case BluetoothA2dp.STATE_DISCONNECTED:
return BluetoothError.ERROR;
case BluetoothA2dp.STATE_DISCONNECTING:
@@ -336,41 +337,36 @@
}
}
- public synchronized List<String> listConnectedSinks() {
+ public synchronized BluetoothDevice[] getConnectedSinks() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return lookupSinksMatchingStates(new int[] {BluetoothA2dp.STATE_CONNECTED,
- BluetoothA2dp.STATE_PLAYING});
+ Set<BluetoothDevice> sinks = lookupSinksMatchingStates(
+ new int[] {BluetoothA2dp.STATE_CONNECTED, BluetoothA2dp.STATE_PLAYING});
+ return sinks.toArray(new BluetoothDevice[sinks.size()]);
}
- public synchronized int getSinkState(String address) {
+ public synchronized int getSinkState(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return BluetoothError.ERROR;
- }
- Integer state = mAudioDevices.get(address);
+ Integer state = mAudioDevices.get(device);
if (state == null)
return BluetoothA2dp.STATE_DISCONNECTED;
return state;
}
- public synchronized int getSinkPriority(String address) {
+ public synchronized int getSinkPriority(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
- return BluetoothError.ERROR;
- }
return Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.getBluetoothA2dpSinkPriorityKey(address),
+ Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()),
BluetoothA2dp.PRIORITY_OFF);
}
- public synchronized int setSinkPriority(String address, int priority) {
+ public synchronized int setSinkPriority(BluetoothDevice device, int priority) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH_ADMIN permission");
- if (!BluetoothDevice.checkBluetoothAddress(address)) {
+ if (!BluetoothDevice.checkBluetoothAddress(device.getAddress())) {
return BluetoothError.ERROR;
}
return Settings.Secure.putInt(mContext.getContentResolver(),
- Settings.Secure.getBluetoothA2dpSinkPriorityKey(address), priority) ?
+ Settings.Secure.getBluetoothA2dpSinkPriorityKey(device.getAddress()), priority) ?
BluetoothError.SUCCESS : BluetoothError.ERROR;
}
@@ -386,20 +382,22 @@
return;
}
+ BluetoothDevice device = mAdapter.getRemoteDevice(address);
+
if (name.equals(PROPERTY_STATE)) {
int state = convertBluezSinkStringtoState(propValues[1]);
- if (mAudioDevices.get(address) == null) {
+ if (mAudioDevices.get(device) == null) {
// This is for an incoming connection for a device not known to us.
// We have authorized it and bluez state has changed.
- addAudioSink(address);
+ addAudioSink(device);
} else {
- int prevState = mAudioDevices.get(address);
- handleSinkStateChange(address, prevState, state);
+ int prevState = mAudioDevices.get(device);
+ handleSinkStateChange(device, prevState, state);
}
}
}
- private void handleSinkStateChange(String address, int prevState, int state) {
+ private void handleSinkStateChange(BluetoothDevice device, int prevState, int state) {
if (state != prevState) {
if (state == BluetoothA2dp.STATE_DISCONNECTED ||
state == BluetoothA2dp.STATE_DISCONNECTING) {
@@ -413,28 +411,28 @@
} else if (state == BluetoothA2dp.STATE_CONNECTED) {
mSinkCount ++;
}
- mAudioDevices.put(address, state);
+ mAudioDevices.put(device, state);
Intent intent = new Intent(BluetoothA2dp.SINK_STATE_CHANGED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
+ intent.putExtra(BluetoothIntent.DEVICE, device);
intent.putExtra(BluetoothA2dp.SINK_PREVIOUS_STATE, prevState);
intent.putExtra(BluetoothA2dp.SINK_STATE, state);
mContext.sendBroadcast(intent, BLUETOOTH_PERM);
- if (DBG) log("A2DP state : address: " + address + " State:" + prevState + "->" + state);
+ if (DBG) log("A2DP state : device: " + device + " State:" + prevState + "->" + state);
}
}
- private synchronized List<String> lookupSinksMatchingStates(int[] states) {
- List<String> sinks = new ArrayList<String>();
+ private synchronized Set<BluetoothDevice> lookupSinksMatchingStates(int[] states) {
+ Set<BluetoothDevice> sinks = new HashSet<BluetoothDevice>();
if (mAudioDevices.isEmpty()) {
return sinks;
}
- for (String path: mAudioDevices.keySet()) {
- int sinkState = getSinkState(path);
+ for (BluetoothDevice device: mAudioDevices.keySet()) {
+ int sinkState = getSinkState(device);
for (int state : states) {
if (state == sinkState) {
- sinks.add(path);
+ sinks.add(device);
break;
}
}
@@ -446,9 +444,9 @@
protected synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mAudioDevices.isEmpty()) return;
pw.println("Cached audio devices:");
- for (String address : mAudioDevices.keySet()) {
- int state = mAudioDevices.get(address);
- pw.println(address + " " + BluetoothA2dp.stateToString(state));
+ for (BluetoothDevice device : mAudioDevices.keySet()) {
+ int state = mAudioDevices.get(device);
+ pw.println(device + " " + BluetoothA2dp.stateToString(state));
}
}
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 1704733..6610d0e 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -18,6 +18,7 @@
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothError;
import android.bluetooth.BluetoothIntent;
@@ -46,8 +47,10 @@
private Thread mThread;
private boolean mStarted;
private boolean mInterrupted;
+
private final HashMap<String, Integer> mPasskeyAgentRequestData;
- private final BluetoothDeviceService mBluetoothService;
+ private final BluetoothService mBluetoothService;
+ private final BluetoothAdapter mAdapter;
private final Context mContext;
private static final int EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 1;
@@ -84,10 +87,12 @@
static { classInitNative(); }
private static native void classInitNative();
- /* pacakge */ BluetoothEventLoop(Context context, BluetoothDeviceService bluetoothService) {
+ /* pacakge */ BluetoothEventLoop(Context context, BluetoothAdapter adapter,
+ BluetoothService bluetoothService) {
mBluetoothService = bluetoothService;
mContext = context;
mPasskeyAgentRequestData = new HashMap();
+ mAdapter = adapter;
initializeNativeDataNative();
}
@@ -137,7 +142,7 @@
}
if (classValue != null) {
Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_FOUND_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
+ intent.putExtra(BluetoothIntent.DEVICE, mAdapter.getRemoteDevice(address));
intent.putExtra(BluetoothIntent.CLASS, Integer.valueOf(classValue));
intent.putExtra(BluetoothIntent.RSSI, rssiValue);
intent.putExtra(BluetoothIntent.NAME, name);
@@ -158,7 +163,7 @@
private void onDeviceDisappeared(String address) {
Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_DISAPPEARED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
+ intent.putExtra(BluetoothIntent.DEVICE, mAdapter.getRemoteDevice(address));
mContext.sendBroadcast(intent, BLUETOOTH_PERM);
}
@@ -251,7 +256,7 @@
if (pairable == null || discoverable == null)
return;
- int mode = BluetoothDeviceService.bluezStringToScanMode(
+ int mode = BluetoothService.bluezStringToScanMode(
pairable.equals("true"),
discoverable.equals("true"));
if (mode >= 0) {
@@ -299,15 +304,16 @@
Log.e(TAG, "onDevicePropertyChanged: Address of the remote device in null");
return;
}
+ BluetoothDevice device = mAdapter.getRemoteDevice(address);
if (name.equals("Name")) {
Intent intent = new Intent(BluetoothIntent.REMOTE_NAME_UPDATED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
+ intent.putExtra(BluetoothIntent.DEVICE, device);
intent.putExtra(BluetoothIntent.NAME, propValues[1]);
mContext.sendBroadcast(intent, BLUETOOTH_PERM);
mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
} else if (name.equals("Class")) {
Intent intent = new Intent(BluetoothIntent.REMOTE_DEVICE_CLASS_UPDATED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
+ intent.putExtra(BluetoothIntent.DEVICE, device);
intent.putExtra(BluetoothIntent.CLASS, propValues[1]);
mContext.sendBroadcast(intent, BLUETOOTH_PERM);
mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
@@ -318,7 +324,7 @@
} else {
intent = new Intent(BluetoothIntent.REMOTE_DEVICE_DISCONNECTED_ACTION);
}
- intent.putExtra(BluetoothIntent.ADDRESS, address);
+ intent.putExtra(BluetoothIntent.DEVICE, device);
mContext.sendBroadcast(intent, BLUETOOTH_PERM);
mBluetoothService.setRemoteDeviceProperty(address, name, propValues[1]);
} else if (name.equals("UUIDs")) {
@@ -351,7 +357,7 @@
address = address.toUpperCase();
mPasskeyAgentRequestData.put(address, new Integer(nativeData));
- if (mBluetoothService.getBluetoothState() == BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF) {
+ if (mBluetoothService.getBluetoothState() == BluetoothAdapter.BLUETOOTH_STATE_TURNING_OFF) {
// shutdown path
mBluetoothService.cancelPairingUserInput(address);
return null;
@@ -364,7 +370,7 @@
if (address == null) return;
Intent intent = new Intent(BluetoothIntent.PAIRING_REQUEST_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
+ intent.putExtra(BluetoothIntent.DEVICE, mAdapter.getRemoteDevice(address));
intent.putExtra(BluetoothIntent.PASSKEY, passkey);
intent.putExtra(BluetoothIntent.PAIRING_VARIANT,
BluetoothDevice.PAIRING_VARIANT_CONFIRMATION);
@@ -377,7 +383,7 @@
if (address == null) return;
Intent intent = new Intent(BluetoothIntent.PAIRING_REQUEST_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
+ intent.putExtra(BluetoothIntent.DEVICE, mAdapter.getRemoteDevice(address));
intent.putExtra(BluetoothIntent.PAIRING_VARIANT, BluetoothDevice.PAIRING_VARIANT_PASSKEY);
mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
return;
@@ -409,7 +415,7 @@
}
}
Intent intent = new Intent(BluetoothIntent.PAIRING_REQUEST_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
+ intent.putExtra(BluetoothIntent.DEVICE, mAdapter.getRemoteDevice(address));
intent.putExtra(BluetoothIntent.PAIRING_VARIANT, BluetoothDevice.PAIRING_VARIANT_PIN);
mContext.sendBroadcast(intent, BLUETOOTH_ADMIN_PERM);
return;
@@ -428,7 +434,8 @@
(BluetoothUuid.isAudioSink(uuid) || BluetoothUuid.isAvrcpController(uuid)
|| BluetoothUuid.isAdvAudioDist(uuid))) {
BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
- authorized = a2dp.getSinkPriority(address) > BluetoothA2dp.PRIORITY_OFF;
+ BluetoothDevice device = mAdapter.getRemoteDevice(address);
+ authorized = a2dp.getSinkPriority(device) > BluetoothA2dp.PRIORITY_OFF;
if (authorized) {
Log.i(TAG, "Allowing incoming A2DP / AVRCP connection from " + address);
} else {
diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothService.java
similarity index 92%
rename from core/java/android/server/BluetoothDeviceService.java
rename to core/java/android/server/BluetoothService.java
index d2b4447..acee3af2 100644
--- a/core/java/android/server/BluetoothDeviceService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -16,7 +16,7 @@
/**
* TODO: Move this to
- * java/services/com/android/server/BluetoothDeviceService.java
+ * java/services/com/android/server/BluetoothService.java
* and make the contructor package private again.
*
* @hide
@@ -25,11 +25,12 @@
package android.server;
import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothError;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothIntent;
-import android.bluetooth.IBluetoothDevice;
+import android.bluetooth.IBluetooth;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -55,8 +56,8 @@
import java.util.Iterator;
import java.util.Map;
-public class BluetoothDeviceService extends IBluetoothDevice.Stub {
- private static final String TAG = "BluetoothDeviceService";
+public class BluetoothService extends IBluetooth.Stub {
+ private static final String TAG = "BluetoothService";
private static final boolean DBG = true;
private int mNativeData;
@@ -65,11 +66,11 @@
private boolean mIsAirplaneSensitive;
private int mBluetoothState;
private boolean mRestart = false; // need to call enable() after disable()
-
- private final BondState mBondState = new BondState(); // local cache of bondings
private boolean mIsDiscovering;
- private final IBatteryStats mBatteryStats;
+ private BluetoothAdapter mAdapter; // constant after init()
+ private final BondState mBondState = new BondState(); // local cache of bondings
+ private final IBatteryStats mBatteryStats;
private final Context mContext;
private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
@@ -78,14 +79,14 @@
private static final int MESSAGE_REGISTER_SDP_RECORDS = 1;
private static final int MESSAGE_FINISH_DISABLE = 2;
- private Map<String, String> mProperties;
- private HashMap <String, Map<String, String>> mRemoteDeviceProperties;
+ private final Map<String, String> mAdapterProperties;
+ private final HashMap <String, Map<String, String>> mDeviceProperties;
static {
classInitNative();
}
- public BluetoothDeviceService(Context context) {
+ public BluetoothService(Context context) {
mContext = context;
// Need to do this in place of:
@@ -93,11 +94,7 @@
// Since we can not import BatteryStatsService from here. This class really needs to be
// moved to java/services/com/android/server/
mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
- }
- /** Must be called after construction, and before any other method.
- */
- public synchronized void init() {
initializeNativeDataNative();
if (isEnabledNative() == 1) {
@@ -105,12 +102,16 @@
disableNative();
}
- setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_OFF);
+ mBluetoothState = BluetoothAdapter.BLUETOOTH_STATE_OFF;
mIsDiscovering = false;
- mEventLoop = new BluetoothEventLoop(mContext, this);
+ mAdapterProperties = new HashMap<String, String>();
+ mDeviceProperties = new HashMap<String, Map<String,String>>();
registerForAirplaneMode();
- mProperties = new HashMap<String, String>();
- mRemoteDeviceProperties = new HashMap<String, Map<String,String>>();
+ }
+
+ public synchronized void initAfterRegistration() {
+ mAdapter = (BluetoothAdapter) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
+ mEventLoop = new BluetoothEventLoop(mContext, mAdapter, this);
}
@Override
@@ -127,7 +128,7 @@
public boolean isEnabled() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mBluetoothState == BluetoothDevice.BLUETOOTH_STATE_ON;
+ return mBluetoothState == BluetoothAdapter.BLUETOOTH_STATE_ON;
}
public int getBluetoothState() {
@@ -152,9 +153,9 @@
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
switch (mBluetoothState) {
- case BluetoothDevice.BLUETOOTH_STATE_OFF:
+ case BluetoothAdapter.BLUETOOTH_STATE_OFF:
return true;
- case BluetoothDevice.BLUETOOTH_STATE_ON:
+ case BluetoothAdapter.BLUETOOTH_STATE_ON:
break;
default:
return false;
@@ -162,11 +163,11 @@
if (mEnableThread != null && mEnableThread.isAlive()) {
return false;
}
- setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF);
+ setBluetoothState(BluetoothAdapter.BLUETOOTH_STATE_TURNING_OFF);
// Allow 3 seconds for profiles to gracefully disconnect
// TODO: Introduce a callback mechanism so that each profile can notify
- // BluetoothDeviceService when it is done shutting down
+ // BluetoothService when it is done shutting down
mHandler.sendMessageDelayed(
mHandler.obtainMessage(MESSAGE_FINISH_DISABLE, saveSetting ? 1 : 0, 0), 3000);
return true;
@@ -174,7 +175,7 @@
private synchronized void finishDisable(boolean saveSetting) {
- if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF) {
+ if (mBluetoothState != BluetoothAdapter.BLUETOOTH_STATE_TURNING_OFF) {
return;
}
mEventLoop.stop();
@@ -189,17 +190,17 @@
// update mode
Intent intent = new Intent(BluetoothIntent.SCAN_MODE_CHANGED_ACTION);
- intent.putExtra(BluetoothIntent.SCAN_MODE, BluetoothDevice.SCAN_MODE_NONE);
+ intent.putExtra(BluetoothIntent.SCAN_MODE, BluetoothAdapter.SCAN_MODE_NONE);
mContext.sendBroadcast(intent, BLUETOOTH_PERM);
mIsDiscovering = false;
- mProperties.clear();
+ mAdapterProperties.clear();
if (saveSetting) {
persistBluetoothOnSetting(false);
}
- setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_OFF);
+ setBluetoothState(BluetoothAdapter.BLUETOOTH_STATE_OFF);
// Log bluetooth off to battery stats.
long ident = Binder.clearCallingIdentity();
@@ -236,13 +237,13 @@
if (mIsAirplaneSensitive && isAirplaneModeOn()) {
return false;
}
- if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_OFF) {
+ if (mBluetoothState != BluetoothAdapter.BLUETOOTH_STATE_OFF) {
return false;
}
if (mEnableThread != null && mEnableThread.isAlive()) {
return false;
}
- setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_ON);
+ setBluetoothState(BluetoothAdapter.BLUETOOTH_STATE_TURNING_ON);
mEnableThread = new EnableThread(saveSetting);
mEnableThread.start();
return true;
@@ -250,7 +251,7 @@
/** Forcibly restart Bluetooth if it is on */
/* package */ synchronized void restart() {
- if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_ON) {
+ if (mBluetoothState != BluetoothAdapter.BLUETOOTH_STATE_ON) {
return;
}
mRestart = true;
@@ -356,8 +357,8 @@
mEnableThread = null;
setBluetoothState(res ?
- BluetoothDevice.BLUETOOTH_STATE_ON :
- BluetoothDevice.BLUETOOTH_STATE_OFF);
+ BluetoothAdapter.BLUETOOTH_STATE_ON :
+ BluetoothAdapter.BLUETOOTH_STATE_OFF);
if (res) {
// Update mode
@@ -410,7 +411,7 @@
));
public synchronized void loadBondState() {
- if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_TURNING_ON) {
+ if (mBluetoothState != BluetoothAdapter.BLUETOOTH_STATE_TURNING_ON) {
return;
}
String []bonds = null;
@@ -442,7 +443,7 @@
if (DBG) log(address + " bond state " + oldState + " -> " + state + " (" +
reason + ")");
Intent intent = new Intent(BluetoothIntent.BOND_STATE_CHANGED_ACTION);
- intent.putExtra(BluetoothIntent.ADDRESS, address);
+ intent.putExtra(BluetoothIntent.DEVICE, mAdapter.getRemoteDevice(address));
intent.putExtra(BluetoothIntent.BOND_STATE, state);
intent.putExtra(BluetoothIntent.BOND_PREVIOUS_STATE, oldState);
if (state == BluetoothDevice.BOND_NOT_BONDED) {
@@ -539,7 +540,7 @@
/*package*/synchronized void getAllProperties() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- mProperties.clear();
+ mAdapterProperties.clear();
String properties[] = (String [])getAdapterPropertiesNative();
// The String Array consists of key-value pairs.
@@ -568,17 +569,17 @@
} else {
newValue = properties[++i];
}
- mProperties.put(name, newValue);
+ mAdapterProperties.put(name, newValue);
}
// Add adapter object path property.
String adapterPath = getAdapterPathNative();
if (adapterPath != null)
- mProperties.put("ObjectPath", adapterPath + "/dev_");
+ mAdapterProperties.put("ObjectPath", adapterPath + "/dev_");
}
/* package */ synchronized void setProperty(String name, String value) {
- mProperties.put(name, value);
+ mAdapterProperties.put(name, value);
}
public synchronized boolean setName(String name) {
@@ -646,10 +647,10 @@
}
/*package*/ synchronized String getProperty (String name) {
- if (!mProperties.isEmpty())
- return mProperties.get(name);
+ if (!mAdapterProperties.isEmpty())
+ return mAdapterProperties.get(name);
getAllProperties();
- return mProperties.get(name);
+ return mAdapterProperties.get(name);
}
public synchronized String getAddress() {
@@ -678,7 +679,7 @@
if (!BluetoothDevice.checkBluetoothAddress(address)) {
return null;
}
- Map <String, String> properties = mRemoteDeviceProperties.get(address);
+ Map <String, String> properties = mDeviceProperties.get(address);
if (properties != null) return properties.get("Name");
return null;
}
@@ -805,7 +806,7 @@
}
/*package*/ boolean isRemoteDeviceInCache(String address) {
- return (mRemoteDeviceProperties.get(address) != null);
+ return (mDeviceProperties.get(address) != null);
}
/*package*/ String[] getRemoteDeviceProperties(String address) {
@@ -814,7 +815,7 @@
}
/*package*/ synchronized String getRemoteDeviceProperty(String address, String property) {
- Map<String, String> properties = mRemoteDeviceProperties.get(address);
+ Map<String, String> properties = mDeviceProperties.get(address);
if (properties != null) {
return properties.get(property);
} else {
@@ -835,7 +836,7 @@
/*
* We get a DeviceFound signal every time RSSI changes or name changes.
* Don't create a new Map object every time */
- Map<String, String> propertyValues = mRemoteDeviceProperties.get(address);
+ Map<String, String> propertyValues = mDeviceProperties.get(address);
if (propertyValues != null) {
propertyValues.clear();
} else {
@@ -864,19 +865,19 @@
}
propertyValues.put(name, newValue);
}
- mRemoteDeviceProperties.put(address, propertyValues);
+ mDeviceProperties.put(address, propertyValues);
}
/* package */ void removeRemoteDeviceProperties(String address) {
- mRemoteDeviceProperties.remove(address);
+ mDeviceProperties.remove(address);
}
/* package */ synchronized void setRemoteDeviceProperty(String address, String name,
String value) {
- Map <String, String> propVal = mRemoteDeviceProperties.get(address);
+ Map <String, String> propVal = mDeviceProperties.get(address);
if (propVal != null) {
propVal.put(name, value);
- mRemoteDeviceProperties.put(address, propVal);
+ mDeviceProperties.put(address, propVal);
} else {
Log.e(TAG, "setRemoteDeviceProperty for a device not in cache:" + address);
}
@@ -1059,16 +1060,16 @@
pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive + "\n");
switch(mBluetoothState) {
- case BluetoothDevice.BLUETOOTH_STATE_OFF:
+ case BluetoothAdapter.BLUETOOTH_STATE_OFF:
pw.println("\nBluetooth OFF\n");
return;
- case BluetoothDevice.BLUETOOTH_STATE_TURNING_ON:
+ case BluetoothAdapter.BLUETOOTH_STATE_TURNING_ON:
pw.println("\nBluetooth TURNING ON\n");
return;
- case BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF:
+ case BluetoothAdapter.BLUETOOTH_STATE_TURNING_OFF:
pw.println("\nBluetooth TURNING OFF\n");
return;
- case BluetoothDevice.BLUETOOTH_STATE_ON:
+ case BluetoothAdapter.BLUETOOTH_STATE_ON:
pw.println("\nBluetooth ON\n");
}
@@ -1079,7 +1080,7 @@
BluetoothHeadset headset = new BluetoothHeadset(mContext, null);
pw.println("\n--Known devices--");
- for (String address : mRemoteDeviceProperties.keySet()) {
+ for (String address : mDeviceProperties.keySet()) {
pw.printf("%s %10s (%d) %s\n", address,
toBondStateString(mBondState.getBondState(address)),
mBondState.getAttempt(address),
@@ -1113,7 +1114,7 @@
pw.println("getState() = STATE_ERROR");
break;
}
- pw.println("getHeadsetAddress() = " + headset.getHeadsetAddress());
+ pw.println("getCurrentHeadset() = " + headset.getCurrentHeadset());
pw.println("getBatteryUsageHint() = " + headset.getBatteryUsageHint());
headset.close();
@@ -1121,20 +1122,20 @@
/* package */ static int bluezStringToScanMode(boolean pairable, boolean discoverable) {
if (pairable && discoverable)
- return BluetoothDevice.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
+ return BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE;
else if (pairable && !discoverable)
- return BluetoothDevice.SCAN_MODE_CONNECTABLE;
+ return BluetoothAdapter.SCAN_MODE_CONNECTABLE;
else
- return BluetoothDevice.SCAN_MODE_NONE;
+ return BluetoothAdapter.SCAN_MODE_NONE;
}
/* package */ static String scanModeToBluezString(int mode) {
switch (mode) {
- case BluetoothDevice.SCAN_MODE_NONE:
+ case BluetoothAdapter.SCAN_MODE_NONE:
return "off";
- case BluetoothDevice.SCAN_MODE_CONNECTABLE:
+ case BluetoothAdapter.SCAN_MODE_CONNECTABLE:
return "connectable";
- case BluetoothDevice.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
+ case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
return "discoverable";
}
return null;
diff --git a/core/java/android/server/search/SearchDialogWrapper.java b/core/java/android/server/search/SearchDialogWrapper.java
index 49718cb..9ee64af 100644
--- a/core/java/android/server/search/SearchDialogWrapper.java
+++ b/core/java/android/server/search/SearchDialogWrapper.java
@@ -58,6 +58,7 @@
// data[KEY_INITIAL_QUERY]: initial query
// data[KEY_LAUNCH_ACTIVITY]: launch activity
// data[KEY_APP_SEARCH_DATA]: app search data
+ // data[KEY_TRIGGER]: 0 = false, 1 = true
private static final int MSG_START_SEARCH = 1;
// Takes no arguments
private static final int MSG_STOP_SEARCH = 2;
@@ -69,7 +70,8 @@
private static final String KEY_INITIAL_QUERY = "q";
private static final String KEY_LAUNCH_ACTIVITY = "a";
private static final String KEY_APP_SEARCH_DATA = "d";
- private static final String KEY_IDENT= "i";
+ private static final String KEY_IDENT = "i";
+ private static final String KEY_TRIGGER = "t";
// Context used for getting search UI resources
private final Context mContext;
@@ -173,7 +175,8 @@
final Bundle appSearchData,
final boolean globalSearch,
final ISearchManagerCallback searchManagerCallback,
- int ident) {
+ int ident,
+ boolean trigger) {
if (DBG) debug("startSearch()");
Message msg = Message.obtain();
msg.what = MSG_START_SEARCH;
@@ -185,6 +188,7 @@
msgData.putParcelable(KEY_LAUNCH_ACTIVITY, launchActivity);
msgData.putBundle(KEY_APP_SEARCH_DATA, appSearchData);
msgData.putInt(KEY_IDENT, ident);
+ msgData.putInt(KEY_TRIGGER, trigger ? 1 : 0);
mSearchUiThread.sendMessage(msg);
// be a little more eager in setting this so isVisible will return the correct value if
// called immediately after startSearch
@@ -268,8 +272,9 @@
boolean globalSearch = msg.arg2 != 0;
ISearchManagerCallback searchManagerCallback = (ISearchManagerCallback) msg.obj;
int ident = msgData.getInt(KEY_IDENT);
+ boolean trigger = msgData.getInt(KEY_TRIGGER) != 0;
performStartSearch(initialQuery, selectInitialQuery, launchActivity,
- appSearchData, globalSearch, searchManagerCallback, ident);
+ appSearchData, globalSearch, searchManagerCallback, ident, trigger);
}
}
@@ -284,7 +289,8 @@
Bundle appSearchData,
boolean globalSearch,
ISearchManagerCallback searchManagerCallback,
- int ident) {
+ int ident,
+ boolean trigger) {
if (DBG) debug("performStartSearch()");
registerBroadcastReceiver();
@@ -301,6 +307,9 @@
mSearchDialog.show(initialQuery, selectInitialQuery, launchActivity, appSearchData,
globalSearch);
mVisible = true;
+ if (trigger) {
+ mSearchDialog.launchQuerySearch();
+ }
}
/**
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index afed4a4..5e0b3d2 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -233,7 +233,31 @@
appSearchData,
globalSearch,
searchManagerCallback,
- ident);
+ ident,
+ false); // don't trigger
+ }
+
+ /**
+ * Launches the search UI and triggers the search, as if the user had clicked on the
+ * search button within the dialog.
+ *
+ * @see SearchManager#triggerSearch(String, android.content.ComponentName, android.os.Bundle)
+ */
+ public void triggerSearch(String query,
+ ComponentName launchActivity,
+ Bundle appSearchData,
+ ISearchManagerCallback searchManagerCallback,
+ boolean globalSearch,
+ int ident) {
+ getSearchDialog().startSearch(
+ query,
+ false,
+ launchActivity,
+ appSearchData,
+ globalSearch,
+ searchManagerCallback,
+ ident,
+ true); // triger search after launching
}
/**
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 595b10c..80a154b 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -30,6 +30,7 @@
import android.util.Log;
import android.view.Gravity;
import android.view.IWindowSession;
+import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.ViewGroup;
@@ -58,6 +59,8 @@
private static final int MSG_UPDATE_SURFACE = 10000;
private static final int MSG_VISIBILITY_CHANGED = 10010;
private static final int MSG_WALLPAPER_OFFSETS = 10020;
+ private static final int MSG_WINDOW_RESIZED = 10030;
+ private static final int MSG_TOUCH_EVENT = 10040;
/**
* The actual implementation of a wallpaper. A wallpaper service may
@@ -86,6 +89,8 @@
int mType;
int mCurWidth;
int mCurHeight;
+ int mWindowFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+ int mCurWindowFlags = mWindowFlags;
boolean mDestroyReportNeeded;
final Rect mVisibleInsets = new Rect();
final Rect mWinFrame = new Rect();
@@ -99,6 +104,7 @@
boolean mOffsetMessageEnqueued;
float mPendingXOffset;
float mPendingYOffset;
+ MotionEvent mPendingMove;
final BaseSurfaceHolder mSurfaceHolder = new BaseSurfaceHolder() {
@@ -130,6 +136,35 @@
};
final BaseIWindow mWindow = new BaseIWindow() {
+ @Override
+ public boolean onDispatchPointer(MotionEvent event, long eventTime,
+ boolean callWhenDone) {
+ synchronized (mLock) {
+ if (event.getAction() == MotionEvent.ACTION_MOVE) {
+ if (mPendingMove != null) {
+ mCaller.removeMessages(MSG_TOUCH_EVENT, mPendingMove);
+ mPendingMove.recycle();
+ }
+ mPendingMove = event;
+ } else {
+ mPendingMove = null;
+ }
+ Message msg = mCaller.obtainMessageO(MSG_TOUCH_EVENT,
+ event);
+ mCaller.sendMessage(msg);
+ }
+ return false;
+ }
+
+ @Override
+ public void resized(int w, int h, Rect coveredInsets,
+ Rect visibleInsets, boolean reportDraw) {
+ Message msg = mCaller.obtainMessageI(MSG_WINDOW_RESIZED,
+ reportDraw ? 1 : 0);
+ mCaller.sendMessage(msg);
+ }
+
+ @Override
public void dispatchAppVisibility(boolean visible) {
Message msg = mCaller.obtainMessageI(MSG_VISIBILITY_CHANGED,
visible ? 1 : 0);
@@ -177,6 +212,22 @@
}
/**
+ * Control whether this wallpaper will receive raw touch events
+ * from the window manager as the user interacts with the window
+ * that is currently displaying the wallpaper. By default they
+ * are turned off. If enabled, the events will be received in
+ * {@link #onTouchEvent(MotionEvent)}.
+ */
+ public void setTouchEventsEnabled(boolean enabled) {
+ mWindowFlags = enabled
+ ? (mWindowFlags&~WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
+ : (mWindowFlags|WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
+ if (mCreated) {
+ updateSurface(false);
+ }
+ }
+
+ /**
* Called once to initialize the engine. After returning, the
* engine's surface will be created by the framework.
*/
@@ -200,6 +251,16 @@
}
/**
+ * Called as the user performs touch-screen interaction with the
+ * window that is currently showing this wallpaper. Note that the
+ * events you receive here are driven by the actual application the
+ * user is interacting with, so if it is slow you will get viewer
+ * move events.
+ */
+ public void onTouchEvent(MotionEvent event) {
+ }
+
+ /**
* Called to inform you of the wallpaper's offsets changing
* within its contain, corresponding to the container's
* call to {@link WallpaperManager#setWallpaperOffsets(IBinder, float, float)
@@ -238,9 +299,11 @@
final boolean creating = !mCreated;
final boolean formatChanged = mFormat != mSurfaceHolder.getRequestedFormat();
- final boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
+ boolean sizeChanged = mWidth != myWidth || mHeight != myHeight;
final boolean typeChanged = mType != mSurfaceHolder.getRequestedType();
- if (force || creating || formatChanged || sizeChanged || typeChanged) {
+ final boolean flagsChanged = mCurWindowFlags != mWindowFlags;
+ if (force || creating || formatChanged || sizeChanged || typeChanged
+ || flagsChanged) {
if (DEBUG) Log.i(TAG, "Changes: creating=" + creating
+ " format=" + formatChanged + " size=" + sizeChanged);
@@ -251,20 +314,19 @@
mFormat = mSurfaceHolder.getRequestedFormat();
mType = mSurfaceHolder.getRequestedType();
- // Scaling/Translate window's layout here because mLayout is not used elsewhere.
-
- // Places the window relative
mLayout.x = 0;
mLayout.y = 0;
mLayout.width = myWidth;
mLayout.height = myHeight;
mLayout.format = mFormat;
- mLayout.flags |=WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
- | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
- ;
+
+ mCurWindowFlags = mWindowFlags;
+ mLayout.flags = mWindowFlags
+ | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
+ | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ ;
mLayout.memoryType = mType;
mLayout.token = mWindowToken;
@@ -286,8 +348,16 @@
if (DEBUG) Log.i(TAG, "New surface: " + mSurfaceHolder.mSurface
+ ", frame=" + mWinFrame);
- mCurWidth = mWinFrame.width();
- mCurHeight = mWinFrame.height();
+ int w = mWinFrame.width();
+ if (mCurWidth != w) {
+ sizeChanged = true;
+ mCurWidth = w;
+ }
+ int h = mWinFrame.height();
+ if (mCurHeight != h) {
+ sizeChanged = true;
+ mCurHeight = h;
+ }
mSurfaceHolder.mSurfaceLock.unlock();
@@ -312,7 +382,7 @@
}
}
}
- if (creating || formatChanged || sizeChanged) {
+ if (force || creating || formatChanged || sizeChanged) {
onSurfaceChanged(mSurfaceHolder, mFormat,
mCurWidth, mCurHeight);
if (callbacks != null) {
@@ -452,6 +522,26 @@
final int yPixels = availh > 0 ? -(int)(availh*yOffset+.5f) : 0;
mEngine.onOffsetsChanged(xOffset, yOffset, xPixels, yPixels);
} break;
+ case MSG_WINDOW_RESIZED: {
+ final boolean reportDraw = message.arg1 != 0;
+ mEngine.updateSurface(true);
+ if (reportDraw) {
+ try {
+ mEngine.mSession.finishDrawing(mEngine.mWindow);
+ } catch (RemoteException e) {
+ }
+ }
+ } break;
+ case MSG_TOUCH_EVENT: {
+ MotionEvent ev = (MotionEvent)message.obj;
+ synchronized (mEngine.mLock) {
+ if (mEngine.mPendingMove == ev) {
+ mEngine.mPendingMove = null;
+ }
+ }
+ mEngine.onTouchEvent(ev);
+ ev.recycle();
+ } break;
default :
Log.w(TAG, "Unknown message type " + message.what);
}
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index 843754b..944f735 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -19,6 +19,7 @@
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
+import android.text.style.ParagraphStyle;
import android.util.FloatMath;
/**
@@ -262,6 +263,14 @@
TextUtils.recycle(temp);
+ if (boring && text instanceof Spanned) {
+ Spanned sp = (Spanned) text;
+ Object[] styles = sp.getSpans(0, text.length(), ParagraphStyle.class);
+ if (styles.length > 0) {
+ boring = false;
+ }
+ }
+
if (boring) {
Metrics fm = metrics;
if (fm == null) {
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index dd5a440..74f01cc 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -24,6 +24,9 @@
/**
* A structure describing general information about a display, such as its
* size, density, and font scaling.
+ * <p>To access the DisplayMetrics members, initialize an object like this:</p>
+ * <pre> DisplayMetrics metrics = new DisplayMetrics();
+ * getWindowManager().getDefaultDisplay().getMetrics(metrics);</pre>
*/
public class DisplayMetrics {
/**
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index ec2036e..ebc5f7b 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -46,8 +46,8 @@
void resized(int w, int h, in Rect coveredInsets, in Rect visibleInsets,
boolean reportDraw);
void dispatchKey(in KeyEvent event);
- void dispatchPointer(in MotionEvent event, long eventTime);
- void dispatchTrackball(in MotionEvent event, long eventTime);
+ void dispatchPointer(in MotionEvent event, long eventTime, boolean callWhenDone);
+ void dispatchTrackball(in MotionEvent event, long eventTime, boolean callWhenDone);
void dispatchAppVisibility(boolean visible);
void dispatchGetNewSurface();
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index e8bfa6a..b2f0c60 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -552,6 +552,44 @@
}
/**
+ * Create a new MotionEvent, copying from an existing one, but not including
+ * any historical point information.
+ */
+ static public MotionEvent obtainNoHistory(MotionEvent o) {
+ MotionEvent ev = obtain();
+ ev.mDeviceId = o.mDeviceId;
+ ev.mEdgeFlags = o.mEdgeFlags;
+ ev.mDownTime = o.mDownTime;
+ ev.mEventTimeNano = o.mEventTimeNano;
+ ev.mAction = o.mAction;
+ ev.mNumPointers = o.mNumPointers;
+ ev.mRawX = o.mRawX;
+ ev.mRawY = o.mRawY;
+ ev.mMetaState = o.mMetaState;
+ ev.mXPrecision = o.mXPrecision;
+ ev.mYPrecision = o.mYPrecision;
+
+ ev.mNumSamples = 1;
+ ev.mTimeSamples[0] = o.mTimeSamples[0];
+
+ final int NP = (ev.mNumPointers=o.mNumPointers);
+ if (ev.mPointerIdentifiers.length >= NP) {
+ System.arraycopy(o.mPointerIdentifiers, 0, ev.mPointerIdentifiers, 0, NP);
+ } else {
+ ev.mPointerIdentifiers = (int[])o.mPointerIdentifiers.clone();
+ }
+
+ final int ND = NP * NUM_SAMPLE_DATA;
+ if (ev.mDataSamples.length >= ND) {
+ System.arraycopy(o.mDataSamples, 0, ev.mDataSamples, 0, ND);
+ } else {
+ ev.mDataSamples = (float[])o.mDataSamples.clone();
+ }
+
+ return ev;
+ }
+
+ /**
* Recycle the MotionEvent, to be re-used by a later caller. After calling
* this function you must not ever touch the event again.
*/
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index c4bf642..9ec1013 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -34,12 +34,18 @@
/** Surface is created hidden */
public static final int HIDDEN = 0x00000004;
- /** The surface is to be used by hardware accelerators or DMA engines */
+ /** The surface is to be used by hardware accelerators or DMA engines
+ * @deprecated this is ignored, this value is set automatically when needed.
+ */
+ @Deprecated
public static final int HARDWARE = 0x00000010;
/** Implies "HARDWARE", the surface is to be used by the GPU
* additionally the backbuffer is never preserved for these
- * surfaces. */
+ * surfaces.
+ * @deprecated this is ignored, this value is set automatically when needed.
+ */
+ @Deprecated
public static final int GPU = 0x00000028;
/** The surface contains secure content, special measures will
diff --git a/core/java/android/view/SurfaceHolder.java b/core/java/android/view/SurfaceHolder.java
index 3d0dda3..64a10d1 100644
--- a/core/java/android/view/SurfaceHolder.java
+++ b/core/java/android/view/SurfaceHolder.java
@@ -38,8 +38,6 @@
* Surface type.
*
* @see #SURFACE_TYPE_NORMAL
- * @see #SURFACE_TYPE_HARDWARE
- * @see #SURFACE_TYPE_GPU
* @see #SURFACE_TYPE_PUSH_BUFFERS
*/
@@ -47,9 +45,15 @@
* contiguous, cached/buffered RAM. */
public static final int SURFACE_TYPE_NORMAL = MEMORY_TYPE_NORMAL;
/** Surface type: creates a suited to be used with DMA engines and
- * hardware accelerators. */
+ * hardware accelerators.
+ * @deprecated this is ignored, this value is set automatically when needed.
+ */
+ @Deprecated
public static final int SURFACE_TYPE_HARDWARE = MEMORY_TYPE_HARDWARE;
- /** Surface type: creates a surface suited to be used with the GPU */
+ /** Surface type: creates a surface suited to be used with the GPU
+ * @deprecated this is ignored, this value is set automatically when needed.
+ */
+ @Deprecated
public static final int SURFACE_TYPE_GPU = MEMORY_TYPE_GPU;
/** Surface type: creates a "push" surface, that is a surface that
* doesn't owns its buffers. With such a surface lockCanvas will fail. */
@@ -139,11 +143,7 @@
public boolean isCreating();
/**
- * Sets the surface's type. Surfaces intended to be used with OpenGL ES
- * should be of SURFACE_TYPE_GPU, surfaces accessed by DMA engines and
- * hardware accelerators should be of type SURFACE_TYPE_HARDWARE.
- * Failing to set the surface's type appropriately could result in
- * degraded performance or failure.
+ * Sets the surface's type.
*
* @param type The surface's memory type.
*/
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 4840f27..ea879ed9 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -481,7 +481,8 @@
}
}
- public void dispatchPointer(MotionEvent event, long eventTime) {
+ public void dispatchPointer(MotionEvent event, long eventTime,
+ boolean callWhenDone) {
Log.w("SurfaceView", "Unexpected pointer event in surface: " + event);
//if (mSession != null && mSurface != null) {
// try {
@@ -491,7 +492,8 @@
//}
}
- public void dispatchTrackball(MotionEvent event, long eventTime) {
+ public void dispatchTrackball(MotionEvent event, long eventTime,
+ boolean callWhenDone) {
Log.w("SurfaceView", "Unexpected trackball event in surface: " + event);
//if (mSession != null && mSurface != null) {
// try {
@@ -573,9 +575,14 @@
public void setType(int type) {
switch (type) {
- case SURFACE_TYPE_NORMAL:
case SURFACE_TYPE_HARDWARE:
case SURFACE_TYPE_GPU:
+ // these are deprecated, treat as "NORMAL"
+ type = SURFACE_TYPE_NORMAL;
+ break;
+ }
+ switch (type) {
+ case SURFACE_TYPE_NORMAL:
case SURFACE_TYPE_PUSH_BUFFERS:
mRequestedType = type;
if (mWindow != null) {
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 4623bb5..3b78060 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1637,8 +1637,8 @@
break;
case DISPATCH_POINTER: {
MotionEvent event = (MotionEvent)msg.obj;
-
- boolean didFinish;
+ boolean callWhenDone = msg.arg1 != 0;
+
if (event == null) {
try {
long timeBeforeGettingEvents;
@@ -1654,9 +1654,7 @@
}
} catch (RemoteException e) {
}
- didFinish = true;
- } else {
- didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE;
+ callWhenDone = false;
}
if (event != null && mTranslator != null) {
mTranslator.translateEventInScreenToAppWindow(event);
@@ -1728,7 +1726,7 @@
}
}
} finally {
- if (!didFinish) {
+ if (callWhenDone) {
try {
sWindowSession.finishKey(mWindow);
} catch (RemoteException e) {
@@ -1743,7 +1741,7 @@
}
} break;
case DISPATCH_TRACKBALL:
- deliverTrackballEvent((MotionEvent)msg.obj);
+ deliverTrackballEvent((MotionEvent)msg.obj, msg.arg1 != 0);
break;
case DISPATCH_APP_VISIBILITY:
handleAppVisibility(msg.arg1 != 0);
@@ -1985,16 +1983,13 @@
}
- private void deliverTrackballEvent(MotionEvent event) {
- boolean didFinish;
+ private void deliverTrackballEvent(MotionEvent event, boolean callWhenDone) {
if (event == null) {
try {
event = sWindowSession.getPendingTrackballMove(mWindow);
} catch (RemoteException e) {
}
- didFinish = true;
- } else {
- didFinish = false;
+ callWhenDone = false;
}
if (DEBUG_TRACKBALL) Log.v(TAG, "Motion event:" + event);
@@ -2012,7 +2007,7 @@
}
} finally {
if (handled) {
- if (!didFinish) {
+ if (callWhenDone) {
try {
sWindowSession.finishKey(mWindow);
} catch (RemoteException e) {
@@ -2128,7 +2123,7 @@
mLastTrackballTime = curTime;
}
} finally {
- if (!didFinish) {
+ if (callWhenDone) {
try {
sWindowSession.finishKey(mWindow);
} catch (RemoteException e) {
@@ -2591,15 +2586,19 @@
sendMessageAtTime(msg, event.getEventTime());
}
- public void dispatchPointer(MotionEvent event, long eventTime) {
+ public void dispatchPointer(MotionEvent event, long eventTime,
+ boolean callWhenDone) {
Message msg = obtainMessage(DISPATCH_POINTER);
msg.obj = event;
+ msg.arg1 = callWhenDone ? 1 : 0;
sendMessageAtTime(msg, eventTime);
}
- public void dispatchTrackball(MotionEvent event, long eventTime) {
+ public void dispatchTrackball(MotionEvent event, long eventTime,
+ boolean callWhenDone) {
Message msg = obtainMessage(DISPATCH_TRACKBALL);
msg.obj = event;
+ msg.arg1 = callWhenDone ? 1 : 0;
sendMessageAtTime(msg, eventTime);
}
@@ -2772,23 +2771,25 @@
}
}
- public void dispatchPointer(MotionEvent event, long eventTime) {
+ public void dispatchPointer(MotionEvent event, long eventTime,
+ boolean callWhenDone) {
final ViewRoot viewRoot = mViewRoot.get();
if (viewRoot != null) {
if (MEASURE_LATENCY) {
// Note: eventTime is in milliseconds
ViewRoot.lt.sample("* ViewRoot b4 dispatchPtr", System.nanoTime() - eventTime * 1000000);
}
- viewRoot.dispatchPointer(event, eventTime);
+ viewRoot.dispatchPointer(event, eventTime, callWhenDone);
} else {
new EventCompletion(mMainLooper, this, null, true, event);
}
}
- public void dispatchTrackball(MotionEvent event, long eventTime) {
+ public void dispatchTrackball(MotionEvent event, long eventTime,
+ boolean callWhenDone) {
final ViewRoot viewRoot = mViewRoot.get();
if (viewRoot != null) {
- viewRoot.dispatchTrackball(event, eventTime);
+ viewRoot.dispatchTrackball(event, eventTime, callWhenDone);
} else {
new EventCompletion(mMainLooper, this, null, false, event);
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 35d7cc9..8c12656 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -329,8 +329,6 @@
* Default is normal.
*
* @see #MEMORY_TYPE_NORMAL
- * @see #MEMORY_TYPE_HARDWARE
- * @see #MEMORY_TYPE_GPU
* @see #MEMORY_TYPE_PUSH_BUFFERS
*/
public int memoryType;
@@ -338,10 +336,16 @@
/** Memory type: The window's surface is allocated in main memory. */
public static final int MEMORY_TYPE_NORMAL = 0;
/** Memory type: The window's surface is configured to be accessible
- * by DMA engines and hardware accelerators. */
+ * by DMA engines and hardware accelerators.
+ * @deprecated this is ignored, this value is set automatically when needed.
+ */
+ @Deprecated
public static final int MEMORY_TYPE_HARDWARE = 1;
/** Memory type: The window's surface is configured to be accessible
- * by graphics accelerators. */
+ * by graphics accelerators.
+ * @deprecated this is ignored, this value is set automatically when needed.
+ */
+ @Deprecated
public static final int MEMORY_TYPE_GPU = 2;
/** Memory type: The window's surface doesn't own its buffers and
* therefore cannot be locked. Instead the buffers are pushed to
diff --git a/core/java/android/webkit/CallbackProxy.java b/core/java/android/webkit/CallbackProxy.java
index 96bf46e..e77d29b 100644
--- a/core/java/android/webkit/CallbackProxy.java
+++ b/core/java/android/webkit/CallbackProxy.java
@@ -70,6 +70,9 @@
private final WebBackForwardList mBackForwardList;
// Used to call startActivity during url override.
private final Context mContext;
+ // Stores the URL being loaded and the viewing mode to switch into when
+ // the URL finishes loading.
+ private ChangeViewModeOnFinishedLoad mChange;
// Message Ids
private static final int PAGE_STARTED = 100;
@@ -177,6 +180,37 @@
}
/**
+ * Tell the host application that the WebView has changed viewing modes.
+ * @param toZoomedOut If true, the WebView has zoomed out so that the page
+ * fits the screen. If false, it is zoomed to the setting
+ * specified by the user.
+ */
+ /* package */ void uiOnChangeViewingMode(boolean toZoomOverview) {
+ if (mWebChromeClient != null) {
+ mWebChromeClient.onChangeViewingMode(toZoomOverview);
+ }
+ }
+
+ private static class ChangeViewModeOnFinishedLoad {
+ boolean mToZoomOverView;
+ String mOriginalUrl;
+ ChangeViewModeOnFinishedLoad(boolean toZoomOverview,
+ String originalUrl) {
+ mToZoomOverView = toZoomOverview;
+ mOriginalUrl = originalUrl;
+ }
+ }
+
+ /**
+ * Keep track of the url and the viewing mode to change into. If/when that
+ * url finishes loading, this will change the viewing mode.
+ */
+ /* package */ void uiChangeViewingModeOnFinishedLoad(
+ boolean toZoomOverview, String originalUrl) {
+ if (mWebChromeClient == null) return;
+ mChange = new ChangeViewModeOnFinishedLoad(toZoomOverview, originalUrl);
+ }
+ /**
* Called by the UI side. Calling overrideUrlLoading from the WebCore
* side will post a message to call this method.
*/
@@ -237,6 +271,15 @@
if (mWebViewClient != null) {
mWebViewClient.onPageFinished(mWebView, (String) msg.obj);
}
+ if (mChange != null) {
+ if (mWebView.getOriginalUrl().equals(mChange.mOriginalUrl)) {
+ uiOnChangeViewingMode(mChange.mToZoomOverView);
+ } else {
+ // The user has gone to a different page, so there is
+ // no need to hang on to the old object.
+ mChange = null;
+ }
+ }
break;
case RECEIVED_ICON:
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index d188a39..fca591f 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -833,22 +833,24 @@
// "secure" is a known attribute doesn't use "=";
// while sites like live.com uses "secure="
- if (length - index > SECURE_LENGTH
+ if (length - index >= SECURE_LENGTH
&& cookieString.substring(index, index + SECURE_LENGTH).
equalsIgnoreCase(SECURE)) {
index += SECURE_LENGTH;
cookie.secure = true;
+ if (index == length) break;
if (cookieString.charAt(index) == EQUAL) index++;
continue;
}
// "httponly" is a known attribute doesn't use "=";
// while sites like live.com uses "httponly="
- if (length - index > HTTP_ONLY_LENGTH
+ if (length - index >= HTTP_ONLY_LENGTH
&& cookieString.substring(index,
index + HTTP_ONLY_LENGTH).
equalsIgnoreCase(HTTP_ONLY)) {
index += HTTP_ONLY_LENGTH;
+ if (index == length) break;
if (cookieString.charAt(index) == EQUAL) index++;
// FIXME: currently only parse the attribute
continue;
diff --git a/core/java/android/webkit/FrameLoader.java b/core/java/android/webkit/FrameLoader.java
index 81ed367..c1eeb3b 100644
--- a/core/java/android/webkit/FrameLoader.java
+++ b/core/java/android/webkit/FrameLoader.java
@@ -128,6 +128,18 @@
/* package */
static boolean handleLocalFile(String url, LoadListener loadListener,
WebSettings settings) {
+ // Attempt to decode the percent-encoded url before passing to the
+ // local loaders.
+ try {
+ url = new String(URLUtil.decode(url.getBytes()));
+ } catch (IllegalArgumentException e) {
+ loadListener.error(EventHandler.ERROR_BAD_URL,
+ loadListener.getContext().getString(
+ com.android.internal.R.string.httpErrorBadUrl));
+ // Return true here so we do not trigger an unsupported scheme
+ // error.
+ return true;
+ }
if (URLUtil.isAssetUrl(url)) {
FileLoader.requestUrl(url, loadListener, loadListener.getContext(),
true, settings.getAllowFileAccess());
diff --git a/core/java/android/webkit/MockGeolocation.java b/core/java/android/webkit/MockGeolocation.java
new file mode 100644
index 0000000..028cb19
--- /dev/null
+++ b/core/java/android/webkit/MockGeolocation.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+/**
+ * This class is simply a container for the methods used to configure WebKit's
+ * mock Geolocation service for use in LayoutTests.
+ * @hide Pending API council review.
+ */
+public final class MockGeolocation {
+
+ // Global instance of a MockGeolocation
+ private static MockGeolocation sMockGeolocation;
+
+ /**
+ * Set the position for the mock Geolocation service.
+ */
+ public void setPosition(double latitude, double longitude, double accuracy) {
+ // This should only ever be called on the WebKit thread.
+ nativeSetPosition(latitude, longitude, accuracy);
+ }
+
+ /**
+ * Set the error for the mock Geolocation service.
+ */
+ public void setError(int code, String message) {
+ // This should only ever be called on the WebKit thread.
+ nativeSetError(code, message);
+ }
+
+ /**
+ * Get the global instance of MockGeolocation.
+ * @return The global MockGeolocation instance.
+ */
+ public static MockGeolocation getInstance() {
+ if (sMockGeolocation == null) {
+ sMockGeolocation = new MockGeolocation();
+ }
+ return sMockGeolocation;
+ }
+
+ // Native functions
+ private static native void nativeSetPosition(double latitude, double longitude, double accuracy);
+ private static native void nativeSetError(int code, String message);
+}
diff --git a/core/java/android/webkit/PluginManager.java b/core/java/android/webkit/PluginManager.java
index 370d3d2..cd34192 100644
--- a/core/java/android/webkit/PluginManager.java
+++ b/core/java/android/webkit/PluginManager.java
@@ -147,11 +147,6 @@
}
directories.add(directory);
}
- // hack for gears for now
- String gears = mContext.getDir("plugins", 0).getPath();
- if (!directories.contains(gears)) {
- directories.add(gears);
- }
return directories.toArray(new String[directories.size()]);
}
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index c10bc97..e1c8d4d 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -23,6 +23,15 @@
public class WebChromeClient {
/**
+ * Tell the host application that the WebView has changed viewing modes.
+ * @param toZoomedOut If true, the WebView has zoomed out so that the page
+ * fits the screen. If false, it is zoomed to the setting
+ * specified by the user.
+ * @hide
+ */
+ public void onChangeViewingMode(boolean toZoomedOut) {}
+
+ /**
* Tell the host application the current progress of loading a page.
* @param view The WebView that initiated the callback.
* @param newProgress Current page loading progress, represented by
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index be9daa5..f49aab1 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -521,6 +521,7 @@
// follow the links. Double tap will toggle between zoom overview mode and
// the last zoom scale.
boolean mInZoomOverview = false;
+
// ideally mZoomOverviewWidth should be mContentWidth. But sites like espn,
// engadget always have wider mContentWidth no matter what viewport size is.
int mZoomOverviewWidth = WebViewCore.DEFAULT_VIEWPORT_WIDTH;
@@ -4687,19 +4688,21 @@
mZoomCenterX = mLastTouchX;
mZoomCenterY = mLastTouchY;
mInZoomOverview = !mInZoomOverview;
- if (mInZoomOverview) {
- if (getSettings().getBuiltInZoomControls()) {
- if (mZoomButtonsController.isVisible()) {
- mZoomButtonsController.setVisible(false);
- }
- } else {
- if (mZoomControlRunnable != null) {
- mPrivateHandler.removeCallbacks(mZoomControlRunnable);
- }
- if (mZoomControls != null) {
- mZoomControls.hide();
- }
+ mCallbackProxy.uiOnChangeViewingMode(mInZoomOverview);
+ // remove the zoom control after double tap
+ if (getSettings().getBuiltInZoomControls()) {
+ if (mZoomButtonsController.isVisible()) {
+ mZoomButtonsController.setVisible(false);
}
+ } else {
+ if (mZoomControlRunnable != null) {
+ mPrivateHandler.removeCallbacks(mZoomControlRunnable);
+ }
+ if (mZoomControls != null) {
+ mZoomControls.hide();
+ }
+ }
+ if (mInZoomOverview) {
zoomWithPreview((float) getViewWidth() / mZoomOverviewWidth);
} else {
// mLastTouchX and mLastTouchY are the point in the current viewport
@@ -5034,6 +5037,14 @@
mInZoomOverview = ENABLE_DOUBLETAP_ZOOM
&& settings.getLoadWithOverviewMode();
}
+ mCallbackProxy.uiOnChangeViewingMode(true);
+ if (!mInZoomOverview) {
+ // We are going to start zoomed in. However, we
+ // truly want to show the title bar, and then hide
+ // it once the page has loaded
+ mCallbackProxy.uiChangeViewingModeOnFinishedLoad(
+ false, getOriginalUrl());
+ }
setNewZoomScale(mLastScale, false);
setContentScrollTo(restoreState.mScrollX,
restoreState.mScrollY);
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index eea97dc..67721c9 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -546,6 +546,7 @@
private void initAbsListView() {
// Setting focusable in touch mode will set the focusable property to true
+ setClickable(true);
setFocusableInTouchMode(true);
setWillNotDraw(false);
setAlwaysDrawnWithCacheEnabled(false);
@@ -1433,6 +1434,10 @@
* this is a long press.
*/
void keyPressed() {
+ if (!isEnabled() || !isClickable()) {
+ return;
+ }
+
Drawable selector = mSelector;
Rect selectorRect = mSelectorRect;
if (selector != null && (isFocused() || touchModeDrawsInPressedState())
@@ -1450,8 +1455,8 @@
Drawable d = selector.getCurrent();
if (d != null && d instanceof TransitionDrawable) {
if (longClickable) {
- ((TransitionDrawable) d).startTransition(ViewConfiguration
- .getLongPressTimeout());
+ ((TransitionDrawable) d).startTransition(
+ ViewConfiguration.getLongPressTimeout());
} else {
((TransitionDrawable) d).resetTransition();
}
@@ -1732,18 +1737,29 @@
}
@Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ return false;
+ }
+
+ @Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
- if (isPressed() && mSelectedPosition >= 0 && mAdapter != null &&
+ if (!isEnabled()) {
+ return true;
+ }
+ if (isClickable() && isPressed() &&
+ mSelectedPosition >= 0 && mAdapter != null &&
mSelectedPosition < mAdapter.getCount()) {
+
final View view = getChildAt(mSelectedPosition - mFirstPosition);
performItemClick(view, mSelectedPosition, mSelectedRowId);
setPressed(false);
if (view != null) view.setPressed(false);
return true;
}
+ break;
}
return super.onKeyUp(keyCode, event);
}
@@ -1892,6 +1908,12 @@
@Override
public boolean onTouchEvent(MotionEvent ev) {
+ if (!isEnabled()) {
+ // A disabled view that is clickable still consumes the touch
+ // events, it just doesn't respond to them.
+ return isClickable() || isLongClickable();
+ }
+
if (mFastScroller != null) {
boolean intercepted = mFastScroller.onTouchEvent(ev);
if (intercepted) {
diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java
index 5360621..6abb2ae4 100644
--- a/core/java/android/widget/ExpandableListView.java
+++ b/core/java/android/widget/ExpandableListView.java
@@ -33,6 +33,7 @@
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
+import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ExpandableListConnector.PositionMetadata;
/**
@@ -916,7 +917,14 @@
@Override
ContextMenuInfo createContextMenuInfo(View view, int flatListPosition, long id) {
- PositionMetadata pm = mConnector.getUnflattenedPos(flatListPosition);
+ // Adjust for and handle for header views
+ final int adjustedPosition = flatListPosition - getHeaderViewsCount();
+ if (adjustedPosition < 0) {
+ // Return normal info for header view context menus
+ return new AdapterContextMenuInfo(view, flatListPosition, id);
+ }
+
+ PositionMetadata pm = mConnector.getUnflattenedPos(adjustedPosition);
ExpandableListPosition pos = pm.position;
pm.recycle();
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 02a137d..993b7cb 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1428,7 +1428,8 @@
throw new IllegalStateException("The content of the adapter has changed but "
+ "ListView did not receive a notification. Make sure the content of "
+ "your adapter is not modified from a background thread, but only "
- + "from the UI thread.");
+ + "from the UI thread. [in ListView(" + getId() + ", " + getClass()
+ + ") with Adapter(" + mAdapter.getClass() + ")]");
}
setSelectedPositionInt(mNextSelectedPosition);
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 90fbb77..548dee9 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -817,6 +817,7 @@
* @param p the layout parameters of the popup's content view
*/
private void invokePopup(WindowManager.LayoutParams p) {
+ p.packageName = mContext.getPackageName();
mWindowManager.addView(mPopupView, p);
}
diff --git a/core/java/com/android/internal/app/ShutdownThread.java b/core/java/com/android/internal/app/ShutdownThread.java
index 77d6e20..4c9451e 100644
--- a/core/java/com/android/internal/app/ShutdownThread.java
+++ b/core/java/com/android/internal/app/ShutdownThread.java
@@ -21,8 +21,8 @@
import android.app.IActivityManager;
import android.app.ProgressDialog;
import android.app.AlertDialog;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.IBluetoothDevice;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.IBluetooth;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -179,13 +179,13 @@
final ITelephony phone =
ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
- final IBluetoothDevice bluetooth =
- IBluetoothDevice.Stub.asInterface(ServiceManager.checkService(
+ final IBluetooth bluetooth =
+ IBluetooth.Stub.asInterface(ServiceManager.checkService(
Context.BLUETOOTH_SERVICE));
try {
bluetoothOff = bluetooth == null ||
- bluetooth.getBluetoothState() == BluetoothDevice.BLUETOOTH_STATE_OFF;
+ bluetooth.getBluetoothState() == BluetoothAdapter.BLUETOOTH_STATE_OFF;
if (!bluetoothOff) {
Log.w(TAG, "Disabling Bluetooth...");
bluetooth.disable(false); // disable but don't persist new state
@@ -213,7 +213,7 @@
if (!bluetoothOff) {
try {
bluetoothOff =
- bluetooth.getBluetoothState() == BluetoothDevice.BLUETOOTH_STATE_OFF;
+ bluetooth.getBluetoothState() == BluetoothAdapter.BLUETOOTH_STATE_OFF;
} catch (RemoteException ex) {
Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
bluetoothOff = true;
diff --git a/core/java/com/android/internal/os/HandlerCaller.java b/core/java/com/android/internal/os/HandlerCaller.java
index e4c473d..5825024 100644
--- a/core/java/com/android/internal/os/HandlerCaller.java
+++ b/core/java/com/android/internal/os/HandlerCaller.java
@@ -97,6 +97,14 @@
return mH.hasMessages(what);
}
+ public void removeMessages(int what) {
+ mH.removeMessages(what);
+ }
+
+ public void removeMessages(int what, Object obj) {
+ mH.removeMessages(what, obj);
+ }
+
public void sendMessage(Message msg) {
mH.sendMessage(msg);
}
diff --git a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
index 7266ee3..3f2979f 100644
--- a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
+++ b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
@@ -22,6 +22,7 @@
import android.graphics.drawable.Drawable;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
+import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.content.Context;
import android.content.IntentFilter;
@@ -59,6 +60,7 @@
class WallpaperObserver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
mEngine.updateWallpaper();
+ mEngine.drawFrame();
}
}
@@ -66,21 +68,15 @@
private final Object mLock = new Object();
private final Rect mBounds = new Rect();
Drawable mBackground;
- int mXOffset;
- int mYOffset;
+ float mXOffset;
+ float mYOffset;
@Override
public void onCreate(SurfaceHolder surfaceHolder) {
super.onCreate(surfaceHolder);
- mBackground = mWallpaperManager.getDrawable();
- mBounds.left = mBounds.top = 0;
- mBounds.right = mBackground.getIntrinsicWidth();
- mBounds.bottom = mBackground.getIntrinsicHeight();
- int offx = (getDesiredMinimumWidth() - mBounds.right) / 2;
- int offy = (getDesiredMinimumHeight() - mBounds.bottom) / 2;
- mBounds.offset(offx, offy);
- mBackground.setBounds(mBounds);
+ updateWallpaper();
surfaceHolder.setSizeFromLayout();
+ //setTouchEventsEnabled(true);
}
@Override
@@ -89,10 +85,16 @@
}
@Override
+ public void onTouchEvent(MotionEvent event) {
+ super.onTouchEvent(event);
+ Log.i("foo", "Touch event: " + event);
+ }
+
+ @Override
public void onOffsetsChanged(float xOffset, float yOffset,
int xPixels, int yPixels) {
- mXOffset = xPixels;
- mYOffset = yPixels;
+ mXOffset = xOffset;
+ mYOffset = xOffset;
drawFrame();
}
@@ -116,11 +118,20 @@
SurfaceHolder sh = getSurfaceHolder();
Canvas c = sh.lockCanvas();
if (c != null) {
- //final Rect frame = sh.getSurfaceFrame();
+ final Rect frame = sh.getSurfaceFrame();
synchronized (mLock) {
final Drawable background = mBackground;
- //background.setBounds(frame);
- c.translate(mXOffset, mYOffset);
+ final int dw = frame.width();
+ final int dh = frame.height();
+ final int bw = mBackground.getIntrinsicWidth();
+ final int bh = mBackground.getIntrinsicHeight();
+ final int availw = bw-dw;
+ final int availh = bh-dh;
+ int xPixels = availw > 0
+ ? -(int)(availw*mXOffset+.5f) : -(int)(availw/2);
+ int yPixels = availh > 0
+ ? -(int)(availh*mYOffset+.5f) : -(int)(availh/2);
+ c.translate(xPixels, yPixels);
c.drawColor(0xff000000);
background.draw(c);
}
@@ -131,6 +142,10 @@
void updateWallpaper() {
synchronized (mLock) {
mBackground = mWallpaperManager.getDrawable();
+ mBounds.left = mBounds.top = 0;
+ mBounds.right = mBackground.getIntrinsicWidth();
+ mBounds.bottom = mBackground.getIntrinsicHeight();
+ mBackground.setBounds(mBounds);
}
}
}
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index a030db7..f4f6297 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -32,23 +32,47 @@
}
}
- public void dispatchPointer(MotionEvent event, long eventTime) {
+ public boolean onDispatchPointer(MotionEvent event, long eventTime,
+ boolean callWhenDone) {
+ event.recycle();
+ return false;
+ }
+
+ public void dispatchPointer(MotionEvent event, long eventTime,
+ boolean callWhenDone) {
try {
if (event == null) {
event = mSession.getPendingPointerMove(this);
- } else if (event.getAction() != MotionEvent.ACTION_OUTSIDE) {
- mSession.finishKey(this);
+ onDispatchPointer(event, eventTime, false);
+ } else if (callWhenDone) {
+ if (!onDispatchPointer(event, eventTime, true)) {
+ mSession.finishKey(this);
+ }
+ } else {
+ onDispatchPointer(event, eventTime, false);
}
} catch (RemoteException ex) {
}
}
- public void dispatchTrackball(MotionEvent event, long eventTime) {
+ public boolean onDispatchTrackball(MotionEvent event, long eventTime,
+ boolean callWhenDone) {
+ event.recycle();
+ return false;
+ }
+
+ public void dispatchTrackball(MotionEvent event, long eventTime,
+ boolean callWhenDone) {
try {
if (event == null) {
event = mSession.getPendingTrackballMove(this);
- } else if (event.getAction() != MotionEvent.ACTION_OUTSIDE) {
- mSession.finishKey(this);
+ onDispatchTrackball(event, eventTime, false);
+ } else if (callWhenDone) {
+ if (!onDispatchTrackball(event, eventTime, true)) {
+ mSession.finishKey(this);
+ }
+ } else {
+ onDispatchTrackball(event, eventTime, false);
}
} catch (RemoteException ex) {
}
diff --git a/core/java/com/android/internal/view/BaseSurfaceHolder.java b/core/java/com/android/internal/view/BaseSurfaceHolder.java
index 2364ae4..2823689 100644
--- a/core/java/com/android/internal/view/BaseSurfaceHolder.java
+++ b/core/java/com/android/internal/view/BaseSurfaceHolder.java
@@ -91,9 +91,14 @@
public void setType(int type) {
switch (type) {
- case SURFACE_TYPE_NORMAL:
case SURFACE_TYPE_HARDWARE:
case SURFACE_TYPE_GPU:
+ // these are deprecated, treat as "NORMAL"
+ type = SURFACE_TYPE_NORMAL;
+ break;
+ }
+ switch (type) {
+ case SURFACE_TYPE_NORMAL:
case SURFACE_TYPE_PUSH_BUFFERS:
if (mRequestedType != type) {
mRequestedType = type;
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 36d2684..015268b 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -114,7 +114,7 @@
android_bluetooth_BluetoothAudioGateway.cpp \
android_bluetooth_BluetoothSocket.cpp \
android_bluetooth_ScoSocket.cpp \
- android_server_BluetoothDeviceService.cpp \
+ android_server_BluetoothService.cpp \
android_server_BluetoothEventLoop.cpp \
android_server_BluetoothA2dpService.cpp \
android_message_digest_sha1.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 63dc9e8..2e73372 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -146,7 +146,7 @@
extern int register_android_bluetooth_BluetoothAudioGateway(JNIEnv* env);
extern int register_android_bluetooth_BluetoothSocket(JNIEnv *env);
extern int register_android_bluetooth_ScoSocket(JNIEnv *env);
-extern int register_android_server_BluetoothDeviceService(JNIEnv* env);
+extern int register_android_server_BluetoothService(JNIEnv* env);
extern int register_android_server_BluetoothEventLoop(JNIEnv *env);
extern int register_android_server_BluetoothA2dpService(JNIEnv* env);
extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
@@ -1241,7 +1241,7 @@
REG_JNI(register_android_bluetooth_BluetoothAudioGateway),
REG_JNI(register_android_bluetooth_BluetoothSocket),
REG_JNI(register_android_bluetooth_ScoSocket),
- REG_JNI(register_android_server_BluetoothDeviceService),
+ REG_JNI(register_android_server_BluetoothService),
REG_JNI(register_android_server_BluetoothEventLoop),
REG_JNI(register_android_server_BluetoothA2dpService),
REG_JNI(register_android_message_digest_sha1),
diff --git a/core/jni/android_server_BluetoothDeviceService.cpp b/core/jni/android_server_BluetoothService.cpp
similarity index 98%
rename from core/jni/android_server_BluetoothDeviceService.cpp
rename to core/jni/android_server_BluetoothService.cpp
index 444e628..326052b 100644
--- a/core/jni/android_server_BluetoothDeviceService.cpp
+++ b/core/jni/android_server_BluetoothService.cpp
@@ -16,7 +16,7 @@
#define DBUS_ADAPTER_IFACE BLUEZ_DBUS_BASE_IFC ".Adapter"
#define DBUS_DEVICE_IFACE BLUEZ_DBUS_BASE_IFC ".Device"
-#define LOG_TAG "BluetoothDeviceService.cpp"
+#define LOG_TAG "BluetoothService.cpp"
#include "android_bluetooth_common.h"
#include "android_runtime/AndroidRuntime.h"
@@ -49,7 +49,7 @@
#ifdef HAVE_BLUETOOTH
// We initialize these variables when we load class
-// android.server.BluetoothDeviceService
+// android.server.BluetoothService
static jfieldID field_mNativeData;
static jfieldID field_mEventLoop;
@@ -732,9 +732,9 @@
(void *)cancelPairingUserInputNative},
};
-int register_android_server_BluetoothDeviceService(JNIEnv *env) {
+int register_android_server_BluetoothService(JNIEnv *env) {
return AndroidRuntime::registerNativeMethods(env,
- "android/server/BluetoothDeviceService", sMethods, NELEM(sMethods));
+ "android/server/BluetoothService", sMethods, NELEM(sMethods));
}
} /* namespace android */
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d55f188..608c1ff 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1164,9 +1164,6 @@
<service android:name="com.android.internal.service.wallpaper.ImageWallpaper"
android:permission="android.permission.BIND_WALLPAPER">
- <intent-filter>
- <action android:name="android.service.wallpaper.WallpaperService" />
- </intent-filter>
</service>
<receiver android:name="com.android.server.BootReceiver" >
diff --git a/core/res/res/values-en-rUS/donottranslate-names.xml b/core/res/res/values-en-rUS/donottranslate-names.xml
new file mode 100644
index 0000000..42c8ab4
--- /dev/null
+++ b/core/res/res/values-en-rUS/donottranslate-names.xml
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- various string resources for Contacts -->
+ <string-array name="common_nicknames">
+ <item>Albert, Al, Bert, Bertie</item>
+ <item>Alexander, Al, Alex, Lex, Sasha</item>
+ <item>Alexandra, Al, Alex, Allie, Ally, Lex, Lexie, Sandra, Sandy, Sasha</item>
+ <item>Alice, Allie, Ally</item>
+ <item>Alison, Allie, Ally</item>
+ <item>Allison, Allie, Ally</item>
+ <item>Amanda, Mandi, Mandy</item>
+ <item>Andrea, Andie</item>
+ <item>Andrew, Andy, Drew</item>
+ <item>Anthony, Tony, Toni, Tone</item>
+ <item>Arthur, Art, Arty</item>
+ <item>Barbara, Babs, Barb, Barbie</item>
+ <item>Benjamin, Ben, Benji, Benny</item>
+ <item>Bernard, Bern, Bernie</item>
+ <item>Bertram, Bert, Bertie</item>
+ <item>Bradly, Brad</item>
+ <item>Catherine, Cat, Cate, Cath, Catie, Cathy, Kat, Kate, Katie, Kathy</item>
+ <item>Charles, Chuck, Chaz, Charlie, Buck</item>
+ <item>Christine, Chris, Chrissy, Chrissie</item>
+ <item>Christopher, Chris</item>
+ <item>Cynthia, Cindy, Cynth</item>
+ <item>Daniel, Dan, Danny</item>
+ <item>David, Dave</item>
+ <item>Deborah, Deb, Debbie</item>
+ <item>Dennis, Den, Denny, Dean</item>
+ <item>Dolores, Dolly</item>
+ <item>Donald, Don, Donny</item>
+ <item>Donnatella, Donna</item>
+ <item>Dorothea, Dot, Dotty</item>
+ <item>Dorothy, Dot, Dotty</item>
+ <item>Douglas, Doug</item>
+ <item>Edward, Ed, Eddie, Ned, Neddie, Neddy, Ted, Teddy, Teddie</item>
+ <item>Eleanor, Ella, Ellie, Elle</item>
+ <item>Elisabetta, Betta</item>
+ <item>Elizabeth, Beth, Bess, Bessie, Betsy, Betty, Bette, Eliza, Lisa, Liza, Liz</item>
+ <item>Emily, Em, Ems, Emmy</item>
+ <item>Emma, Em, Ems, Emmy</item>
+ <item>Erica, Rikki, Rikkie, Ricky</item>
+ <item>Eugene, Gene</item>
+ <item>Florence, Flo</item>
+ <item>Frances, Fran, Francie</item>
+ <item>Francis, Fran, Frank</item>
+ <item>Frederick, Fred, Freddy</item>
+ <item>Gabriel, Gabe</item>
+ <item>Geoffrey, Jeff</item>
+ <item>Gerald, Gerry</item>
+ <item>Gerard, Gerry</item>
+ <item>Gregory, Greg</item>
+ <item>Harold, Hal, Hank, Harry</item>
+ <item>Henry, Hal, Hank, Harry</item>
+ <item>Herbert, Bert, Bertie</item>
+ <item>Irving, Irv</item>
+ <item>Isabella, Isa, Izzy</item>
+ <item>Jacob, Jake</item>
+ <item>Jacqueline, Jackie</item>
+ <item>James, Jim, Jimmy, Jamie, Jock</item>
+ <item>Janet, Jan</item>
+ <item>Janice, Jan</item>
+ <item>Jason, Jay</item>
+ <item>Jefferson, Jeff</item>
+ <item>Jeffrey, Jeff</item>
+ <item>Jennifer, Jen, Jenny</item>
+ <item>Jerome, Jerry</item>
+ <item>Jessica, Jessie</item>
+ <item>John, Jack, Jacky, Johnny, Jon</item>
+ <item>Jonathan, Jon, John</item>
+ <item>Joseph, Joe, Joey</item>
+ <item>Joshua, Josh</item>
+ <item>Kaitlyn, Cat, Cate, Catie, Cath, Cathy, Kat, Kate, Katie, Kathy</item>
+ <item>Katherine, Cat, Cate, Catie, Cath, Cathy, Kat, Kate, Katie, Kathy</item>
+ <item>Kathleen, Cat, Cate, Catie, Cath, Cathy, Kat, Kate, Katie, Kathy</item>
+ <item>Katrina, Cat, Cate, Catie, Cath, Cathy, Kat, Kate, Katie, Kathy</item>
+ <item>Kenneth, Ken</item>
+ <item>Kevin, Kev</item>
+ <item>Laura, Lauri, Laurie</item>
+ <item>Lauren, Lauri, Laurie</item>
+ <item>Laurence, Larry, Lauri, Laurie</item>
+ <item>Lawrence, Larry, Lauri, Laurie</item>
+ <item>Leonard, Leo, Len, Lenny</item>
+ <item>Leopold, Leo, Len, Lenny</item>
+ <item>Madeline, Maddie, Maddy</item>
+ <item>Margaret, Marge, Marg, Maggie, Mags, Meg, Peggy</item>
+ <item>Matthew, Matt, Mattie</item>
+ <item>Maureen, Mo</item>
+ <item>Maurice, Mo</item>
+ <item>Megan, Meg</item>
+ <item>Michael, Mickey, Mick, Mike, Mikey</item>
+ <item>Morris, Mo</item>
+ <item>Nancy, Nan</item>
+ <item>Nathan, Nat, Nate</item>
+ <item>Nathaniel, Nat, Nate</item>
+ <item>Nicholas, Nick</item>
+ <item>Pamela, Pam</item>
+ <item>Patricia, Pat, Patsy, Patty, Trish, Tricia</item>
+ <item>Patrick, Paddy, Pat, Patty, Patter, Rick, Ricky</item>
+ <item>Peter, Pete</item>
+ <item>Raymond, Ray</item>
+ <item>Philip, Phil</item>
+ <item>Rebecca, Becca</item>
+ <item>Richard, Rick, Rich, Dick</item>
+ <item>Robert, Bob, Rob, Robbie, Bobby, Rab</item>
+ <item>Roberta, Bobbie</item>
+ <item>Rodney. Rod</item>
+ <item>Ronald, Ron, Ronnie</item>
+ <item>Rosemary, Rosie, Rose</item>
+ <item>Russell, Russ, Rusty</item>
+ <item>Ryan, Ry</item>
+ <item>Samantha, Sam</item>
+ <item>Samuel, Sam, Sammy</item>
+ <item>Sophia, Sophie</item>
+ <item>Stephanie, Steph, Stephie</item>
+ <item>Stephen, Steve</item>
+ <item>Steven, Steve</item>
+ <item>Stuart, Stu</item>
+ <item>Susan, Sue, Susie, Suzie</item>
+ <item>Suzanne, Sue, Susie, Suzie</item>
+ <item>Teresa, Terrie, Terry</item>
+ <item>Theodora, Teddie, Thea, Theo</item>
+ <item>Theodore, Ted, Teddy, Theo</item>
+ <item>Thomas, Tom, Thom, Tommy</item>
+ <item>Timothy, Tim, Timmy</item>
+ <item>Valerie, Val</item>
+ <item>Veronica, Ronnie, Roni, Nica, Nikki, Nikka</item>
+ <item>Victor, Vic</item>
+ <item>Victoria, Vicky, Vicki, Vickie, Tori</item>
+ <item>Vincent, Vince, Vin, Vinnie</item>
+ <item>Vivian, Vivi</item>
+ <item>Walter, Walt, Wally</item>
+ <item>Wendy, Wen, Wendel</item>
+ <item>William, Bill, Billy, Will, Willy, Liam</item>
+ <item>Yvonna, Vonna</item>
+ <item>Zachary, Zach, Zack, Zac</item>
+ </string-array>
+ <string name="common_name_prefixes">
+ 1LT, 1ST, 2LT, 2ND, 3RD, ADMIRAL, CAPT, CAPTAIN, COL, CPT, DR,
+ GEN, GENERAL, LCDR, LT, LTC, LTG, LTJG, MAJ, MAJOR, MG, MR,
+ MRS, MS, PASTOR, PROF, REP, REVEREND, REV, SEN, ST
+ </string>
+ <string name="common_name_suffixes">
+ B.A., BA, D.D.S., DDS, I, II, III, IV, IX, JR, M.A., M.D, MA,
+ MD, MS, PH.D., PHD, SR, V, VI, VII, VIII, X
+ </string>
+ <string name="common_last_name_prefixes">
+ D', DE, DEL, DI, LA, LE, MC, SAN, ST, TER, VAN, VON
+ </string>
+ <string name="common_name_conjunctions">
+ &, AND, OR
+ </string>
+</resources>
diff --git a/core/res/res/values/donottranslate-names.xml b/core/res/res/values/donottranslate-names.xml
new file mode 100644
index 0000000..56ae47a
--- /dev/null
+++ b/core/res/res/values/donottranslate-names.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+ <!-- Various locale-specific string resources for Contacts -->
+ <string-array name="common_nicknames"></string-array>
+ <string name="common_name_prefixes"></string>
+ <string name="common_name_suffixes"></string>
+ <string name="common_last_name_prefixes"></string>
+ <string name="common_name_conjunctions"></string>
+</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 815b7673..22f9136 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1923,157 +1923,6 @@
<!-- This string appears (on two lines) when you type a number into contacts search, to let you create a contact whose phone number is the number you typed. The first line will be in bigger type than the second. -->
<string name="create_contact_using">Create contact\nusing <xliff:g id="number" example="555">%s</xliff:g></string>
- <!-- various string resources for Contacts -->
- <string-array name="common_nicknames">
- <item>Albert, Al, Bert, Bertie</item>
- <item>Alexander, Al, Alex, Lex, Sasha</item>
- <item>Alexandra, Al, Alex, Allie, Ally, Lex, Lexie, Sandra, Sandy, Sasha</item>
- <item>Alice, Allie, Ally</item>
- <item>Alison, Allie, Ally</item>
- <item>Allison, Allie, Ally</item>
- <item>Amanda, Mandi, Mandy</item>
- <item>Andrea, Andie</item>
- <item>Andrew, Andy, Drew</item>
- <item>Anthony, Tony, Toni, Tone</item>
- <item>Arthur, Art, Arty</item>
- <item>Barbara, Babs, Barb, Barbie</item>
- <item>Benjamin, Ben, Benji, Benny</item>
- <item>Bernard, Bern, Bernie</item>
- <item>Bertram, Bert, Bertie</item>
- <item>Bradly, Brad</item>
- <item>Catherine, Cat, Cate, Cath, Catie, Cathy, Kat, Kate, Katie, Kathy</item>
- <item>Charles, Chuck, Chaz, Charlie, Buck</item>
- <item>Christine, Chris, Chrissy, Chrissie</item>
- <item>Christopher, Chris</item>
- <item>Cynthia, Cindy, Cynth</item>
- <item>Daniel, Dan, Danny</item>
- <item>David, Dave</item>
- <item>Deborah, Deb, Debbie</item>
- <item>Dennis, Den, Denny, Dean</item>
- <item>Dolores, Dolly</item>
- <item>Donald, Don, Donny</item>
- <item>Donnatella, Donna</item>
- <item>Dorothea, Dot, Dotty</item>
- <item>Dorothy, Dot, Dotty</item>
- <item>Douglas, Doug</item>
- <item>Edward, Ed, Eddie, Ned, Neddie, Neddy, Ted, Teddy, Teddie</item>
- <item>Eleanor, Ella, Ellie, Elle</item>
- <item>Elisabetta, Betta</item>
- <item>Elizabeth, Beth, Bess, Bessie, Betsy, Betty, Bette, Eliza, Lisa, Liza, Liz</item>
- <item>Emily, Em, Ems, Emmy</item>
- <item>Emma, Em, Ems, Emmy</item>
- <item>Erica, Rikki, Rikkie, Ricky</item>
- <item>Eugene, Gene</item>
- <item>Florence, Flo</item>
- <item>Frances, Fran, Francie</item>
- <item>Francis, Fran, Frank</item>
- <item>Frederick, Fred, Freddy</item>
- <item>Gabriel, Gabe</item>
- <item>Geoffrey, Jeff</item>
- <item>Gerald, Gerry</item>
- <item>Gerard, Gerry</item>
- <item>Gregory, Greg</item>
- <item>Harold, Hal, Hank, Harry</item>
- <item>Henry, Hal, Hank, Harry</item>
- <item>Herbert, Bert, Bertie</item>
- <item>Irving, Irv</item>
- <item>Isabella, Isa, Izzy</item>
- <item>Jacob, Jake</item>
- <item>Jacqueline, Jackie</item>
- <item>James, Jim, Jimmy, Jamie, Jock</item>
- <item>Janet, Jan</item>
- <item>Janice, Jan</item>
- <item>Jason, Jay</item>
- <item>Jefferson, Jeff</item>
- <item>Jeffrey, Jeff</item>
- <item>Jennifer, Jen, Jenny</item>
- <item>Jerome, Jerry</item>
- <item>Jessica, Jessie</item>
- <item>John, Jack, Jacky, Johnny, Jon</item>
- <item>Jonathan, Jon, John</item>
- <item>Joseph, Joe, Joey</item>
- <item>Joshua, Josh</item>
- <item>Kaitlyn, Cat, Cate, Catie, Cath, Cathy, Kat, Kate, Katie, Kathy</item>
- <item>Katherine, Cat, Cate, Catie, Cath, Cathy, Kat, Kate, Katie, Kathy</item>
- <item>Kathleen, Cat, Cate, Catie, Cath, Cathy, Kat, Kate, Katie, Kathy</item>
- <item>Katrina, Cat, Cate, Catie, Cath, Cathy, Kat, Kate, Katie, Kathy</item>
- <item>Kenneth, Ken</item>
- <item>Kevin, Kev</item>
- <item>Laura, Lauri, Laurie</item>
- <item>Lauren, Lauri, Laurie</item>
- <item>Laurence, Larry, Lauri, Laurie</item>
- <item>Lawrence, Larry, Lauri, Laurie</item>
- <item>Leonard, Leo, Len, Lenny</item>
- <item>Leopold, Leo, Len, Lenny</item>
- <item>Madeline, Maddie, Maddy</item>
- <item>Margaret, Marge, Marg, Maggie, Mags, Meg, Peggy</item>
- <item>Matthew, Matt, Mattie</item>
- <item>Maureen, Mo</item>
- <item>Maurice, Mo</item>
- <item>Megan, Meg</item>
- <item>Michael, Mickey, Mick, Mike, Mikey</item>
- <item>Morris, Mo</item>
- <item>Nancy, Nan</item>
- <item>Nathan, Nat, Nate</item>
- <item>Nathaniel, Nat, Nate</item>
- <item>Nicholas, Nick</item>
- <item>Pamela, Pam</item>
- <item>Patricia, Pat, Patsy, Patty, Trish, Tricia</item>
- <item>Patrick, Paddy, Pat, Patty, Patter, Rick, Ricky</item>
- <item>Peter, Pete</item>
- <item>Raymond, Ray</item>
- <item>Philip, Phil</item>
- <item>Rebecca, Becca</item>
- <item>Richard, Rick, Rich, Dick</item>
- <item>Robert, Bob, Rob, Robbie, Bobby, Rab</item>
- <item>Roberta, Bobbie</item>
- <item>Rodney. Rod</item>
- <item>Ronald, Ron, Ronnie</item>
- <item>Rosemary, Rosie, Rose</item>
- <item>Russell, Russ, Rusty</item>
- <item>Ryan, Ry</item>
- <item>Samantha, Sam</item>
- <item>Samuel, Sam, Sammy</item>
- <item>Sophia, Sophie</item>
- <item>Stephanie, Steph, Stephie</item>
- <item>Stephen, Steve</item>
- <item>Steven, Steve</item>
- <item>Stuart, Stu</item>
- <item>Susan, Sue, Susie, Suzie</item>
- <item>Suzanne, Sue, Susie, Suzie</item>
- <item>Teresa, Terrie, Terry</item>
- <item>Theodora, Teddie, Thea, Theo</item>
- <item>Theodore, Ted, Teddy, Theo</item>
- <item>Thomas, Tom, Thom, Tommy</item>
- <item>Timothy, Tim, Timmy</item>
- <item>Valerie, Val</item>
- <item>Veronica, Ronnie, Roni, Nica, Nikki, Nikka</item>
- <item>Victor, Vic</item>
- <item>Victoria, Vicky, Vicki, Vickie, Tori</item>
- <item>Vincent, Vince, Vin, Vinnie</item>
- <item>Vivian, Vivi</item>
- <item>Walter, Walt, Wally</item>
- <item>Wendy, Wen, Wendel</item>
- <item>William, Bill, Billy, Will, Willy, Liam</item>
- <item>Yvonna, Vonna</item>
- <item>Zachary, Zach, Zack, Zac</item>
- </string-array>
- <string name="common_name_prefixes">
- 1LT, 1ST, 2LT, 2ND, 3RD, ADMIRAL, CAPT, CAPTAIN, COL, CPT, DR,
- GEN, GENERAL, LCDR, LT, LTC, LTG, LTJG, MAJ, MAJOR, MG, MR,
- MRS, MS, PASTOR, PROF, REP, REVEREND, REV, SEN, ST
- </string>
- <string name="common_name_suffixes">
- B.A., BA, D.D.S., DDS, I, II, III, IV, IX, JR, M.A., M.D, MA,
- MD, MS, PH.D., PHD, SR, V, VI, VII, VIII, X
- </string>
- <string name="common_last_name_prefixes">
- D', DE, DEL, DI, LA, LE, MC, SAN, ST, TER, VAN, VON
- </string>
- <string name="common_name_conjunctions">
- &, AND, OR
- </string>
-
<!-- This string array should be overridden by the manufacture to present a list of carrier-id,locale,wifi-channel sets. This is used at startup to set system defaults by checking the system property ro.carrier for the carrier-id and searching through this array -->
<!-- An Array of [[Carrier-ID] -->
<!-- [default-locale] -->
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 1e3a4a8..bfdce1e 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -112,6 +112,7 @@
<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</item>
<item name="windowTitleSize">25dip</item>
<item name="windowTitleBackgroundStyle">@android:style/WindowTitleBackground</item>
diff --git a/docs/html/guide/developing/tools/aidl.jd b/docs/html/guide/developing/tools/aidl.jd
index f370a80..abfa8b1 100644
--- a/docs/html/guide/developing/tools/aidl.jd
+++ b/docs/html/guide/developing/tools/aidl.jd
@@ -194,7 +194,6 @@
<li>Make your class implement the {@link android.os.Parcelable} interface.</li>
<li>Implement the method <code>public void writeToParcel(Parcel out)</code> that takes the
current state of the object and writes it to a parcel.</li>
-<li>Implement the method <code>public void readFromParcel(Parcel in)</code> that reads the
value in a parcel into your object.</li>
<li>Add a static field called <code>CREATOR</code> to your class which is an object implementing
the {@link android.os.Parcelable.Creator Parcelable.Creator} interface.</li>
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index 2127187..11f8c7b 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -145,7 +145,9 @@
<li><a href="<?cs var:toroot ?>guide/topics/manifest/provider-element.html"><provider></a></li>
<li><a href="<?cs var:toroot ?>guide/topics/manifest/receiver-element.html"><receiver></a></li>
<li><a href="<?cs var:toroot ?>guide/topics/manifest/service-element.html"><service></a></li>
+ <li><a href="<?cs var:toroot ?>guide/topics/manifest/supports-screens-element.html"><supports-screens></a></li> <!-- ##api level 4## -->
<li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-configuration-element.html"><uses-configuration></a></li>
+ <li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-feature-element.html"><uses-feature></a></li> <!-- ##api level 4## -->
<li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-library-element.html"><uses-library></a></li>
<li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-permission-element.html"><uses-permission></a></li>
<li><a href="<?cs var:toroot ?>guide/topics/manifest/uses-sdk-element.html"><uses-sdk></a></li>
@@ -407,6 +409,9 @@
<span class="zh-TW">附錄</span>
</h2>
<ul>
+ <li><a href="<?cs var:toroot ?>guide/appendix/api-levels.html">
+ <span class="en">Android API Levels</span>
+ </a></li>
<li><a href="<?cs var:toroot ?>guide/appendix/media-formats.html">
<span class="en">Supported Media Formats</span>
</a></li>
diff --git a/docs/html/guide/topics/manifest/manifest-intro.jd b/docs/html/guide/topics/manifest/manifest-intro.jd
index 1907024..9e1b18d 100644
--- a/docs/html/guide/topics/manifest/manifest-intro.jd
+++ b/docs/html/guide/topics/manifest/manifest-intro.jd
@@ -78,10 +78,11 @@
<a href="{@docRoot}guide/topics/manifest/permission-element.html"><permission /></a>
<a href="{@docRoot}guide/topics/manifest/permission-tree-element.html"><permission-tree /></a>
<a href="{@docRoot}guide/topics/manifest/permission-group-element.html"><permission-group /></a>
-
<a href="{@docRoot}guide/topics/manifest/instrumentation-element.html"><instrumentation /></a>
-
<a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><uses-sdk /></a>
+ <a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html"><uses-configuration /></a> <!-- ##api level 3## -->
+ <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><uses-feature /></a> <!-- ##api level 4## -->
+ <a href="{@docRoot}guide/topics/manifest/supports-screens-element.html"><supports-screens /></a> <!-- ##api level 4## -->
<a href="{@docRoot}guide/topics/manifest/application-element.html"><application></a>
@@ -115,7 +116,6 @@
<a href="{@docRoot}guide/topics/manifest/provider-element.html"></provider></a>
<a href="{@docRoot}guide/topics/manifest/uses-library-element.html"><uses-library /></a>
- <a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html"><uses-configuration /></a> <!-- ##api level 3## -->
<a href="{@docRoot}guide/topics/manifest/application-element.html"></application></a>
@@ -146,13 +146,16 @@
<br/><code><a href="{@docRoot}guide/topics/manifest/provider-element.html"><provider></a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/receiver-element.html"><receiver></a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/service-element.html"><service></a></code>
+<br/><code><a href="{@docRoot}guide/topics/manifest/supports-screens-element.html"><supports-screens></a></code> <!-- ##api level 4## -->
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html"><uses-configuration></a></code> <!-- ##api level 3## -->
+<br/><code><a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><uses-feature></a></code> <!-- ##api level 4## -->
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-library-element.html"><uses-library></a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-permission-element.html"><uses-permission></a></code>
<br/><code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><uses-sdk></a></code>
</p>
+
<h2 id="filec">File Conventions</h2>
diff --git a/docs/html/guide/topics/manifest/supports-screens-element.jd b/docs/html/guide/topics/manifest/supports-screens-element.jd
new file mode 100644
index 0000000..00797ed
--- /dev/null
+++ b/docs/html/guide/topics/manifest/supports-screens-element.jd
@@ -0,0 +1,123 @@
+page.title=<supports-screens>
+@jd:body
+
+<dl class="xml">
+
+<dt>syntax:</dt>
+<dd>
+<pre class="stx">
+<supports-screens android:<a href="#small">smallScreens</a>=["true" | "false"]
+ android:<a href="#normal">normalScreens</a>=["true" | "false"]
+ android:<a href="#large">largeScreens</a>=["true" | "false"]
+ android:<a href="#any">anyDensity</a>=["true" | "false"] />
+</pre>
+</dd>
+
+<dt>contained in:</dt>
+<dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html"><manifest></a></code></dd>
+
+<dt>description:</dt>
+<dd>Lets you specify the screen dimensions the
+application supports. By default a modern application (using API Level 4 or higher) supports all
+screen sizes and must explicitly disable certain screen sizes here;
+older applications are assumed to support only the "normal"
+screen size. Note that screen size is a separate axis from
+density. Screen size is determined as the available pixels to an application
+after density scaling has been applied.
+
+<p>Based on the target device screen density, the Android
+framework will scale down assets by a factor of 0.75 (low dpi screens)
+or scale them up by a factor of 1.5 (high dpi screens).
+The screen density is expressed as dots-per-inch (dpi).</p>
+
+<p>Currently supported densities:</p>
+<ul>
+ <li>Low density: 120 dpi</li>
+ <li>Medium density: 160 dpi</li>
+ <li>High density: 240 dpi</li>
+</ul>
+
+<p>Table of display types:</p>
+
+<table>
+<tr>
+ <th></th><th>Low Density</th><th>Medium Density</th><th>High Density</th>
+</tr>
+<tr>
+ <th>Small Screen</th>
+ <td>QVGA</td>
+ <td>n/a</td>
+ <td>VGA</td>
+</tr>
+<tr>
+ <th>Normal Screen</th>
+ <td>WQVGA</td>
+ <td>HVGA</td>
+ <td>WVGA, FWVGA</td>
+</tr>
+<tr>
+ <th>Large Screen</th>
+ <td>n/a</td>
+ <td>VGA, WVGA, FWVGA</td>
+ <td>n/a</td>
+</tr>
+</table>
+
+</dd>
+
+
+<dt>attributes:</dt>
+
+<dd>
+<dl class="attr"><dt><a name="small"></a>{@code android:smallScreens}</dt>
+ <dd>Indicates whether the application supports smaller screen form-factors.
+ A small screen is defined as one with a smaller aspect ratio than
+ the "normal" (traditional HVGA) screen. An application that does
+ not support small screens <em>will not be available</em> for
+ small screen devices, because there is little the platform can do
+ to make such an application work on a smaller screen. Applications using
+ API Level 4 or higher default this to "true", others are "false".
+ </dd>
+
+ <dt><a name="normal"></a>{@code android:normalScreens}</dt>
+ <dd>Indicates whether an application supports the "normal" screen
+ form-factors. Traditionally this is an HVGA medium density
+ screen, but WQVGA low density and WVGA high density are also
+ considered to be normal. This attribute is "true" by default,
+ and applications currently should leave it that way.
+ </dd>
+
+ <dt><a name="large"></a>{@code android:largeScreens}</dt>
+ <dd>Indicates whether the application supports larger screen form-factors.
+ A large screen is defined as a screen that is significantly larger
+ than a "normal" phone screen, and thus may require some special care
+ on the application's part to make good use of it. An application that
+ does not support large screens will be placed as a "postage stamp" on
+ such a screen, so that it retains the dimensions it was originally
+ designed for. Applications using API Level 4 or higher default
+ to "true", others are "false".
+ </dd>
+
+ <dt><a name="any"></a>{@code android:anyDensity}</dt>
+ <dd>Indicates whether the application can accommodate any screen
+ density. Older applications (pre API Level 4) are assumed unable to
+ accomodate all densities and this is "false" by default. Applications using
+ API Level 4 or higher are assumed able to and this is "true" by default.
+ You can explicitly supply your abilities here.
+ </dd>
+
+
+</dl></dd>
+
+<!-- ##api level indication## -->
+<dt>introduced in:</dt>
+<dd>API Level 4</dd>
+
+<dt>see also:</dt>
+<dd>
+ <ul>
+ <li>{@link android.util.DisplayMetrics}</li>
+ </ul>
+</dd>
+
+</dl>
diff --git a/docs/html/guide/topics/manifest/uses-configuration-element.jd b/docs/html/guide/topics/manifest/uses-configuration-element.jd
index b26881e..4578c63 100755
--- a/docs/html/guide/topics/manifest/uses-configuration-element.jd
+++ b/docs/html/guide/topics/manifest/uses-configuration-element.jd
@@ -168,9 +168,14 @@
<dd>API Level 3</dd>
<dt>see also:</dt>
-<dd><code><a href="{@docRoot}guide/topics/manifest/activity-element.html#config">configChanges</a></code>
+<dd>
+ <ul>
+ <li><code><a href="{@docRoot}guide/topics/manifest/activity-element.html#config">configChanges</a></code>
attribute of the
<code><a href="{@docRoot}guide/topics/manifest/activity-element.html"><activity></a></code>
-element</dd>
+element</dd></li>
+ <li>{@link android.content.pm.ConfigurationInfo}</li>
+ </ul>
+</dd>
</dl>
diff --git a/docs/html/guide/topics/manifest/uses-feature-element.jd b/docs/html/guide/topics/manifest/uses-feature-element.jd
new file mode 100644
index 0000000..2626735
--- /dev/null
+++ b/docs/html/guide/topics/manifest/uses-feature-element.jd
@@ -0,0 +1,52 @@
+page.title=<uses-feature>
+@jd:body
+
+<dl class="xml">
+
+<dt>syntax:</dt>
+<dd>
+<pre class="stx">
+<uses-feature android:<a href="#glEsVersion">glEsVersion</a>=["true" | "false"] />
+</pre>
+</dd>
+
+<dt>contained in:</dt>
+<dd><code><a href="{@docRoot}guide/topics/manifest/manifest-element.html"><manifest></a></code></dd>
+
+<dt>description:</dt>
+<dd>This element specifies specific features used by the application.
+Android provides some features that may not be equally supported by all
+Android devices. In a manner similar to the <code><a href="uses-sdk-element.html"><uses-sdk></a></code>
+element, this element allows an application to specify which potentially variable
+features it requires. In this way, the application
+will not be installed on devices that do not offer the required feature.</p>
+
+<p>For example, an application might specify that it requires a certain version of Open GL.
+If a device does not support that version of Open GL, then it will not allow installation of the application.</p>
+</dd>
+
+
+<dt>attributes:</dt>
+
+<dd>
+<dl class="attr"><dt><a name="glEsVersion"></a>{@code android:glEsVersion}</dt>
+ <dd>The GLES version needed by the application.
+ The higher 16 bits represent the major number and the lower 16 bits
+ represent the minor number. For example, for GL 1.2 referring to
+ 0x00000102, the actual value should be set as 0x00010002.
+ </dd>
+</dl>
+</dd>
+
+<!-- ##api level indication## -->
+<dt>introduced in:</dt>
+<dd>API Level 4</dd>
+
+<dt>see also:</dt>
+<dd>
+ <ul>
+ <li>{@link android.content.pm.ConfigurationInfo}</li>
+ </ul>
+</dd>
+
+</dl>
diff --git a/docs/html/guide/topics/manifest/uses-sdk-element.jd b/docs/html/guide/topics/manifest/uses-sdk-element.jd
index b6e7374..adcdc28 100644
--- a/docs/html/guide/topics/manifest/uses-sdk-element.jd
+++ b/docs/html/guide/topics/manifest/uses-sdk-element.jd
@@ -11,50 +11,68 @@
<dt>description:</dt>
<dd>Lets you express an application's compatibility with one or more versions of the Android platform,
by means of an API Level integer. The API Level expressed by an application will be compared to the
-API Level of a given Android system, which may vary among different Android devices. To declare your
-application's minimum API Level compatibility, use the <a href="#min">minSdkVersion</a> attribute.
+API Level of a given Android system, which may vary among different Android devices.
</p>
<p>
-The default level is 1.
-</p>
-
-<p>
-For more information on the API level, see the
-<a href="{@docRoot}guide/publishing/versioning.html#minsdkversion">Specifying
-Minimum System API Version</a> section of
-<a href="{@docRoot}guide/publishing/versioning.html">Versioning Your
-Applications</a>.
-</p></dd>
-
-
-<dt>attributes:</dt>
-<dd><dl class="attr">
-<dt><a name="min"></a>{@code android:minSdkVersion}</dt>
-<dd>An integer designating the minimum level of the Android API that's required
-for the application to run.
-
-<p>
-Despite its name, this attribute specifies the API Level, <em>not</em> the
+Despite its name, this element is used to specify the API Level, <em>not</em> the
version number of the SDK (software development kit). The API Level is always
a single integer; the SDK version may be split into major and minor components
(such as 1.5). You cannot derive the API Level from the SDK version number
(for example, it is not the same as the major version or the sum of the major
-and minor versions). To learn what the API Level is, check the notes that
-came with the SDK you're using.</p>
+and minor versions).</p>
-<p>Prior to installing an application, the Android system checks the value of this
-attribute and allows the installation only if the
-API Level is less than or equal to the API Level used by the system itself.</p>
+<p>For more information, read about
+<a href="{@docRoot}guide/appendix/api-levels.html">Android API Levels</a> and
+<a href="{@docRoot}guide/publishing/versioning.html">Versioning Your Applications</a>.
+</p></dd>
-<p>If you do not declare this attribute, then a value of "1" is assumed, which
-indicates that your application is compatible with all versions of Android. If your
-application is <em>not</em> universally compatible (for instance if it uses APIs
-introduced in Android 1.5) and you have not declared the proper <code>minSdkVersion</code>,
-then when installed on a system with a lower API Level, the application
-will crash during runtime. For this reason, be certain to declare the appropriate API Level
-in the <code>minSdkVersion</code> attribute.</p>
-</dd>
+
+<dt>attributes:</dt>
+
+<dd>
+<dl class="attr">
+ <dt><a name="min"></a>{@code android:minSdkVersion}</dt>
+ <dd>An integer designating the minimum level of the Android API that's required
+ for the application to run.
+
+ <p>Prior to installing an application, the Android system checks the value of this
+ attribute and allows the installation only if it
+ is less than or equal to the API Level used by the system itself.</p>
+
+ <p>If you do not declare this attribute, then a value of "1" is assumed, which
+ indicates that your application is compatible with all versions of Android. If your
+ application is <em>not</em> universally compatible (for instance if it uses APIs
+ introduced in Android 1.5) and you have not declared the proper <code>minSdkVersion</code>,
+ then when installed on a system with a lower API Level, the application
+ will crash during runtime. For this reason, be certain to declare the appropriate API Level
+ in the <code>minSdkVersion</code> attribute.</p>
+ </dd>
+
+ <dt><a name="max"></a>{@code android:maxSdkVersion}</dt>
+ <dd>An integer designating the maximum level of the Android API that the application is
+ compatible with. You can use this to ensure your application is filtered out
+ of later versions of the platform when you know you have incompatibility with them.</p>
+
+ <p>Prior to installing an application, the Android system checks the value of this
+ attribute and allows the installation only it
+ is greater than or equal to the API Level used by the system itself.</p>
+
+ <p>Introduced in: API Level 4</p>
+ </dd>
+
+ <dt><a name="target"></a>{@code android:targetSdkVersion}</dt>
+ <dd>An integer designating the API Level that the application is targetting.
+
+ <p>With this attribute set, the application says that is is be able to run on
+ older versions (down to {@code minSdkVersion}), but was explicitly tested to work
+ with the version specified here.
+ Specifying this version allows the platform to disable compatibility
+ code that is not required or enable newer features that are not
+ available to older applications.</p>
+
+ <p>Introduced in: API Level 4</p>
+ </dd>
</dl></dd>
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 076cd0c..2abb777 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -73,7 +73,7 @@
public Bitmap.Config inPreferredConfig;
/**
- * If dither is true, the decoder will atttempt to dither the decoded
+ * If dither is true, the decoder will attempt to dither the decoded
* image.
*/
public boolean inDither;
@@ -452,6 +452,10 @@
bm = nativeDecodeStream(is, tempStorage, outPadding, opts);
}
+ return finishDecode(bm, outPadding, opts);
+ }
+
+ private static Bitmap finishDecode(Bitmap bm, Rect outPadding, Options opts) {
if (bm == null || opts == null) {
return bm;
}
@@ -487,7 +491,7 @@
return bm;
}
-
+
/**
* Decode an input stream into a bitmap. If the input stream is null, or
* cannot be used to decode a bitmap, the function returns null.
@@ -507,7 +511,7 @@
/**
* Decode a bitmap from the file descriptor. If the bitmap cannot be decoded
* return null. The position within the descriptor will not be changed when
- * this returns, so the descriptor can be used again as is.
+ * this returns, so the descriptor can be used again as-is.
*
* @param fd The file descriptor containing the bitmap data to decode
* @param outPadding If not null, return the padding rect for the bitmap if
@@ -524,13 +528,15 @@
int mappedlength = MemoryFile.getMappedSize(fd);
MemoryFile file = new MemoryFile(fd, mappedlength, "r");
InputStream is = file.getInputStream();
- return decodeStream(is, outPadding, opts);
+ Bitmap bm = decodeStream(is, outPadding, opts);
+ return finishDecode(bm, outPadding, opts);
}
} catch (IOException ex) {
// invalid filedescriptor, no need to call nativeDecodeFileDescriptor()
return null;
}
- return nativeDecodeFileDescriptor(fd, outPadding, opts);
+ Bitmap bm = nativeDecodeFileDescriptor(fd, outPadding, opts);
+ return finishDecode(bm, outPadding, opts);
}
/**
diff --git a/graphics/java/android/graphics/DashPathEffect.java b/graphics/java/android/graphics/DashPathEffect.java
index 3deca4a..4f16dc4 100644
--- a/graphics/java/android/graphics/DashPathEffect.java
+++ b/graphics/java/android/graphics/DashPathEffect.java
@@ -23,13 +23,13 @@
* the even indices specifying the "on" intervals, and the odd indices
* specifying the "off" intervals. phase is an offset into the intervals
* array (mod the sum of all of the intervals). The intervals array
- * controlls the width of the dashes. The paint's strokeWidth controlls the
- * height of the dashes.
+ * controls the length of the dashes. The paint's strokeWidth controls the
+ * thickness of the dashes.
* Note: this patheffect only affects drawing with the paint's style is set
* to STROKE or STROKE_AND_FILL. It is ignored if the drawing is done with
* style == FILL.
* @param intervals array of ON and OFF distances
- * @param phase offset before the first ON interval is drawn
+ * @param phase offset into the intervals array
*/
public DashPathEffect(float intervals[], float phase) {
if (intervals.length < 2) {
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 193f399..21b5e39 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -654,7 +654,7 @@
* Create a drawable from an inputstream
*/
public static Drawable createFromStream(InputStream is, String srcName) {
- return createFromResourceStream(null, null, is, srcName);
+ return createFromResourceStream(null, null, is, srcName, null);
}
/**
@@ -663,6 +663,15 @@
*/
public static Drawable createFromResourceStream(Resources res, TypedValue value,
InputStream is, String srcName) {
+ return createFromResourceStream(res, value, is, srcName, null);
+ }
+
+ /**
+ * Create a drawable from an inputstream, using the given resources and
+ * value to determine density information.
+ */
+ public static Drawable createFromResourceStream(Resources res, TypedValue value,
+ InputStream is, String srcName, BitmapFactory.Options opts) {
if (is == null) {
return null;
@@ -683,7 +692,7 @@
// an application in compatibility mode, without scaling those down
// to the compatibility density only to have them scaled back up when
// drawn to the screen.
- BitmapFactory.Options opts = new BitmapFactory.Options();
+ if (opts == null) opts = new BitmapFactory.Options();
opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE;
Bitmap bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts);
if (bm != null) {
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index 9155da8..cf181b7 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -16,9 +16,6 @@
package android.renderscript;
-import android.util.Config;
-import android.util.Log;
-
import java.lang.reflect.Field;
/**
@@ -193,9 +190,7 @@
void addEntry(Entry e) {
if(mEntries.length >= mEntryCount) {
Entry[] en = new Entry[mEntryCount + 8];
- for(int ct=0; ct < mEntries.length; ct++) {
- en[ct] = mEntries[ct];
- }
+ System.arraycopy(mEntries, 0, en, 0, mEntries.length);
mEntries = en;
}
mEntries[mEntryCount] = e;
@@ -228,6 +223,58 @@
return this;
}
+ public Builder addFloat(Element.DataKind dk) {
+ add(DataType.FLOAT, dk, false, 32, null);
+ return this;
+ }
+
+ public Builder addFloat(Element.DataKind dk, String name) {
+ add(DataType.FLOAT, dk, false, 32, name);
+ return this;
+ }
+
+ public Builder addFloatXY() {
+ add(DataType.FLOAT, DataKind.X, false, 32, null);
+ add(DataType.FLOAT, DataKind.Y, false, 32, null);
+ return this;
+ }
+
+ public Builder addFloatXYZ() {
+ add(DataType.FLOAT, DataKind.X, false, 32, null);
+ add(DataType.FLOAT, DataKind.Y, false, 32, null);
+ add(DataType.FLOAT, DataKind.Z, false, 32, null);
+ return this;
+ }
+
+ public Builder addFloatST() {
+ add(DataType.FLOAT, DataKind.S, false, 32, null);
+ add(DataType.FLOAT, DataKind.T, false, 32, null);
+ return this;
+ }
+
+ public Builder addFloatRGB() {
+ add(DataType.FLOAT, DataKind.RED, false, 32, null);
+ add(DataType.FLOAT, DataKind.GREEN, false, 32, null);
+ add(DataType.FLOAT, DataKind.BLUE, false, 32, null);
+ return this;
+ }
+
+ public Builder addFloatRGBA() {
+ add(DataType.FLOAT, DataKind.RED, false, 32, null);
+ add(DataType.FLOAT, DataKind.GREEN, false, 32, null);
+ add(DataType.FLOAT, DataKind.BLUE, false, 32, null);
+ add(DataType.FLOAT, DataKind.ALPHA, false, 32, null);
+ return this;
+ }
+
+ public Builder addUNorm8RGBA() {
+ add(DataType.UNSIGNED, DataKind.RED, true, 8, null);
+ add(DataType.UNSIGNED, DataKind.GREEN, true, 8, null);
+ add(DataType.UNSIGNED, DataKind.BLUE, true, 8, null);
+ add(DataType.UNSIGNED, DataKind.ALPHA, true, 8, null);
+ return this;
+ }
+
static synchronized Element internalCreate(RenderScript rs, Builder b) {
rs.nElementBegin();
for (int ct=0; ct < b.mEntryCount; ct++) {
diff --git a/graphics/java/android/renderscript/RSSurfaceView.java b/graphics/java/android/renderscript/RSSurfaceView.java
index f024bf6..a4be171 100644
--- a/graphics/java/android/renderscript/RSSurfaceView.java
+++ b/graphics/java/android/renderscript/RSSurfaceView.java
@@ -62,7 +62,6 @@
// underlying surface is created and destroyed
SurfaceHolder holder = getHolder();
holder.addCallback(this);
- holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
}
/**
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index b98a48ab..ab263ed 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -142,7 +142,7 @@
native void nScriptSetClearDepth(int script, float depth);
native void nScriptSetClearStencil(int script, int stencil);
native void nScriptSetTimeZone(int script, byte[] timeZone);
- native void nScriptSetType(int type, String name, int slot);
+ native void nScriptSetType(int type, boolean writable, String name, int slot);
native void nScriptSetRoot(boolean isRoot);
native void nScriptCBegin();
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index 47479d8..5b9eb553 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -24,6 +24,7 @@
boolean mIsRoot;
Type[] mTypes;
+ boolean[] mWritable;
Script(int id, RenderScript rs) {
super(rs);
@@ -67,11 +68,13 @@
boolean mIsRoot = false;
Type[] mTypes;
String[] mNames;
+ boolean[] mWritable;
Builder(RenderScript rs) {
mRS = rs;
mTypes = new Type[MAX_SLOT];
mNames = new String[MAX_SLOT];
+ mWritable = new boolean[MAX_SLOT];
}
public void setType(Type t, int slot) {
@@ -84,11 +87,15 @@
mNames[slot] = name;
}
+ public void setType(boolean writable, int slot) {
+ mWritable[slot] = writable;
+ }
+
void transferCreate() {
mRS.nScriptSetRoot(mIsRoot);
for(int ct=0; ct < mTypes.length; ct++) {
if(mTypes[ct] != null) {
- mRS.nScriptSetType(mTypes[ct].mID, mNames[ct], ct);
+ mRS.nScriptSetType(mTypes[ct].mID, mWritable[ct], mNames[ct], ct);
}
}
}
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 5780e02..ff997e7 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -74,7 +74,7 @@
jint len = _env->GetArrayLength(str);
jbyte * cptr = (jbyte *) _env->GetPrimitiveArrayCritical(str, 0);
- rsAssignName((void *)obj, (const char *)cptr, len);
+ rsAssignName(con, (void *)obj, (const char *)cptr, len);
_env->ReleasePrimitiveArrayCritical(str, cptr, JNI_ABORT);
}
@@ -87,7 +87,7 @@
jint len = _env->GetArrayLength(str);
jbyte * cptr = (jbyte *) _env->GetPrimitiveArrayCritical(str, 0);
- jint ret = (jint)rsFileOpen((const char *)cptr, len);
+ jint ret = (jint)rsFileOpen(con, (const char *)cptr, len);
_env->ReleasePrimitiveArrayCritical(str, cptr, JNI_ABORT);
return ret;
}
@@ -141,7 +141,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nElementBegin, con(%p)", con);
- rsElementBegin();
+ rsElementBegin(con);
}
static void
@@ -149,7 +149,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nElementAddPredefined, con(%p), predef(%i)", con, predef);
- rsElementAddPredefined((RsElementPredefined)predef);
+ rsElementAddPredefined(con, (RsElementPredefined)predef);
}
static void
@@ -161,7 +161,7 @@
n = _env->GetStringUTFChars(name, NULL);
}
LOG_API("nElementAdd, con(%p), kind(%i), type(%i), norm(%i), bits(%i)", con, kind, type, norm, bits);
- rsElementAdd((RsDataKind)kind, (RsDataType)type, norm != 0, (size_t)bits, n);
+ rsElementAdd(con, (RsDataKind)kind, (RsDataType)type, norm != 0, (size_t)bits, n);
if (n) {
_env->ReleaseStringUTFChars(name, n);
}
@@ -172,7 +172,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nElementCreate, con(%p)", con);
- return (jint)rsElementCreate();
+ return (jint)rsElementCreate(con);
}
static jint
@@ -180,7 +180,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nElementGetPredefined, con(%p) predef(%i)", con, predef);
- return (jint)rsElementGetPredefined((RsElementPredefined)predef);
+ return (jint)rsElementGetPredefined(con, (RsElementPredefined)predef);
}
static void
@@ -188,7 +188,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nElementDestroy, con(%p) e(%p)", con, (RsElement)e);
- rsElementDestroy((RsElement)e);
+ rsElementDestroy(con, (RsElement)e);
}
// -----------------------------------
@@ -198,7 +198,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nTypeBegin, con(%p) e(%p)", con, (RsElement)eID);
- rsTypeBegin((RsElement)eID);
+ rsTypeBegin(con, (RsElement)eID);
}
static void
@@ -206,7 +206,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nTypeAdd, con(%p) dim(%i), val(%i)", con, dim, val);
- rsTypeAdd((RsDimension)dim, val);
+ rsTypeAdd(con, (RsDimension)dim, val);
}
static jint
@@ -214,7 +214,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nTypeCreate, con(%p)", con);
- return (jint)rsTypeCreate();
+ return (jint)rsTypeCreate(con);
}
static void
@@ -222,7 +222,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nTypeDestroy, con(%p), t(%p)", con, (RsType)eID);
- rsTypeDestroy((RsType)eID);
+ rsTypeDestroy(con, (RsType)eID);
}
static void * SF_LoadInt(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
@@ -317,7 +317,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nAllocationCreateTyped, con(%p), e(%p)", con, (RsElement)e);
- return (jint) rsAllocationCreateTyped((RsElement)e);
+ return (jint) rsAllocationCreateTyped(con, (RsElement)e);
}
static jint
@@ -325,7 +325,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nAllocationCreatePredefSized, con(%p), predef(%i), count(%i)", con, predef, count);
- return (jint) rsAllocationCreatePredefSized((RsElementPredefined)predef, count);
+ return (jint) rsAllocationCreatePredefSized(con, (RsElementPredefined)predef, count);
}
static jint
@@ -333,7 +333,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nAllocationCreateSized, con(%p), e(%p), count(%i)", con, (RsElement)e, count);
- return (jint) rsAllocationCreateSized((RsElement)e, count);
+ return (jint) rsAllocationCreateSized(con, (RsElement)e, count);
}
static void
@@ -341,7 +341,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nAllocationUploadToTexture, con(%p), a(%p), mip(%i)", con, (RsAllocation)a, mip);
- rsAllocationUploadToTexture((RsAllocation)a, mip);
+ rsAllocationUploadToTexture(con, (RsAllocation)a, mip);
}
static RsElementPredefined SkBitmapToPredefined(SkBitmap::Config cfg)
@@ -380,7 +380,7 @@
const int w = bitmap.width();
const int h = bitmap.height();
const void* ptr = bitmap.getPixels();
- jint id = (jint)rsAllocationCreateFromBitmap(w, h, (RsElementPredefined)dstFmt, e, genMips, ptr);
+ jint id = (jint)rsAllocationCreateFromBitmap(con, w, h, (RsElementPredefined)dstFmt, e, genMips, ptr);
bitmap.unlockPixels();
return id;
}
@@ -403,7 +403,7 @@
const int w = bitmap.width();
const int h = bitmap.height();
const void* ptr = bitmap.getPixels();
- jint id = (jint)rsAllocationCreateFromBitmapBoxed(w, h, (RsElementPredefined)dstFmt, e, genMips, ptr);
+ jint id = (jint)rsAllocationCreateFromBitmapBoxed(con, w, h, (RsElementPredefined)dstFmt, e, genMips, ptr);
bitmap.unlockPixels();
return id;
}
@@ -416,7 +416,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nAllocationDestroy, con(%p), a(%p)", con, (RsAllocation)a);
- rsAllocationDestroy((RsAllocation)a);
+ rsAllocationDestroy(con, (RsAllocation)a);
}
static void
@@ -426,7 +426,7 @@
jint len = _env->GetArrayLength(data);
LOG_API("nAllocationData_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
jint *ptr = _env->GetIntArrayElements(data, NULL);
- rsAllocationData((RsAllocation)alloc, ptr);
+ rsAllocationData(con, (RsAllocation)alloc, ptr);
_env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
}
@@ -437,7 +437,7 @@
jint len = _env->GetArrayLength(data);
LOG_API("nAllocationData_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
- rsAllocationData((RsAllocation)alloc, ptr);
+ rsAllocationData(con, (RsAllocation)alloc, ptr);
_env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
}
@@ -448,7 +448,7 @@
jint len = _env->GetArrayLength(data);
LOG_API("nAllocation1DSubData_i, con(%p), adapter(%p), offset(%i), count(%i), len(%i)", con, (RsAllocation)alloc, offset, count, len);
jint *ptr = _env->GetIntArrayElements(data, NULL);
- rsAllocation1DSubData((RsAllocation)alloc, offset, count, ptr);
+ rsAllocation1DSubData(con, (RsAllocation)alloc, offset, count, ptr);
_env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
}
@@ -459,7 +459,7 @@
jint len = _env->GetArrayLength(data);
LOG_API("nAllocation1DSubData_f, con(%p), adapter(%p), offset(%i), count(%i), len(%i)", con, (RsAllocation)alloc, offset, count, len);
jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
- rsAllocation1DSubData((RsAllocation)alloc, offset, count, ptr);
+ rsAllocation1DSubData(con, (RsAllocation)alloc, offset, count, ptr);
_env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
}
@@ -470,7 +470,7 @@
jint len = _env->GetArrayLength(data);
LOG_API("nAllocation2DSubData_i, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, w, h, len);
jint *ptr = _env->GetIntArrayElements(data, NULL);
- rsAllocation2DSubData((RsAllocation)alloc, xoff, yoff, w, h, ptr);
+ rsAllocation2DSubData(con, (RsAllocation)alloc, xoff, yoff, w, h, ptr);
_env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
}
@@ -481,7 +481,7 @@
jint len = _env->GetArrayLength(data);
LOG_API("nAllocation2DSubData_i, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, w, h, len);
jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
- rsAllocation2DSubData((RsAllocation)alloc, xoff, yoff, w, h, ptr);
+ rsAllocation2DSubData(con, (RsAllocation)alloc, xoff, yoff, w, h, ptr);
_env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
}
@@ -492,7 +492,7 @@
jint len = _env->GetArrayLength(data);
LOG_API("nAllocationRead_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
jint *ptr = _env->GetIntArrayElements(data, NULL);
- rsAllocationRead((RsAllocation)alloc, ptr);
+ rsAllocationRead(con, (RsAllocation)alloc, ptr);
_env->ReleaseIntArrayElements(data, ptr, JNI_COMMIT);
}
@@ -503,7 +503,7 @@
jint len = _env->GetArrayLength(data);
LOG_API("nAllocationRead_f, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
- rsAllocationRead((RsAllocation)alloc, ptr);
+ rsAllocationRead(con, (RsAllocation)alloc, ptr);
_env->ReleaseFloatArrayElements(data, ptr, JNI_COMMIT);
}
@@ -523,7 +523,7 @@
const TypeFieldCache *tfc = &tc->fields[ct];
buf = tfc->ptr(_env, _o, tfc->field, buf);
}
- rsAllocationData((RsAllocation)alloc, bufAlloc);
+ rsAllocationData(con, (RsAllocation)alloc, bufAlloc);
const uint32_t * tmp = (const uint32_t *)bufAlloc;
free(bufAlloc);
}
@@ -535,7 +535,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nTriangleMeshDestroy, con(%p), tm(%p)", con, (RsAllocation)tm);
- rsTriangleMeshDestroy((RsTriangleMesh)tm);
+ rsTriangleMeshDestroy(con, (RsTriangleMesh)tm);
}
static void
@@ -543,7 +543,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nTriangleMeshBegin, con(%p), vertex(%p), index(%p)", con, (RsElement)v, (RsElement)i);
- rsTriangleMeshBegin((RsElement)v, (RsElement)i);
+ rsTriangleMeshBegin(con, (RsElement)v, (RsElement)i);
}
static void
@@ -552,7 +552,7 @@
float v[] = {x, y};
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nTriangleMeshAddVertex_XY, con(%p), x(%f), y(%f)", con, x, y);
- rsTriangleMeshAddVertex(v);
+ rsTriangleMeshAddVertex(con, v);
}
static void
@@ -561,7 +561,7 @@
float v[] = {x, y, z};
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nTriangleMeshAddVertex_XYZ, con(%p), x(%f), y(%f), z(%f)", con, x, y, z);
- rsTriangleMeshAddVertex(v);
+ rsTriangleMeshAddVertex(con, v);
}
static void
@@ -570,7 +570,7 @@
float v[] = {s, t, x, y};
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nTriangleMeshAddVertex_XY_ST, con(%p), x(%f), y(%f), s(%f), t(%f)", con, x, y, s, t);
- rsTriangleMeshAddVertex(v);
+ rsTriangleMeshAddVertex(con, v);
}
static void
@@ -579,7 +579,7 @@
float v[] = {s, t, x, y, z};
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nTriangleMeshAddVertex_XYZ_ST, con(%p), x(%f), y(%f), z(%f), s(%f), t(%f)", con, x, y, z, s, t);
- rsTriangleMeshAddVertex(v);
+ rsTriangleMeshAddVertex(con, v);
}
static void
@@ -588,7 +588,7 @@
float v[] = {nx, ny, nz, s, t, x, y, z};
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nTriangleMeshAddVertex_XYZ_ST, con(%p), x(%f), y(%f), z(%f), s(%f), t(%f)", con, x, y, z, s, t);
- rsTriangleMeshAddVertex(v);
+ rsTriangleMeshAddVertex(con, v);
}
static void
@@ -596,7 +596,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nTriangleMeshAddTriangle, con(%p), i1(%i), i2(%i), i3(%i)", con, i1, i2, i3);
- rsTriangleMeshAddTriangle(i1, i2, i3);
+ rsTriangleMeshAddTriangle(con, i1, i2, i3);
}
static jint
@@ -604,7 +604,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nTriangleMeshCreate, con(%p)", con);
- return (jint) rsTriangleMeshCreate();
+ return (jint) rsTriangleMeshCreate(con);
}
// -----------------------------------
@@ -614,7 +614,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nAdapter1DDestroy, con(%p), adapter(%p)", con, (RsAdapter1D)adapter);
- rsAdapter1DDestroy((RsAdapter1D)adapter);
+ rsAdapter1DDestroy(con, (RsAdapter1D)adapter);
}
static void
@@ -622,7 +622,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nAdapter1DBindAllocation, con(%p), adapter(%p), alloc(%p)", con, (RsAdapter1D)adapter, (RsAllocation)alloc);
- rsAdapter1DBindAllocation((RsAdapter1D)adapter, (RsAllocation)alloc);
+ rsAdapter1DBindAllocation(con, (RsAdapter1D)adapter, (RsAllocation)alloc);
}
static void
@@ -630,7 +630,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nAdapter1DSetConstraint, con(%p), adapter(%p), dim(%i), value(%i)", con, (RsAdapter1D)adapter, dim, value);
- rsAdapter1DSetConstraint((RsAdapter1D)adapter, (RsDimension)dim, value);
+ rsAdapter1DSetConstraint(con, (RsAdapter1D)adapter, (RsDimension)dim, value);
}
static void
@@ -640,7 +640,7 @@
jint len = _env->GetArrayLength(data);
LOG_API("nAdapter1DData_i, con(%p), adapter(%p), len(%i)", con, (RsAdapter1D)adapter, len);
jint *ptr = _env->GetIntArrayElements(data, NULL);
- rsAdapter1DData((RsAdapter1D)adapter, ptr);
+ rsAdapter1DData(con, (RsAdapter1D)adapter, ptr);
_env->ReleaseIntArrayElements(data, ptr, 0/*JNI_ABORT*/);
}
@@ -651,7 +651,7 @@
jint len = _env->GetArrayLength(data);
LOG_API("nAdapter1DSubData_i, con(%p), adapter(%p), offset(%i), count(%i), len(%i)", con, (RsAdapter1D)adapter, offset, count, len);
jint *ptr = _env->GetIntArrayElements(data, NULL);
- rsAdapter1DSubData((RsAdapter1D)adapter, offset, count, ptr);
+ rsAdapter1DSubData(con, (RsAdapter1D)adapter, offset, count, ptr);
_env->ReleaseIntArrayElements(data, ptr, 0/*JNI_ABORT*/);
}
@@ -662,7 +662,7 @@
jint len = _env->GetArrayLength(data);
LOG_API("nAdapter1DData_f, con(%p), adapter(%p), len(%i)", con, (RsAdapter1D)adapter, len);
jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
- rsAdapter1DData((RsAdapter1D)adapter, ptr);
+ rsAdapter1DData(con, (RsAdapter1D)adapter, ptr);
_env->ReleaseFloatArrayElements(data, ptr, 0/*JNI_ABORT*/);
}
@@ -673,7 +673,7 @@
jint len = _env->GetArrayLength(data);
LOG_API("nAdapter1DSubData_f, con(%p), adapter(%p), offset(%i), count(%i), len(%i)", con, (RsAdapter1D)adapter, offset, count, len);
jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
- rsAdapter1DSubData((RsAdapter1D)adapter, offset, count, ptr);
+ rsAdapter1DSubData(con, (RsAdapter1D)adapter, offset, count, ptr);
_env->ReleaseFloatArrayElements(data, ptr, 0/*JNI_ABORT*/);
}
@@ -682,7 +682,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nAdapter1DCreate, con(%p)", con);
- return (jint)rsAdapter1DCreate();
+ return (jint)rsAdapter1DCreate(con);
}
// -----------------------------------
@@ -692,7 +692,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nAdapter2DDestroy, con(%p), adapter(%p)", con, (RsAdapter2D)adapter);
- rsAdapter2DDestroy((RsAdapter2D)adapter);
+ rsAdapter2DDestroy(con, (RsAdapter2D)adapter);
}
static void
@@ -700,7 +700,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nAdapter2DBindAllocation, con(%p), adapter(%p), alloc(%p)", con, (RsAdapter2D)adapter, (RsAllocation)alloc);
- rsAdapter2DBindAllocation((RsAdapter2D)adapter, (RsAllocation)alloc);
+ rsAdapter2DBindAllocation(con, (RsAdapter2D)adapter, (RsAllocation)alloc);
}
static void
@@ -708,7 +708,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nAdapter2DSetConstraint, con(%p), adapter(%p), dim(%i), value(%i)", con, (RsAdapter2D)adapter, dim, value);
- rsAdapter2DSetConstraint((RsAdapter2D)adapter, (RsDimension)dim, value);
+ rsAdapter2DSetConstraint(con, (RsAdapter2D)adapter, (RsDimension)dim, value);
}
static void
@@ -718,7 +718,7 @@
jint len = _env->GetArrayLength(data);
LOG_API("nAdapter2DData_i, con(%p), adapter(%p), len(%i)", con, (RsAdapter2D)adapter, len);
jint *ptr = _env->GetIntArrayElements(data, NULL);
- rsAdapter2DData((RsAdapter2D)adapter, ptr);
+ rsAdapter2DData(con, (RsAdapter2D)adapter, ptr);
_env->ReleaseIntArrayElements(data, ptr, 0/*JNI_ABORT*/);
}
@@ -729,7 +729,7 @@
jint len = _env->GetArrayLength(data);
LOG_API("nAdapter2DData_f, con(%p), adapter(%p), len(%i)", con, (RsAdapter2D)adapter, len);
jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
- rsAdapter2DData((RsAdapter2D)adapter, ptr);
+ rsAdapter2DData(con, (RsAdapter2D)adapter, ptr);
_env->ReleaseFloatArrayElements(data, ptr, 0/*JNI_ABORT*/);
}
@@ -741,7 +741,7 @@
LOG_API("nAdapter2DSubData_i, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)",
con, (RsAdapter2D)adapter, xoff, yoff, w, h, len);
jint *ptr = _env->GetIntArrayElements(data, NULL);
- rsAdapter2DSubData((RsAdapter2D)adapter, xoff, yoff, w, h, ptr);
+ rsAdapter2DSubData(con, (RsAdapter2D)adapter, xoff, yoff, w, h, ptr);
_env->ReleaseIntArrayElements(data, ptr, 0/*JNI_ABORT*/);
}
@@ -753,7 +753,7 @@
LOG_API("nAdapter2DSubData_f, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)",
con, (RsAdapter2D)adapter, xoff, yoff, w, h, len);
jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
- rsAdapter2DSubData((RsAdapter1D)adapter, xoff, yoff, w, h, ptr);
+ rsAdapter2DSubData(con, (RsAdapter1D)adapter, xoff, yoff, w, h, ptr);
_env->ReleaseFloatArrayElements(data, ptr, 0/*JNI_ABORT*/);
}
@@ -762,7 +762,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nAdapter2DCreate, con(%p)", con);
- return (jint)rsAdapter2DCreate();
+ return (jint)rsAdapter2DCreate(con);
}
// -----------------------------------
@@ -772,7 +772,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nScriptDestroy, con(%p), script(%p)", con, (RsScript)script);
- rsScriptDestroy((RsScript)script);
+ rsScriptDestroy(con, (RsScript)script);
}
static void
@@ -780,7 +780,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nScriptBindAllocation, con(%p), script(%p), alloc(%p), slot(%i)", con, (RsScript)script, (RsAllocation)alloc, slot);
- rsScriptBindAllocation((RsScript)script, (RsAllocation)alloc, slot);
+ rsScriptBindAllocation(con, (RsScript)script, (RsAllocation)alloc, slot);
}
static void
@@ -788,7 +788,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nScriptSetClearColor, con(%p), s(%p), r(%f), g(%f), b(%f), a(%f)", con, script, r, g, b, a);
- rsScriptSetClearColor((RsScript)script, r, g, b, a);
+ rsScriptSetClearColor(con, (RsScript)script, r, g, b, a);
}
static void
@@ -796,7 +796,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nScriptCSetClearDepth, con(%p), s(%p), depth(%f)", con, script, d);
- rsScriptSetClearDepth((RsScript)script, d);
+ rsScriptSetClearDepth(con, (RsScript)script, d);
}
static void
@@ -804,7 +804,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nScriptCSetClearStencil, con(%p), s(%p), stencil(%i)", con, script, stencil);
- rsScriptSetClearStencil((RsScript)script, stencil);
+ rsScriptSetClearStencil(con, (RsScript)script, stencil);
}
static void
@@ -817,7 +817,7 @@
jbyte* timeZone_ptr;
timeZone_ptr = (jbyte *) _env->GetPrimitiveArrayCritical(timeZone, (jboolean *)0);
- rsScriptSetTimeZone((RsScript)script, (const char *)timeZone_ptr, length);
+ rsScriptSetTimeZone(con, (RsScript)script, (const char *)timeZone_ptr, length);
if (timeZone_ptr) {
_env->ReleasePrimitiveArrayCritical(timeZone, timeZone_ptr, 0);
@@ -825,15 +825,15 @@
}
static void
-nScriptSetType(JNIEnv *_env, jobject _this, jint type, jstring _str, jint slot)
+nScriptSetType(JNIEnv *_env, jobject _this, jint type, jboolean writable, jstring _str, jint slot)
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
- LOG_API("nScriptCAddType, con(%p), type(%p), slot(%i)", con, (RsType)type, slot);
+ LOG_API("nScriptCAddType, con(%p), type(%p), writable(%i), slot(%i)", con, (RsType)type, writable, slot);
const char* n = NULL;
if (_str) {
n = _env->GetStringUTFChars(_str, NULL);
}
- rsScriptSetType((RsType)type, slot, n);
+ rsScriptSetType(con, (RsType)type, slot, writable, n);
if (n) {
_env->ReleaseStringUTFChars(_str, n);
}
@@ -844,7 +844,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nScriptCSetRoot, con(%p), isRoot(%i)", con, isRoot);
- rsScriptSetRoot(isRoot);
+ rsScriptSetRoot(con, isRoot);
}
// -----------------------------------
@@ -854,7 +854,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nScriptCBegin, con(%p)", con);
- rsScriptCBegin();
+ rsScriptCBegin(con);
}
static void
@@ -892,7 +892,7 @@
_env->GetPrimitiveArrayCritical(scriptRef, (jboolean *)0);
script_ptr = script_base + offset;
- rsScriptCSetText((const char *)script_ptr, length);
+ rsScriptCSetText(con, (const char *)script_ptr, length);
exit:
if (script_base) {
@@ -906,7 +906,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nScriptCCreate, con(%p)", con);
- return (jint)rsScriptCCreate();
+ return (jint)rsScriptCCreate(con);
}
static void
@@ -915,7 +915,7 @@
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
const char* n = _env->GetStringUTFChars(name, NULL);
LOG_API("nScriptCAddDefineI32, con(%p) name(%s) value(%d)", con, n, value);
- rsScriptCSetDefineI32(n, value);
+ rsScriptCSetDefineI32(con, n, value);
_env->ReleaseStringUTFChars(name, n);
}
@@ -925,7 +925,7 @@
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
const char* n = _env->GetStringUTFChars(name, NULL);
LOG_API("nScriptCAddDefineF, con(%p) name(%s) value(%f)", con, n, value);
- rsScriptCSetDefineF(n, value);
+ rsScriptCSetDefineF(con, n, value);
_env->ReleaseStringUTFChars(name, n);
}
@@ -936,7 +936,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramFragmentStoreBegin, con(%p), in(%p), out(%p)", con, (RsElement)in, (RsElement)out);
- rsProgramFragmentStoreBegin((RsElement)in, (RsElement)out);
+ rsProgramFragmentStoreBegin(con, (RsElement)in, (RsElement)out);
}
static void
@@ -944,7 +944,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramFragmentStoreDepthFunc, con(%p), func(%i)", con, func);
- rsProgramFragmentStoreDepthFunc((RsDepthFunc)func);
+ rsProgramFragmentStoreDepthFunc(con, (RsDepthFunc)func);
}
static void
@@ -952,7 +952,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramFragmentStoreDepthMask, con(%p), enable(%i)", con, enable);
- rsProgramFragmentStoreDepthMask(enable);
+ rsProgramFragmentStoreDepthMask(con, enable);
}
static void
@@ -960,7 +960,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramFragmentStoreColorMask, con(%p), r(%i), g(%i), b(%i), a(%i)", con, r, g, b, a);
- rsProgramFragmentStoreColorMask(r, g, b, a);
+ rsProgramFragmentStoreColorMask(con, r, g, b, a);
}
static void
@@ -968,7 +968,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramFragmentStoreBlendFunc, con(%p), src(%i), dst(%i)", con, src, dst);
- rsProgramFragmentStoreBlendFunc((RsBlendSrcFunc)src, (RsBlendDstFunc)dst);
+ rsProgramFragmentStoreBlendFunc(con, (RsBlendSrcFunc)src, (RsBlendDstFunc)dst);
}
static void
@@ -976,7 +976,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramFragmentStoreDither, con(%p), enable(%i)", con, enable);
- rsProgramFragmentStoreDither(enable);
+ rsProgramFragmentStoreDither(con, enable);
}
static jint
@@ -985,7 +985,7 @@
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramFragmentStoreCreate, con(%p)", con);
- return (jint)rsProgramFragmentStoreCreate();
+ return (jint)rsProgramFragmentStoreCreate(con);
}
static void
@@ -993,7 +993,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramFragmentStoreDestroy, con(%p), pgm(%i)", con, pgm);
- rsProgramFragmentStoreDestroy((RsProgramFragmentStore)pgm);
+ rsProgramFragmentStoreDestroy(con, (RsProgramFragmentStore)pgm);
}
// ---------------------------------------------------------------------------
@@ -1003,7 +1003,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramFragmentBegin, con(%p), in(%p), out(%p)", con, (RsElement)in, (RsElement)out);
- rsProgramFragmentBegin((RsElement)in, (RsElement)out);
+ rsProgramFragmentBegin(con, (RsElement)in, (RsElement)out);
}
static void
@@ -1011,7 +1011,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramFragmentBindTexture, con(%p), vpf(%p), slot(%i), a(%p)", con, (RsProgramFragment)vpf, slot, (RsAllocation)a);
- rsProgramFragmentBindTexture((RsProgramFragment)vpf, slot, (RsAllocation)a);
+ rsProgramFragmentBindTexture(con, (RsProgramFragment)vpf, slot, (RsAllocation)a);
}
static void
@@ -1019,7 +1019,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramFragmentBindSampler, con(%p), vpf(%p), slot(%i), a(%p)", con, (RsProgramFragment)vpf, slot, (RsSampler)a);
- rsProgramFragmentBindSampler((RsProgramFragment)vpf, slot, (RsSampler)a);
+ rsProgramFragmentBindSampler(con, (RsProgramFragment)vpf, slot, (RsSampler)a);
}
static void
@@ -1027,7 +1027,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramFragmentSetType, con(%p), slot(%i), vt(%p)", con, slot, (RsType)vt);
- rsProgramFragmentSetType(slot, (RsType)vt);
+ rsProgramFragmentSetType(con, slot, (RsType)vt);
}
static void
@@ -1035,7 +1035,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramFragmentSetEnvMode, con(%p), slot(%i), vt(%i)", con, slot, env);
- rsProgramFragmentSetEnvMode(slot, (RsTexEnvMode)env);
+ rsProgramFragmentSetEnvMode(con, slot, (RsTexEnvMode)env);
}
static void
@@ -1043,7 +1043,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramFragmentSetTexEnable, con(%p), slot(%i), enable(%i)", con, slot, enable);
- rsProgramFragmentSetTexEnable(slot, enable);
+ rsProgramFragmentSetTexEnable(con, slot, enable);
}
static jint
@@ -1051,7 +1051,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramFragmentCreate, con(%p)", con);
- return (jint)rsProgramFragmentCreate();
+ return (jint)rsProgramFragmentCreate(con);
}
static void
@@ -1059,7 +1059,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramFragmentDestroy, con(%p), pgm(%i)", con, pgm);
- rsProgramFragmentDestroy((RsProgramFragment)pgm);
+ rsProgramFragmentDestroy(con, (RsProgramFragment)pgm);
}
// ---------------------------------------------------------------------------
@@ -1069,7 +1069,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramVertexBegin, con(%p), in(%p), out(%p)", con, (RsElement)in, (RsElement)out);
- rsProgramVertexBegin((RsElement)in, (RsElement)out);
+ rsProgramVertexBegin(con, (RsElement)in, (RsElement)out);
}
static void
@@ -1077,7 +1077,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramVertexBindAllocation, con(%p), vpf(%p), slot(%i), a(%p)", con, (RsProgramVertex)vpv, slot, (RsAllocation)a);
- rsProgramVertexBindAllocation((RsProgramFragment)vpv, (RsAllocation)a);
+ rsProgramVertexBindAllocation(con, (RsProgramFragment)vpv, (RsAllocation)a);
}
static void
@@ -1085,7 +1085,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramVertexSetTextureMatrixEnable, con(%p), enable(%i)", con, enable);
- rsProgramVertexSetTextureMatrixEnable(enable);
+ rsProgramVertexSetTextureMatrixEnable(con, enable);
}
static void
@@ -1093,7 +1093,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramVertexAddLight, con(%p), light(%p)", con, (RsLight)light);
- rsProgramVertexAddLight((RsLight)light);
+ rsProgramVertexAddLight(con, (RsLight)light);
}
static jint
@@ -1101,7 +1101,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramVertexCreate, con(%p)", con);
- return (jint)rsProgramVertexCreate();
+ return (jint)rsProgramVertexCreate(con);
}
static void
@@ -1109,7 +1109,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nProgramFragmentDestroy, con(%p), pgm(%i)", con, pgm);
- rsProgramFragmentDestroy((RsProgramFragment)pgm);
+ rsProgramFragmentDestroy(con, (RsProgramFragment)pgm);
}
@@ -1122,7 +1122,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nContextBindRootScript, con(%p), script(%p)", con, (RsScript)script);
- rsContextBindRootScript((RsScript)script);
+ rsContextBindRootScript(con, (RsScript)script);
}
static void
@@ -1130,7 +1130,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nContextBindProgramFragmentStore, con(%p), pfs(%p)", con, (RsProgramFragmentStore)pfs);
- rsContextBindProgramFragmentStore((RsProgramFragmentStore)pfs);
+ rsContextBindProgramFragmentStore(con, (RsProgramFragmentStore)pfs);
}
static void
@@ -1138,7 +1138,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nContextBindProgramFragment, con(%p), pf(%p)", con, (RsProgramFragment)pf);
- rsContextBindProgramFragment((RsProgramFragment)pf);
+ rsContextBindProgramFragment(con, (RsProgramFragment)pf);
}
static void
@@ -1146,7 +1146,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nContextBindProgramVertex, con(%p), pf(%p)", con, (RsProgramVertex)pf);
- rsContextBindProgramVertex((RsProgramVertex)pf);
+ rsContextBindProgramVertex(con, (RsProgramVertex)pf);
}
static void
@@ -1155,7 +1155,7 @@
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
const char* n = _env->GetStringUTFChars(name, NULL);
LOG_API("nScriptCAddDefineI32, con(%p) name(%s) value(%d)", con, n, value);
- rsContextSetDefineI32(n, value);
+ rsContextSetDefineI32(con, n, value);
_env->ReleaseStringUTFChars(name, n);
}
@@ -1165,7 +1165,7 @@
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
const char* n = _env->GetStringUTFChars(name, NULL);
LOG_API("nScriptCAddDefineF, con(%p) name(%s) value(%f)", con, n, value);
- rsContextSetDefineF(n, value);
+ rsContextSetDefineF(con, n, value);
_env->ReleaseStringUTFChars(name, n);
}
@@ -1177,7 +1177,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nSamplerDestroy, con(%p), sampler(%p)", con, (RsSampler)s);
- rsSamplerDestroy((RsSampler)s);
+ rsSamplerDestroy(con, (RsSampler)s);
}
static void
@@ -1185,7 +1185,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nSamplerBegin, con(%p)", con);
- rsSamplerBegin();
+ rsSamplerBegin(con);
}
static void
@@ -1193,7 +1193,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nSamplerSet, con(%p), param(%i), value(%i)", con, p, v);
- rsSamplerSet((RsSamplerParam)p, (RsSamplerValue)v);
+ rsSamplerSet(con, (RsSamplerParam)p, (RsSamplerValue)v);
}
static jint
@@ -1201,7 +1201,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nSamplerCreate, con(%p)", con);
- return (jint)rsSamplerCreate();
+ return (jint)rsSamplerCreate(con);
}
// ---------------------------------------------------------------------------
@@ -1211,7 +1211,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nLightBegin, con(%p)", con);
- rsLightBegin();
+ rsLightBegin(con);
}
static void
@@ -1219,7 +1219,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nLightSetIsMono, con(%p), isMono(%i)", con, isMono);
- rsLightSetMonochromatic(isMono);
+ rsLightSetMonochromatic(con, isMono);
}
static void
@@ -1227,7 +1227,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nLightSetIsLocal, con(%p), isLocal(%i)", con, isLocal);
- rsLightSetLocal(isLocal);
+ rsLightSetLocal(con, isLocal);
}
static jint
@@ -1235,7 +1235,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nLightCreate, con(%p)", con);
- return (jint)rsLightCreate();
+ return (jint)rsLightCreate(con);
}
static void
@@ -1243,7 +1243,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nLightDestroy, con(%p), light(%p)", con, (RsLight)light);
- rsLightDestroy((RsLight)light);
+ rsLightDestroy(con, (RsLight)light);
}
static void
@@ -1251,7 +1251,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nLightSetColor, con(%p), light(%p), r(%f), g(%f), b(%f)", con, (RsLight)light, r, g, b);
- rsLightSetColor((RsLight)light, r, g, b);
+ rsLightSetColor(con, (RsLight)light, r, g, b);
}
static void
@@ -1259,7 +1259,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nLightSetPosition, con(%p), light(%p), x(%f), y(%f), z(%f)", con, (RsLight)light, x, y, z);
- rsLightSetPosition((RsLight)light, x, y, z);
+ rsLightSetPosition(con, (RsLight)light, x, y, z);
}
// ---------------------------------------------------------------------------
@@ -1269,7 +1269,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nSimpleMeshDestroy, con(%p), SimpleMesh(%p)", con, (RsSimpleMesh)s);
- rsSimpleMeshDestroy((RsSimpleMesh)s);
+ rsSimpleMeshDestroy(con, (RsSimpleMesh)s);
}
static jint
@@ -1280,7 +1280,7 @@
LOG_API("nSimpleMeshCreate, con(%p), batchID(%i), indexID(%i), vtxIDs.len(%i), primID(%i)",
con, batchID, indexID, len, primID);
jint *ptr = _env->GetIntArrayElements(vtxIDs, NULL);
- int id = (int)rsSimpleMeshCreate((void *)batchID, (void *)indexID, (void **)ptr, len, primID);
+ int id = (int)rsSimpleMeshCreate(con, (void *)batchID, (void *)indexID, (void **)ptr, len, primID);
_env->ReleaseIntArrayElements(vtxIDs, ptr, 0/*JNI_ABORT*/);
return id;
}
@@ -1290,7 +1290,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nSimpleMeshBindVertex, con(%p), SimpleMesh(%p), Alloc(%p), slot(%i)", con, (RsSimpleMesh)s, (RsAllocation)alloc, slot);
- rsSimpleMeshBindVertex((RsSimpleMesh)s, (RsAllocation)alloc, slot);
+ rsSimpleMeshBindVertex(con, (RsSimpleMesh)s, (RsAllocation)alloc, slot);
}
static void
@@ -1298,7 +1298,7 @@
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nSimpleMeshBindIndex, con(%p), SimpleMesh(%p), Alloc(%p)", con, (RsSimpleMesh)s, (RsAllocation)alloc);
- rsSimpleMeshBindIndex((RsSimpleMesh)s, (RsAllocation)alloc);
+ rsSimpleMeshBindIndex(con, (RsSimpleMesh)s, (RsAllocation)alloc);
}
// ---------------------------------------------------------------------------
@@ -1381,7 +1381,7 @@
{"nScriptSetClearDepth", "(IF)V", (void*)nScriptSetClearDepth },
{"nScriptSetClearStencil", "(II)V", (void*)nScriptSetClearStencil },
{"nScriptSetTimeZone", "(I[B)V", (void*)nScriptSetTimeZone },
-{"nScriptSetType", "(ILjava/lang/String;I)V", (void*)nScriptSetType },
+{"nScriptSetType", "(IZLjava/lang/String;I)V", (void*)nScriptSetType },
{"nScriptSetRoot", "(Z)V", (void*)nScriptSetRoot },
{"nScriptCBegin", "()V", (void*)nScriptCBegin },
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 58c2d9a..ba6c711 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -74,6 +74,7 @@
status_t writeInt64(int64_t val);
status_t writeFloat(float val);
status_t writeDouble(double val);
+ status_t writeIntPtr(intptr_t val);
status_t writeCString(const char* str);
status_t writeString8(const String8& str);
status_t writeString16(const String16& str);
@@ -109,6 +110,8 @@
status_t readFloat(float *pArg) const;
double readDouble() const;
status_t readDouble(double *pArg) const;
+ intptr_t readIntPtr() const;
+ status_t readIntPtr(intptr_t *pArg) const;
const char* readCString() const;
String8 readString8() const;
@@ -163,6 +166,14 @@
void initState();
void scanForFds() const;
+ template<class T>
+ status_t readAligned(T *pArg) const;
+
+ template<class T> T readAligned() const;
+
+ template<class T>
+ status_t writeAligned(T val);
+
status_t mError;
uint8_t* mData;
size_t mDataSize;
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index 7e5ff61..58a74c7 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -56,6 +56,14 @@
node_id node, OMX_INDEXTYPE index,
const void *params, size_t size) = 0;
+ virtual status_t get_config(
+ node_id node, OMX_INDEXTYPE index,
+ void *params, size_t size) = 0;
+
+ virtual status_t set_config(
+ node_id node, OMX_INDEXTYPE index,
+ const void *params, size_t size) = 0;
+
virtual status_t use_buffer(
node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
buffer_id *buffer) = 0;
@@ -82,6 +90,11 @@
OMX_U32 range_offset, OMX_U32 range_length,
OMX_U32 flags, OMX_TICKS timestamp) = 0;
+ virtual status_t get_extension_index(
+ node_id node,
+ const char *parameter_name,
+ OMX_INDEXTYPE *index) = 0;
+
virtual sp<IOMXRenderer> createRenderer(
const sp<ISurface> &surface,
const char *componentName,
@@ -114,10 +127,11 @@
QUIT_OBSERVER,
} type;
+ IOMX::node_id node;
+
union {
// if type == EVENT
struct {
- IOMX::node_id node;
OMX_EVENTTYPE event;
OMX_U32 data1;
OMX_U32 data2;
@@ -126,13 +140,11 @@
// if type == EMPTY_BUFFER_DONE || type == FILL_BUFFER
// || type == INITIAL_FILL_BUFFER
struct {
- IOMX::node_id node;
IOMX::buffer_id buffer;
} buffer_data;
// if type == EMPTY_BUFFER || type == FILL_BUFFER_DONE
struct {
- IOMX::node_id node;
IOMX::buffer_id buffer;
OMX_U32 range_offset;
OMX_U32 range_length;
@@ -143,7 +155,6 @@
// if type == SEND_COMMAND
struct {
- IOMX::node_id node;
OMX_COMMANDTYPE cmd;
OMX_S32 param;
} send_command_data;
diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h
index 3db8a0f..9ea2775 100644
--- a/include/media/mediametadataretriever.h
+++ b/include/media/mediametadataretriever.h
@@ -52,6 +52,7 @@
METADATA_KEY_VIDEO_FORMAT = 18,
METADATA_KEY_VIDEO_HEIGHT = 19,
METADATA_KEY_VIDEO_WIDTH = 20,
+ METADATA_KEY_WRITER = 21,
// Add more here...
};
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
index 0f2e528..960eda3 100644
--- a/include/media/stagefright/AudioPlayer.h
+++ b/include/media/stagefright/AudioPlayer.h
@@ -31,10 +31,10 @@
class AudioPlayer : public TimeSource {
public:
AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink);
- ~AudioPlayer();
+ virtual ~AudioPlayer();
// Caller retains ownership of "source".
- void setSource(MediaSource *source);
+ void setSource(const sp<MediaSource> &source);
// Return time in us.
virtual int64_t getRealTimeUs();
@@ -56,7 +56,7 @@
status_t seekTo(int64_t time_us);
private:
- MediaSource *mSource;
+ sp<MediaSource> mSource;
AudioTrack *mAudioTrack;
MediaBuffer *mInputBuffer;
diff --git a/include/media/stagefright/CachingDataSource.h b/include/media/stagefright/CachingDataSource.h
index e275cb4..e35e19e 100644
--- a/include/media/stagefright/CachingDataSource.h
+++ b/include/media/stagefright/CachingDataSource.h
@@ -26,14 +26,16 @@
class CachingDataSource : public DataSource {
public:
- // Assumes ownership of "source".
- CachingDataSource(DataSource *source, size_t pageSize, int numPages);
- virtual ~CachingDataSource();
+ CachingDataSource(
+ const sp<DataSource> &source, size_t pageSize, int numPages);
status_t InitCheck() const;
virtual ssize_t read_at(off_t offset, void *data, size_t size);
+protected:
+ virtual ~CachingDataSource();
+
private:
struct Page {
Page *mPrev, *mNext;
@@ -42,7 +44,7 @@
void *mData;
};
- DataSource *mSource;
+ sp<DataSource> mSource;
void *mData;
size_t mPageSize;
Page *mFirst, *mLast;
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index 31eea27..f46f0af 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -22,19 +22,22 @@
#include <utils/Errors.h>
#include <utils/List.h>
+#include <utils/RefBase.h>
#include <utils/threads.h>
namespace android {
class String8;
-class DataSource {
+class DataSource : public RefBase {
public:
DataSource() {}
- virtual ~DataSource() {}
virtual ssize_t read_at(off_t offset, void *data, size_t size) = 0;
+ // Convenience methods:
+ bool getUInt16(off_t offset, uint16_t *x);
+
// May return ERROR_UNSUPPORTED.
virtual status_t getSize(off_t *size);
@@ -43,11 +46,14 @@
bool sniff(String8 *mimeType, float *confidence);
typedef bool (*SnifferFunc)(
- DataSource *source, String8 *mimeType, float *confidence);
+ const sp<DataSource> &source, String8 *mimeType, float *confidence);
static void RegisterSniffer(SnifferFunc func);
static void RegisterDefaultSniffers();
+protected:
+ virtual ~DataSource() {}
+
private:
static Mutex gSnifferMutex;
static List<SnifferFunc> gSniffers;
diff --git a/include/media/stagefright/MP3Extractor.h b/include/media/stagefright/MP3Extractor.h
index 09cfb70..4e1f3c3 100644
--- a/include/media/stagefright/MP3Extractor.h
+++ b/include/media/stagefright/MP3Extractor.h
@@ -28,16 +28,17 @@
class MP3Extractor : public MediaExtractor {
public:
// Extractor assumes ownership of "source".
- MP3Extractor(DataSource *source);
+ MP3Extractor(const sp<DataSource> &source);
- ~MP3Extractor();
+ size_t countTracks();
+ sp<MediaSource> getTrack(size_t index);
+ sp<MetaData> getTrackMetaData(size_t index);
- status_t countTracks(int *num_tracks);
- status_t getTrack(int index, MediaSource **source);
- sp<MetaData> getTrackMetaData(int index);
+protected:
+ virtual ~MP3Extractor();
private:
- DataSource *mDataSource;
+ sp<DataSource> mDataSource;
off_t mFirstFramePos;
sp<MetaData> mMeta;
uint32_t mFixedHeader;
@@ -46,7 +47,8 @@
MP3Extractor &operator=(const MP3Extractor &);
};
-bool SniffMP3(DataSource *source, String8 *mimeType, float *confidence);
+bool SniffMP3(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence);
} // namespace android
diff --git a/include/media/stagefright/MPEG4Extractor.h b/include/media/stagefright/MPEG4Extractor.h
index 51a7e82..932e30f 100644
--- a/include/media/stagefright/MPEG4Extractor.h
+++ b/include/media/stagefright/MPEG4Extractor.h
@@ -29,22 +29,24 @@
class MPEG4Extractor : public MediaExtractor {
public:
// Extractor assumes ownership of "source".
- MPEG4Extractor(DataSource *source);
- ~MPEG4Extractor();
+ MPEG4Extractor(const sp<DataSource> &source);
- status_t countTracks(int *num_tracks);
- status_t getTrack(int index, MediaSource **source);
- sp<MetaData> getTrackMetaData(int index);
+ size_t countTracks();
+ sp<MediaSource> getTrack(size_t index);
+ sp<MetaData> getTrackMetaData(size_t index);
+
+protected:
+ virtual ~MPEG4Extractor();
private:
struct Track {
Track *next;
sp<MetaData> meta;
uint32_t timescale;
- SampleTable *sampleTable;
+ sp<SampleTable> sampleTable;
};
- DataSource *mDataSource;
+ sp<DataSource> mDataSource;
bool mHaveMetadata;
Track *mFirstTrack, *mLastTrack;
@@ -58,7 +60,8 @@
MPEG4Extractor &operator=(const MPEG4Extractor &);
};
-bool SniffMPEG4(DataSource *source, String8 *mimeType, float *confidence);
+bool SniffMPEG4(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence);
} // namespace android
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 40d6127..5147de9 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -30,13 +30,12 @@
class MediaSource;
class MetaData;
-class MPEG4Writer {
+class MPEG4Writer : public RefBase {
public:
MPEG4Writer(const char *filename);
- ~MPEG4Writer();
// Caller retains ownership of both meta and source.
- void addSource(const sp<MetaData> &meta, MediaSource *source);
+ void addSource(const sp<MetaData> &meta, const sp<MediaSource> &source);
void start();
void stop();
@@ -50,6 +49,9 @@
void write(const void *data, size_t size);
void endBox();
+protected:
+ virtual ~MPEG4Writer();
+
private:
class Track;
diff --git a/include/media/stagefright/MediaBuffer.h b/include/media/stagefright/MediaBuffer.h
index c72ed66..339e6fb 100644
--- a/include/media/stagefright/MediaBuffer.h
+++ b/include/media/stagefright/MediaBuffer.h
@@ -75,6 +75,8 @@
// MetaData.
MediaBuffer *clone();
+ int refcount() const;
+
protected:
virtual ~MediaBuffer();
@@ -102,8 +104,6 @@
void setNextBuffer(MediaBuffer *buffer);
MediaBuffer *nextBuffer();
- int refcount() const;
-
MediaBuffer(const MediaBuffer &);
MediaBuffer &operator=(const MediaBuffer &);
};
diff --git a/include/media/stagefright/MediaDebug.h b/include/media/stagefright/MediaDebug.h
new file mode 100644
index 0000000..83acd77
--- /dev/null
+++ b/include/media/stagefright/MediaDebug.h
@@ -0,0 +1,18 @@
+#ifndef MEDIA_DEBUG_H_
+
+#define MEDIA_DEBUG_H_
+
+#define LITERAL_TO_STRING_INTERNAL(x) #x
+#define LITERAL_TO_STRING(x) LITERAL_TO_STRING_INTERNAL(x)
+
+#define CHECK_EQ(x,y) \
+ LOG_ALWAYS_FATAL_IF( \
+ (x) != (y), \
+ __FILE__ ":" LITERAL_TO_STRING(__LINE__) " " #x " != " #y)
+
+#define CHECK(x) \
+ LOG_ALWAYS_FATAL_IF( \
+ !(x), \
+ __FILE__ ":" LITERAL_TO_STRING(__LINE__) " " #x)
+
+#endif // MEDIA_DEBUG_H_
diff --git a/include/media/stagefright/MediaExtractor.h b/include/media/stagefright/MediaExtractor.h
index 38f8e5b..67e45bd 100644
--- a/include/media/stagefright/MediaExtractor.h
+++ b/include/media/stagefright/MediaExtractor.h
@@ -26,18 +26,18 @@
class MediaSource;
class MetaData;
-class MediaExtractor {
+class MediaExtractor : public RefBase {
public:
- static MediaExtractor *Create(DataSource *source, const char *mime = NULL);
+ static sp<MediaExtractor> Create(
+ const sp<DataSource> &source, const char *mime = NULL);
- virtual ~MediaExtractor() {}
-
- virtual status_t countTracks(int *num_tracks) = 0;
- virtual status_t getTrack(int index, MediaSource **source) = 0;
- virtual sp<MetaData> getTrackMetaData(int index) = 0;
+ virtual size_t countTracks() = 0;
+ virtual sp<MediaSource> getTrack(size_t index) = 0;
+ virtual sp<MetaData> getTrackMetaData(size_t index) = 0;
protected:
MediaExtractor() {}
+ virtual ~MediaExtractor() {}
private:
MediaExtractor(const MediaExtractor &);
diff --git a/include/media/stagefright/MediaPlayerImpl.h b/include/media/stagefright/MediaPlayerImpl.h
index e96e5e8..53a2088 100644
--- a/include/media/stagefright/MediaPlayerImpl.h
+++ b/include/media/stagefright/MediaPlayerImpl.h
@@ -35,7 +35,6 @@
class MediaSource;
class MemoryHeapPmem;
class MetaData;
-class OMXDecoder;
class Surface;
class TimeSource;
@@ -71,16 +70,16 @@
OMXClient mClient;
- MediaExtractor *mExtractor;
+ sp<MediaExtractor> mExtractor;
TimeSource *mTimeSource;
- MediaSource *mAudioSource;
- OMXDecoder *mAudioDecoder;
+ sp<MediaSource> mAudioSource;
+ sp<MediaSource> mAudioDecoder;
AudioPlayer *mAudioPlayer;
- MediaSource *mVideoSource;
- MediaSource *mVideoDecoder;
+ sp<MediaSource> mVideoSource;
+ sp<MediaSource> mVideoDecoder;
int32_t mVideoWidth, mVideoHeight;
int64_t mVideoPosition;
@@ -103,16 +102,13 @@
bool mSeeking;
int64_t mSeekTimeUs;
- size_t mFrameSize;
- bool mUseSoftwareColorConversion;
-
void init();
static void *VideoWrapper(void *me);
void videoEntry();
- void setAudioSource(MediaSource *source);
- void setVideoSource(MediaSource *source);
+ void setAudioSource(const sp<MediaSource> &source);
+ void setVideoSource(const sp<MediaSource> &source);
MediaSource *makeShoutcastSource(const char *path);
diff --git a/include/media/stagefright/MediaSource.h b/include/media/stagefright/MediaSource.h
index eb07f68..d1fa114 100644
--- a/include/media/stagefright/MediaSource.h
+++ b/include/media/stagefright/MediaSource.h
@@ -27,9 +27,8 @@
class MediaBuffer;
class MetaData;
-struct MediaSource {
+struct MediaSource : public RefBase {
MediaSource();
- virtual ~MediaSource();
// To be called before any other methods on this object, except
// getFormat().
@@ -81,6 +80,9 @@
int64_t mLatenessUs;
};
+protected:
+ virtual ~MediaSource();
+
private:
MediaSource(const MediaSource &);
MediaSource &operator=(const MediaSource &);
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
new file mode 100644
index 0000000..d4ae349
--- /dev/null
+++ b/include/media/stagefright/OMXCodec.h
@@ -0,0 +1,190 @@
+/*
+ * 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.
+ */
+
+#ifndef OMX_CODEC_H_
+
+#define OMX_CODEC_H_
+
+#include <media/IOMX.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaSource.h>
+#include <utils/threads.h>
+
+namespace android {
+
+class MemoryDealer;
+struct OMXCodecObserver;
+
+struct OMXCodec : public MediaSource,
+ public MediaBufferObserver {
+ static sp<OMXCodec> Create(
+ const sp<IOMX> &omx,
+ const sp<MetaData> &meta, bool createEncoder,
+ const sp<MediaSource> &source);
+
+ virtual status_t start(MetaData *params = NULL);
+ virtual status_t stop();
+
+ virtual sp<MetaData> getFormat();
+
+ virtual status_t read(
+ MediaBuffer **buffer, const ReadOptions *options = NULL);
+
+ void on_message(const omx_message &msg);
+
+ // from MediaBufferObserver
+ virtual void signalBufferReturned(MediaBuffer *buffer);
+
+protected:
+ virtual ~OMXCodec();
+
+private:
+ enum State {
+ DEAD,
+ LOADED,
+ LOADED_TO_IDLE,
+ IDLE_TO_EXECUTING,
+ EXECUTING,
+ EXECUTING_TO_IDLE,
+ IDLE_TO_LOADED,
+ RECONFIGURING,
+ ERROR
+ };
+
+ enum {
+ kPortIndexInput = 0,
+ kPortIndexOutput = 1
+ };
+
+ enum PortStatus {
+ ENABLED,
+ DISABLING,
+ DISABLED,
+ ENABLING,
+ SHUTTING_DOWN,
+ };
+
+ enum Quirks {
+ kNeedsFlushBeforeDisable = 1,
+ kWantsRawNALFrames = 2,
+ kRequiresLoadedToIdleAfterAllocation = 4,
+ kRequiresAllocateBufferOnInputPorts = 8,
+ };
+
+ struct BufferInfo {
+ IOMX::buffer_id mBuffer;
+ bool mOwnedByComponent;
+ sp<IMemory> mMem;
+ MediaBuffer *mMediaBuffer;
+ };
+
+ struct CodecSpecificData {
+ size_t mSize;
+ uint8_t mData[1];
+ };
+
+ sp<IOMX> mOMX;
+ IOMX::node_id mNode;
+ sp<OMXCodecObserver> mObserver;
+ uint32_t mQuirks;
+ bool mIsEncoder;
+ char *mMIME;
+ char *mComponentName;
+ sp<MetaData> mOutputFormat;
+ sp<MediaSource> mSource;
+ Vector<CodecSpecificData *> mCodecSpecificData;
+ size_t mCodecSpecificDataIndex;
+
+ sp<MemoryDealer> mDealer;
+
+ State mState;
+ Vector<BufferInfo> mPortBuffers[2];
+ PortStatus mPortStatus[2];
+ bool mSignalledEOS;
+ bool mNoMoreOutputData;
+ int64_t mSeekTimeUs;
+
+ Mutex mLock;
+ Condition mAsyncCompletion;
+
+ // A list of indices into mPortStatus[kPortIndexOutput] filled with data.
+ List<size_t> mFilledBuffers;
+ Condition mBufferFilled;
+
+ OMXCodec(const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
+ bool isEncoder, const char *mime, const char *componentName,
+ const sp<MediaSource> &source);
+
+ void addCodecSpecificData(const void *data, size_t size);
+ void clearCodecSpecificData();
+
+ void setAMRFormat();
+ void setAACFormat();
+
+ status_t setVideoPortFormatType(
+ OMX_U32 portIndex,
+ OMX_VIDEO_CODINGTYPE compressionFormat,
+ OMX_COLOR_FORMATTYPE colorFormat);
+
+ void setVideoInputFormat(
+ const char *mime, OMX_U32 width, OMX_U32 height);
+
+ void setVideoOutputFormat(
+ const char *mime, OMX_U32 width, OMX_U32 height);
+
+ void setImageOutputFormat(
+ OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height);
+
+ status_t allocateBuffers();
+ status_t allocateBuffersOnPort(OMX_U32 portIndex);
+
+ status_t freeBuffersOnPort(
+ OMX_U32 portIndex, bool onlyThoseWeOwn = false);
+
+ void drainInputBuffer(IOMX::buffer_id buffer);
+ void fillOutputBuffer(IOMX::buffer_id buffer);
+ void drainInputBuffer(BufferInfo *info);
+ void fillOutputBuffer(BufferInfo *info);
+
+ void drainInputBuffers();
+ void fillOutputBuffers();
+
+ void flushPortAsync(OMX_U32 portIndex);
+ void disablePortAsync(OMX_U32 portIndex);
+ void enablePortAsync(OMX_U32 portIndex);
+
+ static size_t countBuffersWeOwn(const Vector<BufferInfo> &buffers);
+ static bool isIntermediateState(State state);
+
+ void onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2);
+ void onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data);
+ void onStateChange(OMX_STATETYPE newState);
+ void onPortSettingsChanged(OMX_U32 portIndex);
+
+ void setState(State newState);
+
+ status_t init();
+ void initOutputFormat(const sp<MetaData> &inputFormat);
+
+ void dumpPortStatus(OMX_U32 portIndex);
+
+ OMXCodec(const OMXCodec &);
+ OMXCodec &operator=(const OMXCodec &);
+};
+
+} // namespace android
+
+#endif // OMX_CODEC_H_
diff --git a/include/media/stagefright/OMXDecoder.h b/include/media/stagefright/OMXDecoder.h
index c6b7cb3..0abc5a6 100644
--- a/include/media/stagefright/OMXDecoder.h
+++ b/include/media/stagefright/OMXDecoder.h
@@ -36,14 +36,10 @@
public OMXObserver,
public MediaBufferObserver {
public:
- static OMXDecoder *Create(
+ static sp<OMXDecoder> Create(
OMXClient *client, const sp<MetaData> &data,
- bool createEncoder = false);
-
- virtual ~OMXDecoder();
-
- // Caller retains ownership of "source".
- void setSource(MediaSource *source);
+ bool createEncoder,
+ const sp<MediaSource> &source);
virtual status_t start(MetaData *params = NULL);
virtual status_t stop();
@@ -61,6 +57,9 @@
// from MediaBufferObserver
virtual void signalBufferReturned(MediaBuffer *buffer);
+protected:
+ virtual ~OMXDecoder();
+
private:
enum {
kPortIndexInput = 0,
@@ -97,7 +96,7 @@
bool mIsEncoder;
uint32_t mQuirks;
- MediaSource *mSource;
+ sp<MediaSource> mSource;
sp<MetaData> mOutputFormat;
Mutex mLock;
@@ -135,7 +134,8 @@
OMXDecoder(OMXClient *client, IOMX::node_id node,
const char *mime, const char *codec,
bool is_encoder,
- uint32_t quirks);
+ uint32_t quirks,
+ const sp<MediaSource> &source);
void setPortStatus(OMX_U32 port_index, PortStatus status);
PortStatus getPortStatus(OMX_U32 port_index) const;
diff --git a/include/media/stagefright/SampleTable.h b/include/media/stagefright/SampleTable.h
index 712da10..808d142 100644
--- a/include/media/stagefright/SampleTable.h
+++ b/include/media/stagefright/SampleTable.h
@@ -22,17 +22,16 @@
#include <stdint.h>
#include <media/stagefright/MediaErrors.h>
+#include <utils/RefBase.h>
#include <utils/threads.h>
namespace android {
class DataSource;
-class SampleTable {
+class SampleTable : public RefBase {
public:
- // Caller retains ownership of "source".
- SampleTable(DataSource *source);
- ~SampleTable();
+ SampleTable(const sp<DataSource> &source);
// type can be 'stco' or 'co64'.
status_t setChunkOffsetParams(
@@ -76,8 +75,11 @@
status_t findClosestSyncSample(
uint32_t start_sample_index, uint32_t *sample_index);
+protected:
+ ~SampleTable();
+
private:
- DataSource *mDataSource;
+ sp<DataSource> mDataSource;
Mutex mLock;
off_t mChunkOffsetOffset;
diff --git a/include/private/ui/android_natives_priv.h b/include/private/ui/android_natives_priv.h
index ee843e9..9c92af8 100644
--- a/include/private/ui/android_natives_priv.h
+++ b/include/private/ui/android_natives_priv.h
@@ -25,7 +25,7 @@
/*****************************************************************************/
-struct android_native_buffer_t
+typedef struct android_native_buffer_t
{
#ifdef __cplusplus
android_native_buffer_t() {
@@ -48,7 +48,7 @@
buffer_handle_t handle;
void* reserved_proc[8];
-};
+} android_native_buffer_t;
/*****************************************************************************/
diff --git a/include/ui/ISurfaceComposer.h b/include/ui/ISurfaceComposer.h
index 1788265..25d954c 100644
--- a/include/ui/ISurfaceComposer.h
+++ b/include/ui/ISurfaceComposer.h
@@ -40,8 +40,6 @@
enum { // (keep in sync with Surface.java)
eHidden = 0x00000004,
- eGPU = 0x00000008,
- eHardware = 0x00000010,
eDestroyBackbuffer = 0x00000020,
eSecure = 0x00000080,
eNonPremultiplied = 0x00000100,
diff --git a/include/ui/Surface.h b/include/ui/Surface.h
index 4ff0e4a..30ab82f 100644
--- a/include/ui/Surface.h
+++ b/include/ui/Surface.h
@@ -146,16 +146,16 @@
static bool isValid(const sp<Surface>& surface) {
return (surface != 0) && surface->isValid();
}
- bool isValid() {
- return mToken>=0 && mClient!=0;
- }
+
static bool isSameSurface(
const sp<Surface>& lhs, const sp<Surface>& rhs);
- SurfaceID ID() const { return mToken; }
- uint32_t getFlags() const { return mFlags; }
+
+ bool isValid();
+ SurfaceID ID() const { return mToken; }
+ uint32_t getFlags() const { return mFlags; }
uint32_t getIdentity() const { return mIdentity; }
-
+ // the lock/unlock APIs must be used from the same thread
status_t lock(SurfaceInfo* info, bool blocking = true);
status_t lock(SurfaceInfo* info, Region* dirty, bool blocking = true);
status_t unlockAndPost();
@@ -175,14 +175,18 @@
friend class SurfaceComposerClient;
friend class SurfaceControl;
+
// camera and camcorder need access to the ISurface binder interface for preview
friend class Camera;
friend class MediaRecorder;
// mediaplayer needs access to ISurface for display
friend class MediaPlayer;
- friend class Test;
friend class IOMX;
- const sp<ISurface>& getISurface() const { return mSurface; }
+ // this is just to be able to write some unit tests
+ friend class Test;
+
+ sp<SurfaceComposerClient> getClient() const;
+ sp<ISurface> getISurface() const;
status_t getBufferLocked(int index, int usage);
@@ -210,24 +214,38 @@
status_t queueBuffer(const sp<SurfaceBuffer>& buffer);
- alloc_device_t* mAllocDevice;
+ void setUsage(uint32_t reqUsage);
+
+ // constants
sp<SurfaceComposerClient> mClient;
sp<ISurface> mSurface;
- sp<SurfaceBuffer> mBuffers[2];
- sp<SurfaceBuffer> mLockedBuffer;
SurfaceID mToken;
uint32_t mIdentity;
- uint32_t mWidth;
- uint32_t mHeight;
- uint32_t mUsage;
PixelFormat mFormat;
uint32_t mFlags;
- mutable Region mDirtyRegion;
- mutable Region mOldDirtyRegion;
- mutable uint8_t mBackbufferIndex;
- mutable Mutex mSurfaceLock;
- Rect mSwapRectangle;
BufferMapper& mBufferMapper;
+
+ // protected by mSurfaceLock
+ Rect mSwapRectangle;
+ uint32_t mUsage;
+ bool mUsageChanged;
+
+ // protected by mSurfaceLock. These are also used from lock/unlock
+ // but in that case, they must be called form the same thread.
+ sp<SurfaceBuffer> mBuffers[2];
+ mutable Region mDirtyRegion;
+ mutable uint8_t mBackbufferIndex;
+
+ // must be used from the lock/unlock thread
+ sp<SurfaceBuffer> mLockedBuffer;
+ mutable Region mOldDirtyRegion;
+
+ // query() must be called from dequeueBuffer() thread
+ uint32_t mWidth;
+ uint32_t mHeight;
+
+ // Inherently thread-safe
+ mutable Mutex mSurfaceLock;
};
}; // namespace android
diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h
index 4c58e47..3740db5 100644
--- a/include/ui/egl/android_natives.h
+++ b/include/ui/egl/android_natives.h
@@ -43,7 +43,7 @@
// ---------------------------------------------------------------------------
-struct android_native_base_t
+typedef struct android_native_base_t
{
/* a magic value defined by the actual EGL native type */
int magic;
@@ -56,7 +56,7 @@
/* reference-counting interface */
void (*incRef)(struct android_native_base_t* base);
void (*decRef)(struct android_native_base_t* base);
-};
+} android_native_base_t;
// ---------------------------------------------------------------------------
@@ -72,7 +72,7 @@
NATIVE_WINDOW_SET_USAGE = 0
};
-struct android_native_window_t
+typedef struct android_native_window_t
{
#ifdef __cplusplus
android_native_window_t()
@@ -166,7 +166,7 @@
int operation, ... );
void* reserved_proc[3];
-};
+} android_native_window_t;
/*
@@ -179,8 +179,8 @@
* reallocated.
*/
-inline int native_window_set_usage(
- struct android_native_window_t* window, int usage)
+static inline int native_window_set_usage(
+ android_native_window_t* window, int usage)
{
return window->perform(window, NATIVE_WINDOW_SET_USAGE, usage);
}
@@ -189,7 +189,7 @@
// ---------------------------------------------------------------------------
/* FIXME: this is legacy for pixmaps */
-struct egl_native_pixmap_t
+typedef struct egl_native_pixmap_t
{
int32_t version; /* must be 32 */
int32_t width;
@@ -203,7 +203,7 @@
int32_t vstride;
};
int32_t reserved;
-};
+} egl_native_pixmap_t;
/*****************************************************************************/
diff --git a/include/utils/Debug.h b/include/utils/Debug.h
index 21d04bd..d9ed32d 100644
--- a/include/utils/Debug.h
+++ b/include/utils/Debug.h
@@ -29,6 +29,8 @@
#define COMPILE_TIME_ASSERT(_exp) \
template class CompileTimeAssert< (_exp) >;
#endif
+#define COMPILE_TIME_ASSERT_FUNCTION_SCOPE(_exp) \
+ CompileTimeAssert<( _exp )>();
// ---------------------------------------------------------------------------
diff --git a/keystore/MODULE_LICENSE_APACHE2 b/keystore/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/keystore/MODULE_LICENSE_APACHE2
diff --git a/keystore/NOTICE b/keystore/NOTICE
new file mode 100644
index 0000000..64aaa8d
--- /dev/null
+++ b/keystore/NOTICE
@@ -0,0 +1,190 @@
+
+ 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.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 785a3c5..e397bce 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -562,54 +562,27 @@
status_t Parcel::writeInt32(int32_t val)
{
- if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
- *reinterpret_cast<int32_t*>(mData+mDataPos) = val;
- return finishWrite(sizeof(val));
- }
-
- status_t err = growData(sizeof(val));
- if (err == NO_ERROR) goto restart_write;
- return err;
+ return writeAligned(val);
}
status_t Parcel::writeInt64(int64_t val)
{
- if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
- *reinterpret_cast<int64_t*>(mData+mDataPos) = val;
- return finishWrite(sizeof(val));
- }
-
- status_t err = growData(sizeof(val));
- if (err == NO_ERROR) goto restart_write;
- return err;
+ return writeAligned(val);
}
status_t Parcel::writeFloat(float val)
{
- if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
- *reinterpret_cast<float*>(mData+mDataPos) = val;
- return finishWrite(sizeof(val));
- }
-
- status_t err = growData(sizeof(val));
- if (err == NO_ERROR) goto restart_write;
- return err;
+ return writeAligned(val);
}
status_t Parcel::writeDouble(double val)
{
- if ((mDataPos+sizeof(val)) <= mDataCapacity) {
-restart_write:
- *reinterpret_cast<double*>(mData+mDataPos) = val;
- return finishWrite(sizeof(val));
- }
+ return writeAligned(val);
+}
- status_t err = growData(sizeof(val));
- if (err == NO_ERROR) goto restart_write;
- return err;
+status_t Parcel::writeIntPtr(intptr_t val)
+{
+ return writeAligned(val);
}
status_t Parcel::writeCString(const char* str)
@@ -768,103 +741,98 @@
return NULL;
}
-status_t Parcel::readInt32(int32_t *pArg) const
-{
- if ((mDataPos+sizeof(int32_t)) <= mDataSize) {
+template<class T>
+status_t Parcel::readAligned(T *pArg) const {
+ COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
+
+ if ((mDataPos+sizeof(T)) <= mDataSize) {
const void* data = mData+mDataPos;
- mDataPos += sizeof(int32_t);
- *pArg = *reinterpret_cast<const int32_t*>(data);
+ mDataPos += sizeof(T);
+ *pArg = *reinterpret_cast<const T*>(data);
return NO_ERROR;
} else {
return NOT_ENOUGH_DATA;
}
}
+template<class T>
+T Parcel::readAligned() const {
+ T result;
+ if (readAligned(&result) != NO_ERROR) {
+ result = 0;
+ }
+
+ return result;
+}
+
+template<class T>
+status_t Parcel::writeAligned(T val) {
+ COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
+
+ if ((mDataPos+sizeof(val)) <= mDataCapacity) {
+restart_write:
+ *reinterpret_cast<T*>(mData+mDataPos) = val;
+ return finishWrite(sizeof(val));
+ }
+
+ status_t err = growData(sizeof(val));
+ if (err == NO_ERROR) goto restart_write;
+ return err;
+}
+
+status_t Parcel::readInt32(int32_t *pArg) const
+{
+ return readAligned(pArg);
+}
+
int32_t Parcel::readInt32() const
{
- if ((mDataPos+sizeof(int32_t)) <= mDataSize) {
- const void* data = mData+mDataPos;
- mDataPos += sizeof(int32_t);
- LOGV("readInt32 Setting data pos of %p to %d\n", this, mDataPos);
- return *reinterpret_cast<const int32_t*>(data);
- }
- return 0;
+ return readAligned<int32_t>();
}
status_t Parcel::readInt64(int64_t *pArg) const
{
- if ((mDataPos+sizeof(int64_t)) <= mDataSize) {
- const void* data = mData+mDataPos;
- mDataPos += sizeof(int64_t);
- *pArg = *reinterpret_cast<const int64_t*>(data);
- LOGV("readInt64 Setting data pos of %p to %d\n", this, mDataPos);
- return NO_ERROR;
- } else {
- return NOT_ENOUGH_DATA;
- }
+ return readAligned(pArg);
}
int64_t Parcel::readInt64() const
{
- if ((mDataPos+sizeof(int64_t)) <= mDataSize) {
- const void* data = mData+mDataPos;
- mDataPos += sizeof(int64_t);
- LOGV("readInt64 Setting data pos of %p to %d\n", this, mDataPos);
- return *reinterpret_cast<const int64_t*>(data);
- }
- return 0;
+ return readAligned<int64_t>();
}
status_t Parcel::readFloat(float *pArg) const
{
- if ((mDataPos+sizeof(float)) <= mDataSize) {
- const void* data = mData+mDataPos;
- mDataPos += sizeof(float);
- LOGV("readFloat Setting data pos of %p to %d\n", this, mDataPos);
- *pArg = *reinterpret_cast<const float*>(data);
- return NO_ERROR;
- } else {
- return NOT_ENOUGH_DATA;
- }
+ return readAligned(pArg);
}
float Parcel::readFloat() const
{
- if ((mDataPos+sizeof(float)) <= mDataSize) {
- const void* data = mData+mDataPos;
- mDataPos += sizeof(float);
- LOGV("readFloat Setting data pos of %p to %d\n", this, mDataPos);
- return *reinterpret_cast<const float*>(data);
- }
- return 0;
+ return readAligned<float>();
}
status_t Parcel::readDouble(double *pArg) const
{
- if ((mDataPos+sizeof(double)) <= mDataSize) {
- const void* data = mData+mDataPos;
- mDataPos += sizeof(double);
- LOGV("readDouble Setting data pos of %p to %d\n", this, mDataPos);
- *pArg = *reinterpret_cast<const double*>(data);
- return NO_ERROR;
- } else {
- return NOT_ENOUGH_DATA;
- }
+ return readAligned(pArg);
}
double Parcel::readDouble() const
{
- if ((mDataPos+sizeof(double)) <= mDataSize) {
- const void* data = mData+mDataPos;
- mDataPos += sizeof(double);
- LOGV("readDouble Setting data pos of %p to %d\n", this, mDataPos);
- return *reinterpret_cast<const double*>(data);
- }
- return 0;
+ return readAligned<double>();
+}
+
+status_t Parcel::readIntPtr(intptr_t *pArg) const
+{
+ return readAligned(pArg);
+}
+
+
+intptr_t Parcel::readIntPtr() const
+{
+ return readAligned<intptr_t>();
}
diff --git a/libs/rs/java/Fountain/res/raw/fountain.c b/libs/rs/java/Fountain/res/raw/fountain.c
index 6e6afcd..e7804a5 100644
--- a/libs/rs/java/Fountain/res/raw/fountain.c
+++ b/libs/rs/java/Fountain/res/raw/fountain.c
@@ -1,86 +1,52 @@
// Fountain test script
-
#pragma version(1)
#pragma stateVertex(default)
-#pragma stateFragment(PgmFragParts)
-#pragma stateFragmentStore(PFSBlend)
-
+#pragma stateFragment(default)
+#pragma stateFragmentStore(default)
int main(int launchID) {
int ct;
- int count = loadI32(0, OFFSETOF_SomeData_count);
- int touch = loadI32(0, OFFSETOF_SomeData_touch);
- int rate = 4;
- int maxLife = (count / rate) - 1;
+ int count = Control_count - 1;
+ int rate = Control_rate;
+ float *dataF = loadArrayF(1, 0);
+ float height = getHeight();
- if (touch) {
- int x = loadI32(0, OFFSETOF_SomeData_x);
- int y = loadI32(0, OFFSETOF_SomeData_y);
- int newPart = loadI32(2, 0);
- for (ct=0; ct<rate; ct++) {
- int idx = newPart * 5 + 1;
- storeF(2, idx, randf(1.f) - 0.5f);
- storeF(2, idx + 1, randf(1.f) - 0.5f);
- storeI32(2, idx + 2, maxLife);
- storeF(2, idx + 3, x);
- storeF(2, idx + 4, y);
+ if (rate) {
+ debugI32("rate", rate);
+ int *dataI = loadArrayI32(1, 0);
+ float rMax = ((float)rate) * 0.005f;
+ int x = Control_x;
+ int y = Control_y;
+ int newPart = loadI32(1, count * 5);
+ int c = colorFloatRGBAtoUNorm8(Control_r, Control_g, Control_b, 0.99f);
+
+ while (rate--) {
+ int idx = newPart * 5;
+ vec2Rand(dataF + idx, rMax);
+ dataF[idx + 2] = x;
+ dataF[idx + 3] = y;
+ dataI[idx + 4] = c;
newPart++;
if (newPart >= count) {
newPart = 0;
}
}
- storeI32(2, 0, newPart);
+ storeI32(1, count * 5, newPart);
}
- int drawCount = 0;
- float height = getHeight();
for (ct=0; ct < count; ct++) {
- int srcIdx = ct * 5 + 1;
-
- int life = loadI32(2, srcIdx + 2);
-
- if (life) {
- float posx = loadF(2, srcIdx + 3);
- float posy = loadF(2, srcIdx + 4);
- float dx = loadF(2, srcIdx);
- float dy = loadF(2, srcIdx + 1);
- if (posy < height) {
- int dstIdx = drawCount * 9;
- int c = 0xcfcfcfcf;
-
- storeI32(1, dstIdx, c);
- storeF(1, dstIdx + 1, posx);
- storeF(1, dstIdx + 2, posy);
-
- storeI32(1, dstIdx + 3, c);
- storeF(1, dstIdx + 4, posx + 1.f);
- storeF(1, dstIdx + 5, posy + dy);
-
- storeI32(1, dstIdx + 6, c);
- storeF(1, dstIdx + 7, posx - 1.f);
- storeF(1, dstIdx + 8, posy + dy);
- drawCount ++;
- } else {
- if (dy > 0) {
- dy *= -0.5f;
- }
- }
-
- posx = posx + dx;
- posy = posy + dy;
- dy = dy + 0.05f;
- life --;
-
- //storeI32(2, srcIdx, dx);
- storeF(2, srcIdx + 1, dy);
- storeI32(2, srcIdx + 2, life);
- storeF(2, srcIdx + 3, posx);
- storeF(2, srcIdx + 4, posy);
+ float dy = dataF[1] + 0.15f;
+ float posy = dataF[3] + dy;
+ if ((posy > height) && (dy > 0)) {
+ dy *= -0.3f;
}
+ dataF[1] = dy;
+ dataF[2] += dataF[0];
+ dataF[3] = posy;
+ dataF += 5;
}
- //drawTriangleArray(NAMED_PartBuffer, drawCount);
uploadToBufferObject(NAMED_PartBuffer);
- drawSimpleMeshRange(NAMED_PartMesh, 0, drawCount * 3);
+ drawSimpleMeshRange(NAMED_PartMesh, 0, count);
return 1;
}
diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
index da4eeb4..da9eda8 100644
--- a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
+++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
@@ -16,26 +16,22 @@
package com.android.fountain;
-import java.io.Writer;
-
-import android.content.Context;
import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
import android.renderscript.*;
import android.util.Log;
public class FountainRS {
- public static final int PART_COUNT = 4000;
+ public static final int PART_COUNT = 20000;
static class SomeData {
public int x;
public int y;
- public int touch;
public int rate;
public int count;
+ public float r;
+ public float g;
+ public float b;
}
public FountainRS() {
@@ -47,8 +43,18 @@
initRS();
}
- public void newTouchPosition(int x, int y) {
- mSD.touch = 1;
+ public void newTouchPosition(int x, int y, int rate) {
+ if (mSD.rate == 0) {
+ mSD.r = ((x & 0x1) != 0) ? 0.f : 1.f;
+ mSD.g = ((x & 0x2) != 0) ? 0.f : 1.f;
+ mSD.b = ((x & 0x4) != 0) ? 0.f : 1.f;
+ if ((mSD.r + mSD.g + mSD.b) < 0.9f) {
+ mSD.r = 0.8f;
+ mSD.g = 0.5f;
+ mSD.b = 1.f;
+ }
+ }
+ mSD.rate = rate;
mSD.x = x;
mSD.y = y;
mIntAlloc.data(mSD);
@@ -62,50 +68,29 @@
private RenderScript mRS;
private Allocation mIntAlloc;
private Allocation mPartAlloc;
- private Allocation mVertAlloc;
private Script mScript;
- private ProgramStore mPFS;
- private ProgramFragment mPF;
private SimpleMesh mSM;
-
- private Bitmap mBackground;
-
- SomeData mSD = new SomeData();
+ private SomeData mSD;
private Type mSDType;
private void initRS() {
mSD = new SomeData();
mSDType = Type.createFromClass(mRS, SomeData.class, 1, "SomeData");
mIntAlloc = Allocation.createTyped(mRS, mSDType);
- mVertAlloc = Allocation.createSized(mRS, Element.USER_I32, PART_COUNT * 5 + 1);
-
- ProgramStore.Builder bs = new ProgramStore.Builder(mRS, null, null);
- bs.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA, ProgramStore.BlendDstFunc.ONE);
- bs.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
- bs.setDepthMask(false);
- bs.setDitherEnable(false);
- mPFS = bs.create();
- mPFS.setName("PFSBlend");
-
- ProgramFragment.Builder bf = new ProgramFragment.Builder(mRS, null, null);
- mPF = bf.create();
- mPF.setName("PgmFragParts");
-
mSD.count = PART_COUNT;
mIntAlloc.data(mSD);
Element.Builder eb = new Element.Builder(mRS);
- eb.add(Element.DataType.UNSIGNED, Element.DataKind.RED, true, 8);
- eb.add(Element.DataType.UNSIGNED, Element.DataKind.GREEN, true, 8);
- eb.add(Element.DataType.UNSIGNED, Element.DataKind.BLUE, true, 8);
- eb.add(Element.DataType.UNSIGNED, Element.DataKind.ALPHA, true, 8);
- eb.add(Element.DataType.FLOAT, Element.DataKind.X, false, 32);
- eb.add(Element.DataType.FLOAT, Element.DataKind.Y, false, 32);
+ eb.addFloat(Element.DataKind.USER); //dx
+ eb.addFloat(Element.DataKind.USER); //dy
+ eb.addFloatXY();
+ eb.addUNorm8RGBA();
Element primElement = eb.create();
+
SimpleMesh.Builder smb = new SimpleMesh.Builder(mRS);
- int vtxSlot = smb.addVertexType(primElement, PART_COUNT * 3);
- smb.setPrimitive(Primitive.TRIANGLE);
+ int vtxSlot = smb.addVertexType(primElement, PART_COUNT);
+ smb.setPrimitive(Primitive.POINT);
mSM = smb.create();
mSM.setName("PartMesh");
@@ -118,13 +103,12 @@
ScriptC.Builder sb = new ScriptC.Builder(mRS);
sb.setScript(mRes, R.raw.fountain);
sb.setRoot(true);
- sb.setType(mSDType, 0);
+ sb.setType(mSDType, "Control", 0);
mScript = sb.create();
mScript.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
mScript.bindAllocation(mIntAlloc, 0);
mScript.bindAllocation(mPartAlloc, 1);
- mScript.bindAllocation(mVertAlloc, 2);
mRS.contextBindRootScript(mScript);
}
diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java
index be8b24e..2768e2c 100644
--- a/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java
+++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java
@@ -61,13 +61,18 @@
@Override
public boolean onTouchEvent(MotionEvent ev)
{
- boolean ret = true;
int act = ev.getAction();
if (act == ev.ACTION_UP) {
- ret = false;
+ mRender.newTouchPosition(0, 0, 0);
+ return false;
}
- mRender.newTouchPosition((int)ev.getX(), (int)ev.getY());
- return ret;
+ float rate = (ev.getPressure() * 50.f);
+ rate *= rate;
+ if(rate > 2000.f) {
+ rate = 2000.f;
+ }
+ mRender.newTouchPosition((int)ev.getX(), (int)ev.getY(), (int)rate);
+ return true;
}
}
diff --git a/libs/rs/java/Galaxy/Android.mk b/libs/rs/java/Galaxy/Android.mk
new file mode 100644
index 0000000..0884e18
--- /dev/null
+++ b/libs/rs/java/Galaxy/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
+
+LOCAL_PACKAGE_NAME := GalaxyRS
+
+include $(BUILD_PACKAGE)
diff --git a/libs/rs/java/Galaxy/AndroidManifest.xml b/libs/rs/java/Galaxy/AndroidManifest.xml
new file mode 100644
index 0000000..6da1e0f
--- /dev/null
+++ b/libs/rs/java/Galaxy/AndroidManifest.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.galaxy.rs">
+
+ <application android:label="GalaxyRS">
+
+ <activity
+ android:screenOrientation="portrait"
+ android:name="Galaxy"
+ android:theme="@android:style/Theme.NoTitleBar">
+
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+
+ </activity>
+
+ </application>
+
+</manifest>
diff --git a/libs/rs/java/Galaxy/res/drawable-hdpi/flares.png b/libs/rs/java/Galaxy/res/drawable-hdpi/flares.png
new file mode 100644
index 0000000..e1c7010
--- /dev/null
+++ b/libs/rs/java/Galaxy/res/drawable-hdpi/flares.png
Binary files differ
diff --git a/libs/rs/java/Galaxy/res/drawable-hdpi/light1.png b/libs/rs/java/Galaxy/res/drawable-hdpi/light1.png
new file mode 100644
index 0000000..4ffb1ee
--- /dev/null
+++ b/libs/rs/java/Galaxy/res/drawable-hdpi/light1.png
Binary files differ
diff --git a/libs/rs/java/Galaxy/res/drawable-hdpi/space.jpg b/libs/rs/java/Galaxy/res/drawable-hdpi/space.jpg
new file mode 100644
index 0000000..b61f6a3
--- /dev/null
+++ b/libs/rs/java/Galaxy/res/drawable-hdpi/space.jpg
Binary files differ
diff --git a/libs/rs/java/Galaxy/res/raw/galaxy.c b/libs/rs/java/Galaxy/res/raw/galaxy.c
new file mode 100644
index 0000000..8575712
--- /dev/null
+++ b/libs/rs/java/Galaxy/res/raw/galaxy.c
@@ -0,0 +1,132 @@
+// 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.
+
+#pragma version(1)
+#pragma stateVertex(PVBackground)
+#pragma stateFragment(PFBackground)
+#pragma stateFragmentStore(PFSBackground)
+
+#define RSID_PARTICLES 1
+
+#define PARTICLE_STRUCT_FIELDS_COUNT 4
+#define PARTICLE_STRUCT_ANGLE 0
+#define PARTICLE_STRUCT_DISTANCE 1
+#define PARTICLE_STRUCT_SPEED 2
+#define PARTICLE_STRUCT_RADIUS 3
+
+#define RSID_PARTICLES_BUFFER 2
+#define PARTICLE_BUFFER_COMPONENTS_COUNT 5
+
+#define PARTICLES_TEXTURES_COUNT 2
+
+#define ELLIPSE_RATIO 0.86f
+#define ELLIPSE_TWIST 0.02333333333f
+
+void drawSpace(int width, int height) {
+ bindTexture(NAMED_PFBackground, 0, NAMED_TSpace);
+ drawQuadTexCoords(
+ 0.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f,
+ width, 0.0f, 0.0f,
+ 2.0f, 1.0f,
+ width, height, 0.0f,
+ 2.0f, 0.0f,
+ 0.0f, height, 0.0f,
+ 0.0f, 0.0f);
+}
+
+void drawLights(int width, int height) {
+ float x = (width - 512.0f) / 2.0f;
+ float y = (height - 512.0f) / 2.0f;
+
+ bindProgramFragment(NAMED_PFBackground);
+ bindTexture(NAMED_PFBackground, 0, NAMED_TLight1);
+ drawQuad(x + 512.0f, y , 0.0f,
+ x , y , 0.0f,
+ x , y + 512.0f, 0.0f,
+ x + 512.0f, y + 512.0f, 0.0f);
+}
+
+void drawParticle(float *particle, int index, float *particleBuffer, int bufferIndex,
+ float w, float h) {
+
+ float distance = particle[index + PARTICLE_STRUCT_DISTANCE];
+ float angle = particle[index + PARTICLE_STRUCT_ANGLE];
+ float speed = particle[index + PARTICLE_STRUCT_SPEED];
+ float r = particle[index + PARTICLE_STRUCT_RADIUS];
+
+ float a = angle + speed;
+ float x = distance * sinf(a);
+ float y = distance * cosf(a) * ELLIPSE_RATIO;
+ float z = distance * ELLIPSE_TWIST;
+ float s = cosf(z);
+ float t = sinf(z);
+
+ float sX = t * x + s * y + w;
+ float sY = s * x - t * y + h;
+
+ // lower left vertex of the particle's triangle
+ particleBuffer[bufferIndex + 1] = sX - r; // X
+ particleBuffer[bufferIndex + 2] = sY + r; // Y
+
+ // lower right vertex of the particle's triangle
+ bufferIndex += PARTICLE_BUFFER_COMPONENTS_COUNT;
+ particleBuffer[bufferIndex + 1] = sX + r; // X
+ particleBuffer[bufferIndex + 2] = sY + r; // Y
+
+ // upper middle vertex of the particle's triangle
+ bufferIndex += PARTICLE_BUFFER_COMPONENTS_COUNT;
+ particleBuffer[bufferIndex + 1] = sX; // X
+ particleBuffer[bufferIndex + 2] = sY - r; // Y
+
+ particle[index + PARTICLE_STRUCT_ANGLE] = a;
+}
+
+void drawParticles(int width, int height) {
+ bindProgramFragment(NAMED_PFLighting);
+ bindProgramFragmentStore(NAMED_PFSLights);
+ bindTexture(NAMED_PFLighting, 0, NAMED_TFlares);
+
+ int radius = State_galaxyRadius;
+ int particlesCount = State_particlesCount;
+ int count = particlesCount * PARTICLE_STRUCT_FIELDS_COUNT;
+
+ float *particle = loadArrayF(RSID_PARTICLES, 0);
+ float *particleBuffer = loadArrayF(RSID_PARTICLES_BUFFER, 0);
+
+ float w = width * 0.5f;
+ float h = height * 0.5f;
+
+ int i = 0;
+ int bufferIndex = 0;
+ for ( ; i < count; i += PARTICLE_STRUCT_FIELDS_COUNT) {
+ drawParticle(particle, i, particleBuffer, bufferIndex, w, h);
+ // each particle is a triangle (3 vertices) of 6 properties (ABGR, X, Y, Z, S, T)
+ bufferIndex += 3 * PARTICLE_BUFFER_COMPONENTS_COUNT;
+ }
+
+ uploadToBufferObject(NAMED_ParticlesBuffer);
+ drawSimpleMeshRange(NAMED_ParticlesMesh, 0, particlesCount * 3);
+}
+
+int main(int index) {
+ int width = State_width;
+ int height = State_height;
+
+ drawSpace(width, height);
+ drawParticles(width, height);
+ drawLights(width, height);
+
+ return 1;
+}
diff --git a/libs/rs/java/Galaxy/src/com/android/galaxy/rs/Galaxy.java b/libs/rs/java/Galaxy/src/com/android/galaxy/rs/Galaxy.java
new file mode 100644
index 0000000..27d333c
--- /dev/null
+++ b/libs/rs/java/Galaxy/src/com/android/galaxy/rs/Galaxy.java
@@ -0,0 +1,46 @@
+/*
+ * 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.galaxy.rs;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class Galaxy extends Activity {
+ private GalaxyView mView;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ mView = new GalaxyView(this);
+ setContentView(mView);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mView.onPause();
+
+ Runtime.getRuntime().exit(0);
+ }
+}
\ No newline at end of file
diff --git a/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyRS.java b/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyRS.java
new file mode 100644
index 0000000..1b9e349
--- /dev/null
+++ b/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyRS.java
@@ -0,0 +1,362 @@
+/*
+ * 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.galaxy.rs;
+
+import android.content.res.Resources;
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptC;
+import android.renderscript.ProgramFragment;
+import android.renderscript.ProgramStore;
+import android.renderscript.ProgramVertex;
+import android.renderscript.Allocation;
+import android.renderscript.Sampler;
+import android.renderscript.Element;
+import android.renderscript.SimpleMesh;
+import android.renderscript.Primitive;
+import android.renderscript.Type;
+import static android.renderscript.Sampler.Value.LINEAR;
+import static android.renderscript.Sampler.Value.NEAREST;
+import static android.renderscript.Sampler.Value.WRAP;
+import static android.renderscript.ProgramStore.DepthFunc.*;
+import static android.renderscript.ProgramStore.BlendDstFunc;
+import static android.renderscript.ProgramStore.BlendSrcFunc;
+import static android.renderscript.ProgramFragment.EnvMode.*;
+import static android.renderscript.Element.*;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import static android.util.MathUtils.*;
+
+import java.util.TimeZone;
+
+class GalaxyRS {
+ private static final int GALAXY_RADIUS = 300;
+ private static final int PARTICLES_COUNT = 12000;
+
+ private static final int RSID_STATE = 0;
+
+ private static final int TEXTURES_COUNT = 3;
+ private static final int PARTICLES_TEXTURES_COUNT = 2;
+ private static final int RSID_TEXTURE_SPACE = 0;
+ private static final int RSID_TEXTURE_LIGHT1 = 1;
+ private static final int RSID_TEXTURE_FLARES = 2;
+
+ private static final int RSID_PARTICLES = 1;
+ private static final int PARTICLE_STRUCT_FIELDS_COUNT = 4;
+ private static final int PARTICLE_STRUCT_ANGLE = 0;
+ private static final int PARTICLE_STRUCT_DISTANCE = 1;
+ private static final int PARTICLE_STRUCT_SPEED = 2;
+ private static final int PARTICLE_STRUCT_RADIUS = 3;
+
+ private static final int RSID_PARTICLES_BUFFER = 2;
+
+ private Resources mResources;
+ private RenderScript mRS;
+
+ private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
+
+ private final int mWidth;
+ private final int mHeight;
+
+ private ScriptC mScript;
+ private Sampler mSampler;
+ private Sampler mLightSampler;
+ private ProgramFragment mPfBackground;
+ private ProgramFragment mPfLighting;
+ private ProgramStore mPfsBackground;
+ private ProgramStore mPfsLights;
+ private ProgramVertex mPvBackground;
+ private ProgramVertex.MatrixAllocation mPvOrthoAlloc;
+
+ private Allocation[] mTextures;
+
+ private Type mStateType;
+ private Allocation mState;
+ private Allocation mParticles;
+ private Allocation mParticlesBuffer;
+ private SimpleMesh mParticlesMesh;
+
+ private final float[] mFloatData5 = new float[5];
+
+ public GalaxyRS(int width, int height) {
+ mWidth = width;
+ mHeight = height;
+ mOptionsARGB.inScaled = false;
+ mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ }
+
+ public void init(RenderScript rs, Resources res) {
+ mRS = rs;
+ mResources = res;
+ initRS();
+ }
+
+ public void destroy() {
+ mScript.destroy();
+ mSampler.destroy();
+ mLightSampler.destroy();
+ mPfBackground.destroy();
+ mPfsBackground.destroy();
+ mPvBackground.destroy();
+ mPvOrthoAlloc.mAlloc.destroy();
+ for (Allocation a : mTextures) {
+ a.destroy();
+ }
+ mState.destroy();
+ mPfLighting.destroy();
+ mParticles.destroy();
+ mPfsLights.destroy();
+ mParticlesMesh.destroy();
+ mParticlesBuffer.destroy();
+ mStateType.destroy();
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ destroy();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ private void initRS() {
+ createProgramVertex();
+ createProgramFragmentStore();
+ createProgramFragment();
+ createScriptStructures();
+ loadTextures();
+
+ ScriptC.Builder sb = new ScriptC.Builder(mRS);
+ sb.setType(mStateType, "State", 0);
+ sb.setScript(mResources, R.raw.galaxy);
+ sb.setRoot(true);
+
+ mScript = sb.create();
+ mScript.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ mScript.setTimeZone(TimeZone.getDefault().getID());
+
+ mScript.bindAllocation(mState, RSID_STATE);
+ mScript.bindAllocation(mParticles, RSID_PARTICLES);
+ mScript.bindAllocation(mParticlesBuffer, RSID_PARTICLES_BUFFER);
+
+ mRS.contextBindRootScript(mScript);
+ }
+
+ private void createScriptStructures() {
+ createState();
+ createParticlesMesh();
+ createParticles();
+ }
+
+ private void createParticlesMesh() {
+ final Element.Builder elementBuilder = new Element.Builder(mRS);
+ elementBuilder.addUNorm8RGBA();
+ elementBuilder.addFloatXY();
+ elementBuilder.addFloatST();
+ final Element vertexElement = elementBuilder.create();
+
+ final SimpleMesh.Builder meshBuilder = new SimpleMesh.Builder(mRS);
+ final int vertexSlot = meshBuilder.addVertexType(vertexElement, PARTICLES_COUNT * 3);
+ meshBuilder.setPrimitive(Primitive.TRIANGLE);
+ mParticlesMesh = meshBuilder.create();
+ mParticlesMesh.setName("ParticlesMesh");
+
+ mParticlesBuffer = mParticlesMesh.createVertexAllocation(vertexSlot);
+ mParticlesBuffer.setName("ParticlesBuffer");
+ mParticlesMesh.bindVertexAllocation(mParticlesBuffer, 0);
+ }
+
+ static class GalaxyState {
+ public int frameCount;
+ public int width;
+ public int height;
+ public int particlesCount;
+ public int galaxyRadius;
+ }
+
+ private void createState() {
+ GalaxyState state = new GalaxyState();
+ state.width = mWidth;
+ state.height = mHeight;
+ state.particlesCount = PARTICLES_COUNT;
+ state.galaxyRadius = GALAXY_RADIUS;
+
+ mStateType = Type.createFromClass(mRS, GalaxyState.class, 1, "GalaxyState");
+ mState = Allocation.createTyped(mRS, mStateType);
+ mState.data(state);
+ }
+
+ private void createParticles() {
+ final float[] particles = new float[PARTICLES_COUNT * PARTICLE_STRUCT_FIELDS_COUNT];
+
+ int bufferIndex = 0;
+
+ for (int i = 0; i < particles.length; i += PARTICLE_STRUCT_FIELDS_COUNT) {
+ createParticle(particles, i, bufferIndex);
+ bufferIndex += 3;
+ }
+
+ mParticles = Allocation.createSized(mRS, USER_FLOAT, particles.length);
+ mParticles.data(particles);
+ }
+
+ @SuppressWarnings({"PointlessArithmeticExpression"})
+ private void createParticle(float[] particles, int index, int bufferIndex) {
+ float d = abs(randomGauss()) * GALAXY_RADIUS / 2.0f;
+
+ particles[index + PARTICLE_STRUCT_ANGLE] = random(0.0f, (float) (Math.PI * 2.0));
+ particles[index + PARTICLE_STRUCT_DISTANCE] = d;
+ particles[index + PARTICLE_STRUCT_SPEED] = random(0.0015f, 0.0025f) *
+ (0.5f + (0.5f * (float) GALAXY_RADIUS / d));
+ particles[index + PARTICLE_STRUCT_RADIUS] = random(1.0f, 2.1f);
+
+ int red, green, blue;
+ if (d < GALAXY_RADIUS / 3.0f) {
+ red = (int) (220 + (d / (float) GALAXY_RADIUS) * 35);
+ green = 220;
+ blue = 220;
+ } else {
+ red = 180;
+ green = 180;
+ blue = (int) constrain(140 + (d / (float) GALAXY_RADIUS) * 115, 140, 255);
+ }
+
+ final int color = 0xFF000000 | red | green << 8 | blue << 16;
+ final int sprite = random(PARTICLES_TEXTURES_COUNT);
+ final float u1 = sprite / (float) PARTICLES_TEXTURES_COUNT;
+ final float u2 = (sprite + 1) / (float) PARTICLES_TEXTURES_COUNT;
+
+ final float[] floatData = mFloatData5;
+ final Allocation buffer = mParticlesBuffer;
+
+ floatData[0] = Float.intBitsToFloat(color);
+ floatData[3] = u1;
+ floatData[4] = 1.0f;
+ buffer.subData1D(bufferIndex, 1, floatData);
+
+ bufferIndex++;
+ floatData[3] = u2;
+ floatData[4] = 1.0f;
+ buffer.subData1D(bufferIndex, 1, floatData);
+
+ bufferIndex++;
+ floatData[3] = u1 + (u2 - u1) / 2.0f;
+ floatData[4] = 0.0f;
+ buffer.subData1D(bufferIndex, 1, floatData);
+ }
+
+ private static float randomGauss() {
+ float x1;
+ float x2;
+ float w;
+
+ do {
+ x1 = 2.0f * random(0.0f, 1.0f) - 1.0f;
+ x2 = 2.0f * random(0.0f, 1.0f) - 1.0f;
+ w = x1 * x1 + x2 * x2;
+ } while (w >= 1.0f);
+
+ w = (float) Math.sqrt(-2.0 * log(w) / w);
+ return x1 * w;
+ }
+
+ private void loadTextures() {
+ mTextures = new Allocation[TEXTURES_COUNT];
+
+ final Allocation[] textures = mTextures;
+ textures[RSID_TEXTURE_SPACE] = loadTexture(R.drawable.space, "TSpace");
+ textures[RSID_TEXTURE_LIGHT1] = loadTextureARGB(R.drawable.light1, "TLight1");
+ textures[RSID_TEXTURE_FLARES] = loadTextureARGB(R.drawable.flares, "TFlares");
+
+ final int count = textures.length;
+ for (int i = 0; i < count; i++) {
+ final Allocation texture = textures[i];
+ texture.uploadToTexture(0);
+ }
+ }
+
+ private Allocation loadTexture(int id, String name) {
+ final Allocation allocation = Allocation.createFromBitmapResource(mRS, mResources,
+ id, RGB_565, false);
+ allocation.setName(name);
+ return allocation;
+ }
+
+ private Allocation loadTextureARGB(int id, String name) {
+ Bitmap b = BitmapFactory.decodeResource(mResources, id, mOptionsARGB);
+ final Allocation allocation = Allocation.createFromBitmap(mRS, b, RGBA_8888, false);
+ allocation.setName(name);
+ return allocation;
+ }
+
+ private void createProgramFragment() {
+ Sampler.Builder sampleBuilder = new Sampler.Builder(mRS);
+ sampleBuilder.setMin(LINEAR);
+ sampleBuilder.setMag(LINEAR);
+ sampleBuilder.setWrapS(WRAP);
+ sampleBuilder.setWrapT(WRAP);
+ mSampler = sampleBuilder.create();
+
+ ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS, null, null);
+ builder.setTexEnable(true, 0);
+ builder.setTexEnvMode(REPLACE, 0);
+ mPfBackground = builder.create();
+ mPfBackground.setName("PFBackground");
+ mPfBackground.bindSampler(mSampler, 0);
+
+ sampleBuilder = new Sampler.Builder(mRS);
+ sampleBuilder.setMin(NEAREST);
+ sampleBuilder.setMag(NEAREST);
+ sampleBuilder.setWrapS(WRAP);
+ sampleBuilder.setWrapT(WRAP);
+ mLightSampler = sampleBuilder.create();
+
+ builder = new ProgramFragment.Builder(mRS, null, null);
+ builder.setTexEnable(true, 0);
+ builder.setTexEnvMode(MODULATE, 0);
+ mPfLighting = builder.create();
+ mPfLighting.setName("PFLighting");
+ mPfLighting.bindSampler(mLightSampler, 0);
+ }
+
+ private void createProgramFragmentStore() {
+ ProgramStore.Builder builder = new ProgramStore.Builder(mRS, null, null);
+ builder.setDepthFunc(ALWAYS);
+ builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
+ builder.setDitherEnable(false);
+ mPfsBackground = builder.create();
+ mPfsBackground.setName("PFSBackground");
+
+ builder = new ProgramStore.Builder(mRS, null, null);
+ builder.setDepthFunc(ALWAYS);
+ builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
+ builder.setDitherEnable(false);
+ mPfsLights = builder.create();
+ mPfsLights.setName("PFSLights");
+ }
+
+ private void createProgramVertex() {
+ mPvOrthoAlloc = new ProgramVertex.MatrixAllocation(mRS);
+ //mPvOrthoAlloc.setupProjectionNormalized(mWidth, mHeight);
+ mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
+
+ ProgramVertex.Builder builder = new ProgramVertex.Builder(mRS, null, null);
+ mPvBackground = builder.create();
+ mPvBackground.bindAllocation(mPvOrthoAlloc);
+ mPvBackground.setName("PVBackground");
+ }
+}
diff --git a/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyView.java b/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyView.java
new file mode 100644
index 0000000..341293b
--- /dev/null
+++ b/libs/rs/java/Galaxy/src/com/android/galaxy/rs/GalaxyView.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.galaxy.rs;
+
+import android.content.Context;
+import android.view.SurfaceHolder;
+import android.renderscript.RenderScript;
+import android.renderscript.RSSurfaceView;
+
+class GalaxyView extends RSSurfaceView {
+ private GalaxyRS mRender;
+
+ public GalaxyView(Context context) {
+ super(context);
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+ }
+
+ public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+ super.surfaceChanged(holder, format, w, h);
+
+ RenderScript RS = createRenderScript();
+ mRender = new GalaxyRS(w, h);
+ mRender.init(RS, getResources());
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ if (mRender != null) mRender.destroy();
+ }
+}
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 105142b..0df237f 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -315,6 +315,7 @@
ScriptSetType {
param RsType type
param uint32_t slot
+ param bool isWritable
param const char * name
}
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 2860452..52389ea 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -84,11 +84,6 @@
bool Context::runRootScript()
{
-#if RS_LOG_TIMES
- struct timespec beginTime;
- clock_gettime(CLOCK_MONOTONIC, &beginTime);
-#endif
-
rsAssert(mRootScript->mEnviroment.mIsRoot);
//glColor4f(1,1,1,1);
@@ -116,9 +111,10 @@
struct timespec endTime;
clock_gettime(CLOCK_MONOTONIC, &endTime);
- int t1 = ((unsigned long)startTime.tv_nsec - (unsigned long)beginTime.tv_nsec) / 1000 / 1000;
- int t2 = ((unsigned long)endTime.tv_nsec - (unsigned long)startTime.tv_nsec) / 1000 / 1000;
- LOGE("times %i, %i", t1, t2);
+ uint64_t t1 = endTime.tv_nsec + ((uint64_t)endTime.tv_sec * 1000 * 1000 * 1000);
+ uint64_t t2 = startTime.tv_nsec + ((uint64_t)startTime.tv_sec * 1000 * 1000 * 1000);
+ int t3 = (int)((t1 - t2) / 1000 / 1000);
+ LOGE("times %i", t3);
#endif
return ret;
@@ -143,7 +139,6 @@
{
Context *rsc = static_cast<Context *>(vrsc);
- gIO = new ThreadIO();
rsc->initEGL();
ScriptTLSStruct *tlsStruct = new ScriptTLSStruct;
@@ -168,7 +163,7 @@
rsc->mRunning = true;
bool mDraw = true;
while (!rsc->mExit) {
- mDraw |= gIO->playCoreCommands(rsc, !mDraw);
+ mDraw |= rsc->mIO.playCoreCommands(rsc, !mDraw);
mDraw &= (rsc->mRootScript.get() != NULL);
if (mDraw) {
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 60a526b..3d17298 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -21,6 +21,7 @@
#include <ui/Surface.h>
+#include "rsThreadIO.h"
#include "rsType.h"
#include "rsMatrix.h"
#include "rsAllocation.h"
@@ -115,6 +116,9 @@
uint32_t getWidth() const {return mWidth;}
uint32_t getHeight() const {return mHeight;}
+
+ ThreadIO mIO;
+
protected:
Device *mDev;
diff --git a/libs/rs/rsScript.cpp b/libs/rs/rsScript.cpp
index 75c994b..6bcb8f2 100644
--- a/libs/rs/rsScript.cpp
+++ b/libs/rs/rsScript.cpp
@@ -76,11 +76,12 @@
s->mEnviroment.mClearStencil = v;
}
-void rsi_ScriptSetType(Context * rsc, RsType vt, uint32_t slot, const char *name)
+void rsi_ScriptSetType(Context * rsc, RsType vt, uint32_t slot, bool writable, const char *name)
{
ScriptCState *ss = &rsc->mScriptC;
const Type *t = static_cast<const Type *>(vt);
ss->mConstantBufferTypes[slot].set(t);
+ ss->mSlotWritable[slot] = writable;
if (name) {
ss->mSlotNames[slot].setTo(name);
} else {
diff --git a/libs/rs/rsScript.h b/libs/rs/rsScript.h
index dc66763..60f83a6 100644
--- a/libs/rs/rsScript.h
+++ b/libs/rs/rsScript.h
@@ -61,6 +61,7 @@
ObjectBaseRef<Allocation> mSlots[MAX_SCRIPT_BANKS];
ObjectBaseRef<const Type> mTypes[MAX_SCRIPT_BANKS];
String8 mSlotNames[MAX_SCRIPT_BANKS];
+ bool mSlotWritable[MAX_SCRIPT_BANKS];
virtual bool run(Context *, uint32_t launchID) = 0;
};
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index ced2516..db4fd09 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -93,6 +93,7 @@
for (uint32_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
mConstantBufferTypes[ct].clear();
mSlotNames[ct].setTo("");
+ mSlotWritable[ct] = false;
}
memset(&mEnviroment, 0, sizeof(mEnviroment));
@@ -341,6 +342,7 @@
for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
s->mTypes[ct].set(ss->mConstantBufferTypes[ct].get());
s->mSlotNames[ct] = ss->mSlotNames[ct];
+ s->mSlotWritable[ct] = ss->mSlotWritable[ct];
}
ss->clear();
diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h
index 32a9079..302515e 100644
--- a/libs/rs/rsScriptC.h
+++ b/libs/rs/rsScriptC.h
@@ -70,6 +70,7 @@
ObjectBaseRef<const Type> mConstantBufferTypes[MAX_SCRIPT_BANKS];
String8 mSlotNames[MAX_SCRIPT_BANKS];
+ bool mSlotWritable[MAX_SCRIPT_BANKS];
void clear();
void runCompiler(Context *rsc);
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index c13894b..0ecdf9a 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -465,6 +465,14 @@
}
+static void SC_vec2Rand(float *vec, float maxLen)
+{
+ float angle = SC_randf(PI * 2);
+ float len = SC_randf(maxLen);
+ vec[0] = len * sinf(angle);
+ vec[1] = len * cosf(angle);
+}
+
//////////////////////////////////////////////////////////////////////////////
@@ -780,6 +788,24 @@
return rsc->getHeight();
}
+static uint32_t SC_colorFloatRGBAtoUNorm8(float r, float g, float b, float a)
+{
+ uint32_t c = 0;
+ c |= (uint32_t)(r * 255.f + 0.5f);
+ c |= ((uint32_t)(g * 255.f + 0.5f)) << 8;
+ c |= ((uint32_t)(b * 255.f + 0.5f)) << 16;
+ c |= ((uint32_t)(a * 255.f + 0.5f)) << 24;
+ return c;
+}
+
+static uint32_t SC_colorFloatRGBAto565(float r, float g, float b)
+{
+ uint32_t ir = (uint32_t)(r * 255.f + 0.5f);
+ uint32_t ig = (uint32_t)(g * 255.f + 0.5f);
+ uint32_t ib = (uint32_t)(b * 255.f + 0.5f);
+ return rs888to565(ir, ig, ib);
+}
+
//////////////////////////////////////////////////////////////////////////////
// Class implementation
//////////////////////////////////////////////////////////////////////////////
@@ -937,6 +963,10 @@
{ "matrixTranslate", (void *)&SC_matrixTranslate,
"void", "(float *mat, float x, float y, float z)" },
+ // vector
+ { "vec2Rand", (void *)&SC_vec2Rand,
+ "void", "(float *vec, float maxLen)" },
+
// context
{ "bindProgramFragment", (void *)&SC_bindProgramFragment,
"void", "(int)" },
@@ -999,6 +1029,12 @@
{ "uploadToBufferObject", (void *)&SC_uploadToBufferObject,
"void", "(int)" },
+ { "colorFloatRGBAtoUNorm8", (void *)&SC_colorFloatRGBAtoUNorm8,
+ "int", "(float, float, float, float)" },
+ { "colorFloatRGBto565", (void *)&SC_colorFloatRGBAto565,
+ "int", "(float, float, float)" },
+
+
{ "getWidth", (void *)&SC_getWidth,
"int", "()" },
{ "getHeight", (void *)&SC_getHeight,
diff --git a/libs/rs/rsThreadIO.cpp b/libs/rs/rsThreadIO.cpp
index 89df59d..20b0a94 100644
--- a/libs/rs/rsThreadIO.cpp
+++ b/libs/rs/rsThreadIO.cpp
@@ -21,8 +21,6 @@
using namespace android;
using namespace android::renderscript;
-ThreadIO *android::renderscript::gIO = NULL;
-
ThreadIO::ThreadIO()
{
mToCore.init(16 * 1024);
diff --git a/libs/rs/rsThreadIO.h b/libs/rs/rsThreadIO.h
index 72746c5..4aab1b4 100644
--- a/libs/rs/rsThreadIO.h
+++ b/libs/rs/rsThreadIO.h
@@ -43,9 +43,6 @@
};
-extern ThreadIO *gIO;
-
-
}
}
diff --git a/libs/rs/rsg_generator.c b/libs/rs/rsg_generator.c
index 7cf6bb6..e3f816f 100644
--- a/libs/rs/rsg_generator.c
+++ b/libs/rs/rsg_generator.c
@@ -103,8 +103,10 @@
fprintf(f, " %s%s (", prefix, api->name);
if (addContext) {
fprintf(f, "Context *");
+ } else {
+ fprintf(f, "RsContext rsc");
}
- printArgList(f, api, addContext);
+ printArgList(f, api, 1);
fprintf(f, ")");
}
@@ -147,7 +149,7 @@
printFuncDecl(f, api, "rs", 0);
fprintf(f, "\n{\n");
- fprintf(f, " ThreadIO *io = gIO;\n");
+ fprintf(f, " ThreadIO *io = &((Context *)rsc)->mIO;\n");
//fprintf(f, " LOGE(\"add command %s\\n\");\n", api->name);
fprintf(f, " RS_CMD_%s *cmd = static_cast<RS_CMD_%s *>(io->mToCore.reserve(sizeof(RS_CMD_%s)));\n", api->name, api->name, api->name);
fprintf(f, " uint32_t size = sizeof(RS_CMD_%s);\n", api->name);
@@ -200,7 +202,7 @@
fprintf(f, " const RS_CMD_%s *cmd = static_cast<const RS_CMD_%s *>(vp);\n", api->name, api->name);
fprintf(f, " ");
if (api->ret.typeName[0]) {
- fprintf(f, "gIO->mToCoreRet = (intptr_t)");
+ fprintf(f, "con->mIO.mToCoreRet = (intptr_t)");
}
fprintf(f, "rsi_%s(con", api->name);
for(ct2=0; ct2 < api->paramCount; ct2++) {
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 8c0b40d..6f92515 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -109,9 +109,6 @@
if (err) return err;
uint32_t bufferFlags = 0;
- if (flags & ISurfaceComposer::eGPU)
- bufferFlags |= Buffer::GPU;
-
if (flags & ISurfaceComposer::eSecure)
bufferFlags |= Buffer::SECURE;
@@ -599,7 +596,12 @@
Point Layer::getPhysicalSize() const
{
sp<const Buffer> front(frontBuffer().getBuffer());
- return Point(front->getWidth(), front->getHeight());
+ Point size(front->getWidth(), front->getHeight());
+ if ((size.x | size.y) == 0) {
+ // if we don't have a buffer yet, just use the state's size.
+ size = LayerBase::getPhysicalSize();
+ }
+ return size;
}
void Layer::unlockPageFlip(
diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h
index 48ee553..87e8f42 100644
--- a/libs/surfaceflinger/LayerBitmap.h
+++ b/libs/surfaceflinger/LayerBitmap.h
@@ -53,7 +53,6 @@
public:
enum {
DONT_CLEAR = 0x00000001,
- GPU = 0x00000002,
SECURE = 0x00000004
};
@@ -98,7 +97,6 @@
public:
enum {
DONT_CLEAR = Buffer::DONT_CLEAR,
- GPU = Buffer::GPU,
SECURE = Buffer::SECURE
};
LayerBitmap();
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index 2b6905f..f6792c4 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -382,9 +382,9 @@
Surface::Surface(const sp<SurfaceControl>& surface)
: mClient(surface->mClient), mSurface(surface->mSurface),
mToken(surface->mToken), mIdentity(surface->mIdentity),
- mWidth(surface->mWidth), mHeight(surface->mHeight),
mFormat(surface->mFormat), mFlags(surface->mFlags),
- mBufferMapper(BufferMapper::get())
+ mBufferMapper(BufferMapper::get()),
+ mWidth(surface->mWidth), mHeight(surface->mHeight)
{
init();
}
@@ -426,9 +426,9 @@
const_cast<uint32_t&>(android_native_window_t::flags) = 0;
// be default we request a hardware surface
mUsage = GRALLOC_USAGE_HW_RENDER;
+ mUsageChanged = true;
}
-
Surface::~Surface()
{
// this is a client-side operation, the surface is destroyed, unmap
@@ -446,11 +446,24 @@
IPCThreadState::self()->flushCommands();
}
+sp<SurfaceComposerClient> Surface::getClient() const {
+ return mClient;
+}
+
+sp<ISurface> Surface::getISurface() const {
+ return mSurface;
+}
+
+bool Surface::isValid() {
+ return mToken>=0 && mClient!=0;
+}
+
status_t Surface::validate(per_client_cblk_t const* cblk) const
{
+ sp<SurfaceComposerClient> client(getClient());
if (mToken<0 || mClient==0) {
LOGE("invalid token (%d, identity=%u) or client (%p)",
- mToken, mIdentity, mClient.get());
+ mToken, mIdentity, client.get());
return NO_INIT;
}
if (cblk == 0) {
@@ -477,6 +490,7 @@
{
if (lhs == 0 || rhs == 0)
return false;
+
return lhs->mSurface->asBinder() == rhs->mSurface->asBinder();
}
@@ -532,10 +546,9 @@
{
android_native_buffer_t* out;
status_t err = dequeueBuffer(&out);
- *buffer = SurfaceBuffer::getSelf(out);
- // reset the width/height with the what we get from the buffer
- mWidth = uint32_t(out->width);
- mHeight = uint32_t(out->height);
+ if (err == NO_ERROR) {
+ *buffer = SurfaceBuffer::getSelf(out);
+ }
return err;
}
@@ -557,7 +570,8 @@
Mutex::Autolock _l(mSurfaceLock);
- per_client_cblk_t* const cblk = mClient->mControl;
+ sp<SurfaceComposerClient> client(getClient());
+ per_client_cblk_t* const cblk = client->mControl;
status_t err = validate(cblk);
if (err != NO_ERROR)
return err;
@@ -572,14 +586,17 @@
mBackbufferIndex = backIdx;
layer_cblk_t* const lcblk = &(cblk->layers[index]);
-
volatile const surface_info_t* const back = lcblk->surface + backIdx;
- if (back->flags & surface_info_t::eNeedNewBuffer) {
+ if ((back->flags & surface_info_t::eNeedNewBuffer) || mUsageChanged) {
+ mUsageChanged = false;
err = getBufferLocked(backIdx, mUsage);
}
if (err == NO_ERROR) {
const sp<SurfaceBuffer>& backBuffer(mBuffers[backIdx]);
+ // reset the width/height with the what we get from the buffer
+ mWidth = uint32_t(backBuffer->width);
+ mHeight = uint32_t(backBuffer->height);
mDirtyRegion.set(backBuffer->width, backBuffer->height);
*buffer = backBuffer.get();
}
@@ -591,7 +608,8 @@
{
Mutex::Autolock _l(mSurfaceLock);
- per_client_cblk_t* const cblk = mClient->mControl;
+ sp<SurfaceComposerClient> client(getClient());
+ per_client_cblk_t* const cblk = client->mControl;
status_t err = validate(cblk);
if (err != NO_ERROR)
return err;
@@ -604,7 +622,8 @@
{
Mutex::Autolock _l(mSurfaceLock);
- per_client_cblk_t* const cblk = mClient->mControl;
+ sp<SurfaceComposerClient> client(getClient());
+ per_client_cblk_t* const cblk = client->mControl;
status_t err = validate(cblk);
if (err != NO_ERROR)
return err;
@@ -620,7 +639,7 @@
uint32_t newstate = cblk->unlock_layer_and_post(size_t(index));
if (!(newstate & eNextFlipPending))
- mClient->signalServer();
+ client->signalServer();
return NO_ERROR;
}
@@ -646,7 +665,7 @@
int res = NO_ERROR;
switch (operation) {
case NATIVE_WINDOW_SET_USAGE:
- mUsage = va_arg(args, int);
+ setUsage( va_arg(args, int) );
break;
default:
res = NAME_NOT_FOUND;
@@ -655,6 +674,15 @@
return res;
}
+void Surface::setUsage(uint32_t reqUsage)
+{
+ Mutex::Autolock _l(mSurfaceLock);
+ if (mUsage != reqUsage) {
+ mUsageChanged = true;
+ mUsage = reqUsage;
+ }
+}
+
// ----------------------------------------------------------------------------
status_t Surface::lock(SurfaceInfo* info, bool blocking) {
@@ -663,11 +691,9 @@
status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
{
- // FIXME: needs some locking here
-
// we're intending to do software rendering from this point
- mUsage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
-
+ setUsage(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+
sp<SurfaceBuffer> backBuffer;
status_t err = dequeueBuffer(&backBuffer);
if (err == NO_ERROR) {
@@ -679,7 +705,8 @@
Region scratch(bounds);
Region& newDirtyRegion(dirtyIn ? *dirtyIn : scratch);
- per_client_cblk_t* const cblk = mClient->mControl;
+ sp<SurfaceComposerClient> client(getClient());
+ per_client_cblk_t* const cblk = client->mControl;
layer_cblk_t* const lcblk = &(cblk->layers[SurfaceID(mToken)]);
volatile const surface_info_t* const back = lcblk->surface + mBackbufferIndex;
if (back->flags & surface_info_t::eBufferDirty) {
@@ -725,8 +752,6 @@
status_t Surface::unlockAndPost()
{
- // FIXME: needs some locking here
-
if (mLockedBuffer == 0)
return BAD_VALUE;
@@ -753,13 +778,17 @@
}
void Surface::setSwapRectangle(const Rect& r) {
+ Mutex::Autolock _l(mSurfaceLock);
mSwapRectangle = r;
}
status_t Surface::getBufferLocked(int index, int usage)
{
+ sp<ISurface> s(mSurface);
+ if (s == 0) return NO_INIT;
+
status_t err = NO_MEMORY;
- sp<SurfaceBuffer> buffer = mSurface->getBuffer(usage);
+ sp<SurfaceBuffer> buffer = s->getBuffer(usage);
LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
if (buffer != 0) {
sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 60fc0e0..16bf8a2 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -153,20 +153,6 @@
@Deprecated public static final int NUM_STREAMS = AudioSystem.NUM_STREAMS;
- /** @hide Maximum volume index values for audio streams */
- public static final int[] MAX_STREAM_VOLUME = new int[] {
- 6, // STREAM_VOICE_CALL
- 8, // STREAM_SYSTEM
- 8, // STREAM_RING
- 16, // STREAM_MUSIC
- 8, // STREAM_ALARM
- 8, // STREAM_NOTIFICATION
- 16, // STREAM_BLUETOOTH_SCO
- 8, // STREAM_SYSTEM_ENFORCED
- 16, // STREAM_DTMF
- 16 // STREAM_TTS
- };
-
/** @hide Default volume index values for audio streams */
public static final int[] DEFAULT_STREAM_VOLUME = new int[] {
4, // STREAM_VOICE_CALL
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 9afe6a1..05b68d4 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -17,16 +17,16 @@
package android.media;
import android.app.ActivityManagerNative;
+import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.bluetooth.BluetoothIntent;
-import android.content.BroadcastReceiver;
-import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothIntent;
+import android.bluetooth.BluetoothHeadset;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
@@ -44,6 +44,7 @@
import android.provider.Settings.System;
import android.util.Log;
import android.view.VolumePanel;
+import android.os.SystemProperties;
import com.android.internal.telephony.ITelephony;
@@ -54,6 +55,7 @@
import java.util.Map;
import java.util.Set;
+
/**
* The implementation of the volume manager service.
* <p>
@@ -140,6 +142,19 @@
{4, -1} // FX_FOCUS_RETURN
};
+ /** @hide Maximum volume index values for audio streams */
+ private int[] MAX_STREAM_VOLUME = new int[] {
+ 6, // STREAM_VOICE_CALL
+ 8, // STREAM_SYSTEM
+ 8, // STREAM_RING
+ 16, // STREAM_MUSIC
+ 8, // STREAM_ALARM
+ 8, // STREAM_NOTIFICATION
+ 16, // STREAM_BLUETOOTH_SCO
+ 8, // STREAM_SYSTEM_ENFORCED
+ 16, // STREAM_DTMF
+ 16 // STREAM_TTS
+ };
/* STREAM_VOLUME_ALIAS[] indicates for each stream if it uses the volume settings
* of another stream: This avoids multiplying the volume settings for hidden
* stream types that follow other stream behavior for volume settings
@@ -221,8 +236,6 @@
// Forced device usage for communications
private int mForcedUseForComm;
- private BluetoothDevice mBluetoothDevice = null;
-
///////////////////////////////////////////////////////////////////////////
// Construction
///////////////////////////////////////////////////////////////////////////
@@ -231,6 +244,12 @@
public AudioService(Context context) {
mContext = context;
mContentResolver = context.getContentResolver();
+
+ // Intialized volume
+ MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL] = SystemProperties.getInt(
+ "ro.config.vc_call_vol_steps",
+ MAX_STREAM_VOLUME[AudioSystem.STREAM_VOICE_CALL]);
+
mVolumePanel = new VolumePanel(context, this);
mSettingsObserver = new SettingsObserver();
mMode = AudioSystem.MODE_NORMAL;
@@ -249,6 +268,7 @@
intentFilter.addAction(BluetoothA2dp.SINK_STATE_CHANGED_ACTION);
intentFilter.addAction(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION);
context.registerReceiver(mReceiver, intentFilter);
+
}
private void createAudioSystemThread() {
@@ -945,7 +965,7 @@
mStreamType = streamType;
final ContentResolver cr = mContentResolver;
- mIndexMax = AudioManager.MAX_STREAM_VOLUME[streamType];
+ mIndexMax = MAX_STREAM_VOLUME[streamType];
mIndex = Settings.System.getInt(cr,
mVolumeIndexSettingName,
AudioManager.DEFAULT_STREAM_VOLUME[streamType]);
@@ -1349,8 +1369,8 @@
if (action.equals(BluetoothA2dp.SINK_STATE_CHANGED_ACTION)) {
int state = intent.getIntExtra(BluetoothA2dp.SINK_STATE,
BluetoothA2dp.STATE_DISCONNECTED);
- String address = intent.getStringExtra(BluetoothIntent.ADDRESS);
-
+ BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothIntent.DEVICE);
+ String address = btDevice.getAddress();
boolean isConnected = (mConnectedDevices.containsKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) &&
((String)mConnectedDevices.get(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP)).equals(address));
@@ -1365,30 +1385,27 @@
AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
AudioSystem.DEVICE_STATE_AVAILABLE,
address);
- mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP), address);
+ mConnectedDevices.put( new Integer(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP),
+ address);
}
} else if (action.equals(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION)) {
int state = intent.getIntExtra(BluetoothIntent.HEADSET_STATE,
BluetoothHeadset.STATE_ERROR);
- String address = intent.getStringExtra(BluetoothIntent.ADDRESS);
+ BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothIntent.DEVICE);
+ String address = btDevice.getAddress();
int device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
- if (mBluetoothDevice == null) {
- mBluetoothDevice = (BluetoothDevice)mContext.getSystemService(Context.BLUETOOTH_SERVICE);
- }
- if (mBluetoothDevice != null) {
- int btClass = mBluetoothDevice.getRemoteClass(address);
- if (BluetoothClass.Device.Major.getDeviceMajor(btClass) == BluetoothClass.Device.Major.AUDIO_VIDEO) {
- switch (BluetoothClass.Device.getDevice(btClass)) {
- case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
- case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
- device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
- break;
- case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
- device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
- break;
- default:
- break;
- }
+ int btClass = btDevice.getBluetoothClass();
+ if (BluetoothClass.Device.Major.getDeviceMajor(btClass) == BluetoothClass.Device.Major.AUDIO_VIDEO) {
+ switch (BluetoothClass.Device.getDevice(btClass)) {
+ case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
+ case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
+ device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
+ break;
+ case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
+ device = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
+ break;
+ default:
+ break;
}
}
@@ -1404,7 +1421,7 @@
AudioSystem.setDeviceConnectionState(device,
AudioSystem.DEVICE_STATE_AVAILABLE,
address);
- mConnectedDevices.put( new Integer(device), address);
+ mConnectedDevices.put(new Integer(device), address);
}
} else if (action.equals(Intent.ACTION_HEADSET_PLUG)) {
int state = intent.getIntExtra("state", 0);
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 6d7c0ae..d578c81 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -18,6 +18,9 @@
import android.util.Log;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@@ -59,7 +62,7 @@
// The Exif tag names
public static final String TAG_ORIENTATION = "Orientation";
- public static final String TAG_DATE_TIME_ORIGINAL = "DateTimeOriginal";
+ public static final String TAG_DATETIME = "DateTime";
public static final String TAG_MAKE = "Make";
public static final String TAG_MODEL = "Model";
public static final String TAG_FLASH = "Flash";
@@ -321,6 +324,28 @@
return latlng;
}
+ private static SimpleDateFormat sFormatter =
+ new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
+
+ // Returns number of milliseconds since Jan. 1, 1970, midnight GMT.
+ // Returns -1 if the date time information if not available.
+ public static long getDateTime(HashMap<String, String> exifData) {
+ if (exifData == null) {
+ return -1;
+ }
+
+ String dateTimeString = exifData.get(ExifInterface.TAG_DATETIME);
+ if (dateTimeString == null) return -1;
+
+ ParsePosition pos = new ParsePosition(0);
+ try {
+ Date date = sFormatter.parse(dateTimeString, pos);
+ return date.getTime();
+ } catch (IllegalArgumentException ex) {
+ return -1;
+ }
+ }
+
public static float convertRationalLatLonToFloat(
String rationalString, String ref) {
try {
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index c6a9ae8..cecf4f8 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -254,5 +254,6 @@
public static final int METADATA_KEY_VIDEO_FORMAT = 18;
public static final int METADATA_KEY_VIDEO_HEIGHT = 19;
public static final int METADATA_KEY_VIDEO_WIDTH = 20;
+ public static final int METADATA_KEY_WRITER = 21;
// Add more here...
}
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 71af909..3d5aae3 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -396,6 +396,7 @@
private String mPath;
private long mLastModified;
private long mFileSize;
+ private String mWriter;
public FileCacheEntry beginFile(String path, String mimeType, long lastModified, long fileSize) {
@@ -479,6 +480,7 @@
mDuration = 0;
mPath = path;
mLastModified = lastModified;
+ mWriter = null;
return entry;
}
@@ -593,6 +595,8 @@
mTrack = (num * 1000) + (mTrack % 1000);
} else if (name.equalsIgnoreCase("duration")) {
mDuration = parseSubstring(value, 0, 0);
+ } else if (name.equalsIgnoreCase("writer") || name.startsWith("writer;")) {
+ mWriter = value.trim();
}
}
@@ -716,6 +720,11 @@
values.put(Images.Media.LATITUDE, latlng[0]);
values.put(Images.Media.LONGITUDE, latlng[1]);
}
+
+ long time = ExifInterface.getDateTime(exifData);
+ if (time != -1) {
+ values.put(Images.Media.DATE_TAKEN, time);
+ }
}
}
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index d1dbc5c..10bebd0 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -18,6 +18,8 @@
SEND_COMMAND,
GET_PARAMETER,
SET_PARAMETER,
+ GET_CONFIG,
+ SET_CONFIG,
USE_BUFFER,
ALLOC_BUFFER,
ALLOC_BUFFER_WITH_BACKUP,
@@ -25,6 +27,7 @@
OBSERVE_NODE,
FILL_BUFFER,
EMPTY_BUFFER,
+ GET_EXTENSION_INDEX,
CREATE_RENDERER,
OBSERVER_ON_MSG,
RENDERER_RENDER,
@@ -42,16 +45,6 @@
displayWidth, displayHeight);
}
-static void *readVoidStar(const Parcel *parcel) {
- // FIX if sizeof(void *) != sizeof(int32)
- return (void *)parcel->readInt32();
-}
-
-static void writeVoidStar(void *x, Parcel *parcel) {
- // FIX if sizeof(void *) != sizeof(int32)
- parcel->writeInt32((int32_t)x);
-}
-
class BpOMX : public BpInterface<IOMX> {
public:
BpOMX(const sp<IBinder> &impl)
@@ -83,7 +76,7 @@
status_t err = reply.readInt32();
if (err == OK) {
- *node = readVoidStar(&reply);
+ *node = (void*)reply.readIntPtr();
} else {
*node = 0;
}
@@ -94,7 +87,7 @@
virtual status_t free_node(node_id node) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- writeVoidStar(node, &data);
+ data.writeIntPtr((intptr_t)node);
remote()->transact(FREE_NODE, data, &reply);
return reply.readInt32();
@@ -104,7 +97,7 @@
node_id node, OMX_COMMANDTYPE cmd, OMX_S32 param) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- writeVoidStar(node, &data);
+ data.writeIntPtr((intptr_t)node);
data.writeInt32(cmd);
data.writeInt32(param);
remote()->transact(SEND_COMMAND, data, &reply);
@@ -117,7 +110,7 @@
void *params, size_t size) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- writeVoidStar(node, &data);
+ data.writeIntPtr((intptr_t)node);
data.writeInt32(index);
data.writeInt32(size);
data.write(params, size);
@@ -138,7 +131,7 @@
const void *params, size_t size) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- writeVoidStar(node, &data);
+ data.writeIntPtr((intptr_t)node);
data.writeInt32(index);
data.writeInt32(size);
data.write(params, size);
@@ -147,12 +140,47 @@
return reply.readInt32();
}
+ virtual status_t get_config(
+ node_id node, OMX_INDEXTYPE index,
+ void *params, size_t size) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(index);
+ data.writeInt32(size);
+ data.write(params, size);
+ remote()->transact(GET_CONFIG, data, &reply);
+
+ status_t err = reply.readInt32();
+ if (err != OK) {
+ return err;
+ }
+
+ reply.read(params, size);
+
+ return OK;
+ }
+
+ virtual status_t set_config(
+ node_id node, OMX_INDEXTYPE index,
+ const void *params, size_t size) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeInt32(index);
+ data.writeInt32(size);
+ data.write(params, size);
+ remote()->transact(SET_CONFIG, data, &reply);
+
+ return reply.readInt32();
+ }
+
virtual status_t use_buffer(
node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
buffer_id *buffer) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- writeVoidStar(node, &data);
+ data.writeIntPtr((intptr_t)node);
data.writeInt32(port_index);
data.writeStrongBinder(params->asBinder());
remote()->transact(USE_BUFFER, data, &reply);
@@ -164,7 +192,7 @@
return err;
}
- *buffer = readVoidStar(&reply);
+ *buffer = (void*)reply.readIntPtr();
return err;
}
@@ -174,7 +202,7 @@
buffer_id *buffer) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- writeVoidStar(node, &data);
+ data.writeIntPtr((intptr_t)node);
data.writeInt32(port_index);
data.writeInt32(size);
remote()->transact(ALLOC_BUFFER, data, &reply);
@@ -186,7 +214,7 @@
return err;
}
- *buffer = readVoidStar(&reply);
+ *buffer = (void*)reply.readIntPtr();
return err;
}
@@ -196,7 +224,7 @@
buffer_id *buffer) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- writeVoidStar(node, &data);
+ data.writeIntPtr((intptr_t)node);
data.writeInt32(port_index);
data.writeStrongBinder(params->asBinder());
remote()->transact(ALLOC_BUFFER_WITH_BACKUP, data, &reply);
@@ -208,7 +236,7 @@
return err;
}
- *buffer = readVoidStar(&reply);
+ *buffer = (void*)reply.readIntPtr();
return err;
}
@@ -217,9 +245,9 @@
node_id node, OMX_U32 port_index, buffer_id buffer) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- writeVoidStar(node, &data);
+ data.writeIntPtr((intptr_t)node);
data.writeInt32(port_index);
- writeVoidStar(buffer, &data);
+ data.writeIntPtr((intptr_t)buffer);
remote()->transact(FREE_BUFFER, data, &reply);
return reply.readInt32();
@@ -229,7 +257,7 @@
node_id node, const sp<IOMXObserver> &observer) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- writeVoidStar(node, &data);
+ data.writeIntPtr((intptr_t)node);
data.writeStrongBinder(observer->asBinder());
remote()->transact(OBSERVE_NODE, data, &reply);
@@ -239,8 +267,8 @@
virtual void fill_buffer(node_id node, buffer_id buffer) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- writeVoidStar(node, &data);
- writeVoidStar(buffer, &data);
+ data.writeIntPtr((intptr_t)node);
+ data.writeIntPtr((intptr_t)buffer);
remote()->transact(FILL_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
}
@@ -251,8 +279,8 @@
OMX_U32 flags, OMX_TICKS timestamp) {
Parcel data, reply;
data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
- writeVoidStar(node, &data);
- writeVoidStar(buffer, &data);
+ data.writeIntPtr((intptr_t)node);
+ data.writeIntPtr((intptr_t)buffer);
data.writeInt32(range_offset);
data.writeInt32(range_length);
data.writeInt32(flags);
@@ -260,6 +288,27 @@
remote()->transact(EMPTY_BUFFER, data, &reply, IBinder::FLAG_ONEWAY);
}
+ virtual status_t get_extension_index(
+ node_id node,
+ const char *parameter_name,
+ OMX_INDEXTYPE *index) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IOMX::getInterfaceDescriptor());
+ data.writeIntPtr((intptr_t)node);
+ data.writeCString(parameter_name);
+
+ remote()->transact(GET_EXTENSION_INDEX, data, &reply);
+
+ status_t err = reply.readInt32();
+ if (err == OK) {
+ *index = static_cast<OMX_INDEXTYPE>(reply.readInt32());
+ } else {
+ *index = OMX_IndexComponentStartUnused;
+ }
+
+ return err;
+ }
+
virtual sp<IOMXRenderer> createRenderer(
const sp<ISurface> &surface,
const char *componentName,
@@ -320,7 +369,7 @@
status_t err = allocate_node(data.readCString(), &node);
reply->writeInt32(err);
if (err == OK) {
- writeVoidStar(node, reply);
+ reply->writeIntPtr((intptr_t)node);
}
return NO_ERROR;
@@ -330,7 +379,7 @@
{
CHECK_INTERFACE(IOMX, data, reply);
- node_id node = readVoidStar(&data);
+ node_id node = (void*)data.readIntPtr();
reply->writeInt32(free_node(node));
@@ -341,7 +390,7 @@
{
CHECK_INTERFACE(IOMX, data, reply);
- node_id node = readVoidStar(&data);
+ node_id node = (void*)data.readIntPtr();
OMX_COMMANDTYPE cmd =
static_cast<OMX_COMMANDTYPE>(data.readInt32());
@@ -356,7 +405,7 @@
{
CHECK_INTERFACE(IOMX, data, reply);
- node_id node = readVoidStar(&data);
+ node_id node = (void*)data.readIntPtr();
OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
size_t size = data.readInt32();
@@ -383,7 +432,7 @@
{
CHECK_INTERFACE(IOMX, data, reply);
- node_id node = readVoidStar(&data);
+ node_id node = (void*)data.readIntPtr();
OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
size_t size = data.readInt32();
@@ -394,11 +443,53 @@
return NO_ERROR;
}
+ case GET_CONFIG:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
+
+ size_t size = data.readInt32();
+
+ // XXX I am not happy with this but Parcel::readInplace didn't work.
+ void *params = malloc(size);
+ data.read(params, size);
+
+ status_t err = get_config(node, index, params, size);
+
+ reply->writeInt32(err);
+
+ if (err == OK) {
+ reply->write(params, size);
+ }
+
+ free(params);
+ params = NULL;
+
+ return NO_ERROR;
+ }
+
+ case SET_CONFIG:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ OMX_INDEXTYPE index = static_cast<OMX_INDEXTYPE>(data.readInt32());
+
+ size_t size = data.readInt32();
+ void *params = const_cast<void *>(data.readInplace(size));
+
+ reply->writeInt32(set_config(node, index, params, size));
+
+ return NO_ERROR;
+ }
+
case USE_BUFFER:
{
CHECK_INTERFACE(IOMX, data, reply);
- node_id node = readVoidStar(&data);
+ node_id node = (void*)data.readIntPtr();
OMX_U32 port_index = data.readInt32();
sp<IMemory> params =
interface_cast<IMemory>(data.readStrongBinder());
@@ -408,7 +499,7 @@
reply->writeInt32(err);
if (err == OK) {
- writeVoidStar(buffer, reply);
+ reply->writeIntPtr((intptr_t)buffer);
}
return NO_ERROR;
@@ -418,7 +509,7 @@
{
CHECK_INTERFACE(IOMX, data, reply);
- node_id node = readVoidStar(&data);
+ node_id node = (void*)data.readIntPtr();
OMX_U32 port_index = data.readInt32();
size_t size = data.readInt32();
@@ -427,7 +518,7 @@
reply->writeInt32(err);
if (err == OK) {
- writeVoidStar(buffer, reply);
+ reply->writeIntPtr((intptr_t)buffer);
}
return NO_ERROR;
@@ -437,7 +528,7 @@
{
CHECK_INTERFACE(IOMX, data, reply);
- node_id node = readVoidStar(&data);
+ node_id node = (void*)data.readIntPtr();
OMX_U32 port_index = data.readInt32();
sp<IMemory> params =
interface_cast<IMemory>(data.readStrongBinder());
@@ -449,7 +540,7 @@
reply->writeInt32(err);
if (err == OK) {
- writeVoidStar(buffer, reply);
+ reply->writeIntPtr((intptr_t)buffer);
}
return NO_ERROR;
@@ -459,9 +550,9 @@
{
CHECK_INTERFACE(IOMX, data, reply);
- node_id node = readVoidStar(&data);
+ node_id node = (void*)data.readIntPtr();
OMX_U32 port_index = data.readInt32();
- buffer_id buffer = readVoidStar(&data);
+ buffer_id buffer = (void*)data.readIntPtr();
reply->writeInt32(free_buffer(node, port_index, buffer));
return NO_ERROR;
@@ -471,7 +562,7 @@
{
CHECK_INTERFACE(IOMX, data, reply);
- node_id node = readVoidStar(&data);
+ node_id node = (void*)data.readIntPtr();
sp<IOMXObserver> observer =
interface_cast<IOMXObserver>(data.readStrongBinder());
reply->writeInt32(observe_node(node, observer));
@@ -483,8 +574,8 @@
{
CHECK_INTERFACE(IOMX, data, reply);
- node_id node = readVoidStar(&data);
- buffer_id buffer = readVoidStar(&data);
+ node_id node = (void*)data.readIntPtr();
+ buffer_id buffer = (void*)data.readIntPtr();
fill_buffer(node, buffer);
return NO_ERROR;
@@ -494,8 +585,8 @@
{
CHECK_INTERFACE(IOMX, data, reply);
- node_id node = readVoidStar(&data);
- buffer_id buffer = readVoidStar(&data);
+ node_id node = (void*)data.readIntPtr();
+ buffer_id buffer = (void*)data.readIntPtr();
OMX_U32 range_offset = data.readInt32();
OMX_U32 range_length = data.readInt32();
OMX_U32 flags = data.readInt32();
@@ -508,6 +599,25 @@
return NO_ERROR;
}
+ case GET_EXTENSION_INDEX:
+ {
+ CHECK_INTERFACE(IOMX, data, reply);
+
+ node_id node = (void*)data.readIntPtr();
+ const char *parameter_name = data.readCString();
+
+ OMX_INDEXTYPE index;
+ status_t err = get_extension_index(node, parameter_name, &index);
+
+ reply->writeInt32(err);
+
+ if (err == OK) {
+ reply->writeInt32(index);
+ }
+
+ return OK;
+ }
+
case CREATE_RENDERER:
{
CHECK_INTERFACE(IOMX, data, reply);
@@ -591,7 +701,7 @@
virtual void render(IOMX::buffer_id buffer) {
Parcel data, reply;
data.writeInterfaceToken(IOMXRenderer::getInterfaceDescriptor());
- writeVoidStar(buffer, &data);
+ data.writeIntPtr((intptr_t)buffer);
// NOTE: Do NOT make this a ONE_WAY call, it must be synchronous
// so that the caller knows when to recycle the buffer.
@@ -608,7 +718,7 @@
{
CHECK_INTERFACE(IOMXRenderer, data, reply);
- IOMX::buffer_id buffer = readVoidStar(&data);
+ IOMX::buffer_id buffer = (void*)data.readIntPtr();
render(buffer);
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 00ba1ac..0c40b91 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -17,6 +17,7 @@
MediaSource.cpp \
MetaData.cpp \
MmapSource.cpp \
+ OMXCodec.cpp \
SampleTable.cpp \
ShoutcastSource.cpp \
TimeSource.cpp \
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index d547556..e8571b5 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -28,8 +28,7 @@
namespace android {
AudioPlayer::AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink)
- : mSource(NULL),
- mAudioTrack(NULL),
+ : mAudioTrack(NULL),
mInputBuffer(NULL),
mSampleRate(0),
mLatencyUs(0),
@@ -48,7 +47,7 @@
}
}
-void AudioPlayer::setSource(MediaSource *source) {
+void AudioPlayer::setSource(const sp<MediaSource> &source) {
assert(mSource == NULL);
mSource = source;
}
diff --git a/media/libstagefright/CachingDataSource.cpp b/media/libstagefright/CachingDataSource.cpp
index 0fd71d5..d599cd5 100644
--- a/media/libstagefright/CachingDataSource.cpp
+++ b/media/libstagefright/CachingDataSource.cpp
@@ -25,7 +25,7 @@
namespace android {
CachingDataSource::CachingDataSource(
- DataSource *source, size_t pageSize, int numPages)
+ const sp<DataSource> &source, size_t pageSize, int numPages)
: mSource(source),
mData(malloc(pageSize * numPages)),
mPageSize(pageSize),
@@ -61,9 +61,6 @@
free(mData);
mData = NULL;
-
- delete mSource;
- mSource = NULL;
}
status_t CachingDataSource::InitCheck() const {
@@ -78,7 +75,7 @@
Page *page = mFirst;
while (page != NULL) {
if (page->mOffset >= 0 && offset >= page->mOffset
- && offset < page->mOffset + page->mLength) {
+ && offset < page->mOffset + (off_t)page->mLength) {
break;
}
page = page->mNext;
@@ -102,7 +99,7 @@
return n;
}
- if (offset >= page->mOffset + page->mLength) {
+ if (offset >= page->mOffset + (off_t)page->mLength) {
break;
}
} else {
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 6e6b43d..02a276b 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -22,6 +22,19 @@
namespace android {
+bool DataSource::getUInt16(off_t offset, uint16_t *x) {
+ *x = 0;
+
+ uint8_t byte[2];
+ if (read_at(offset, byte, 2) != 2) {
+ return false;
+ }
+
+ *x = (byte[0] << 8) | byte[1];
+
+ return true;
+}
+
status_t DataSource::getSize(off_t *size) {
*size = 0;
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
index 01cb2d9..44258ba 100644
--- a/media/libstagefright/MP3Extractor.cpp
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -165,7 +165,7 @@
}
static bool Resync(
- DataSource *source, uint32_t match_header,
+ const sp<DataSource> &source, uint32_t match_header,
off_t *inout_pos, uint32_t *out_header) {
// Everything must match except for
// protection, bitrate, padding, private bits and mode extension.
@@ -281,11 +281,9 @@
class MP3Source : public MediaSource {
public:
MP3Source(
- const sp<MetaData> &meta, DataSource *source,
+ const sp<MetaData> &meta, const sp<DataSource> &source,
off_t first_frame_pos, uint32_t fixed_header);
- virtual ~MP3Source();
-
virtual status_t start(MetaData *params = NULL);
virtual status_t stop();
@@ -294,9 +292,12 @@
virtual status_t read(
MediaBuffer **buffer, const ReadOptions *options = NULL);
+protected:
+ virtual ~MP3Source();
+
private:
sp<MetaData> mMeta;
- DataSource *mDataSource;
+ sp<DataSource> mDataSource;
off_t mFirstFramePos;
uint32_t mFixedHeader;
off_t mCurrentPos;
@@ -309,7 +310,7 @@
MP3Source &operator=(const MP3Source &);
};
-MP3Extractor::MP3Extractor(DataSource *source)
+MP3Extractor::MP3Extractor(const sp<DataSource> &source)
: mDataSource(source),
mFirstFramePos(-1),
mFixedHeader(0) {
@@ -347,28 +348,22 @@
}
MP3Extractor::~MP3Extractor() {
- delete mDataSource;
- mDataSource = NULL;
}
-status_t MP3Extractor::countTracks(int *num_tracks) {
- *num_tracks = mFirstFramePos < 0 ? 0 : 1;
-
- return OK;
+size_t MP3Extractor::countTracks() {
+ return (mFirstFramePos < 0) ? 0 : 1;
}
-status_t MP3Extractor::getTrack(int index, MediaSource **source) {
+sp<MediaSource> MP3Extractor::getTrack(size_t index) {
if (mFirstFramePos < 0 || index != 0) {
- return ERROR_OUT_OF_RANGE;
+ return NULL;
}
- *source = new MP3Source(
+ return new MP3Source(
mMeta, mDataSource, mFirstFramePos, mFixedHeader);
-
- return OK;
}
-sp<MetaData> MP3Extractor::getTrackMetaData(int index) {
+sp<MetaData> MP3Extractor::getTrackMetaData(size_t index) {
if (mFirstFramePos < 0 || index != 0) {
return NULL;
}
@@ -379,7 +374,7 @@
////////////////////////////////////////////////////////////////////////////////
MP3Source::MP3Source(
- const sp<MetaData> &meta, DataSource *source,
+ const sp<MetaData> &meta, const sp<DataSource> &source,
off_t first_frame_pos, uint32_t fixed_header)
: mMeta(meta),
mDataSource(source),
@@ -509,7 +504,8 @@
return OK;
}
-bool SniffMP3(DataSource *source, String8 *mimeType, float *confidence) {
+bool SniffMP3(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence) {
off_t pos = 0;
uint32_t header;
if (!Resync(source, 0, &pos, &header)) {
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 4c883c6..662d5fb 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -42,10 +42,9 @@
class MPEG4Source : public MediaSource {
public:
// Caller retains ownership of both "dataSource" and "sampleTable".
- MPEG4Source(const sp<MetaData> &format, DataSource *dataSource,
- SampleTable *sampleTable);
-
- virtual ~MPEG4Source();
+ MPEG4Source(const sp<MetaData> &format,
+ const sp<DataSource> &dataSource,
+ const sp<SampleTable> &sampleTable);
virtual status_t start(MetaData *params = NULL);
virtual status_t stop();
@@ -55,11 +54,14 @@
virtual status_t read(
MediaBuffer **buffer, const ReadOptions *options = NULL);
+protected:
+ virtual ~MPEG4Source();
+
private:
sp<MetaData> mFormat;
- DataSource *mDataSource;
+ sp<DataSource> mDataSource;
int32_t mTimescale;
- SampleTable *mSampleTable;
+ sp<SampleTable> mSampleTable;
uint32_t mCurrentSampleIndex;
bool mIsAVC;
@@ -141,7 +143,7 @@
}
}
-MPEG4Extractor::MPEG4Extractor(DataSource *source)
+MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
: mDataSource(source),
mHaveMetadata(false),
mFirstTrack(NULL),
@@ -153,39 +155,29 @@
while (track) {
Track *next = track->next;
- delete track->sampleTable;
- track->sampleTable = NULL;
-
delete track;
track = next;
}
mFirstTrack = mLastTrack = NULL;
-
- delete mDataSource;
- mDataSource = NULL;
}
-status_t MPEG4Extractor::countTracks(int *num_tracks) {
+size_t MPEG4Extractor::countTracks() {
status_t err;
if ((err = readMetaData()) != OK) {
- return err;
+ return 0;
}
- *num_tracks = 0;
+ size_t n = 0;
Track *track = mFirstTrack;
while (track) {
- ++*num_tracks;
+ ++n;
track = track->next;
}
- return OK;
+ return n;
}
-sp<MetaData> MPEG4Extractor::getTrackMetaData(int index) {
- if (index < 0) {
- return NULL;
- }
-
+sp<MetaData> MPEG4Extractor::getTrackMetaData(size_t index) {
status_t err;
if ((err = readMetaData()) != OK) {
return NULL;
@@ -701,39 +693,32 @@
return OK;
}
-status_t MPEG4Extractor::getTrack(int index, MediaSource **source) {
- *source = NULL;
-
- if (index < 0) {
- return ERROR_OUT_OF_RANGE;
- }
-
+sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
status_t err;
if ((err = readMetaData()) != OK) {
- return err;
+ return NULL;
}
Track *track = mFirstTrack;
while (index > 0) {
if (track == NULL) {
- return ERROR_OUT_OF_RANGE;
+ return NULL;
}
track = track->next;
--index;
}
- *source = new MPEG4Source(
+ return new MPEG4Source(
track->meta, mDataSource, track->sampleTable);
-
- return OK;
}
////////////////////////////////////////////////////////////////////////////////
MPEG4Source::MPEG4Source(
const sp<MetaData> &format,
- DataSource *dataSource, SampleTable *sampleTable)
+ const sp<DataSource> &dataSource,
+ const sp<SampleTable> &sampleTable)
: mFormat(format),
mDataSource(dataSource),
mTimescale(0),
@@ -935,7 +920,8 @@
return OK;
}
-bool SniffMPEG4(DataSource *source, String8 *mimeType, float *confidence) {
+bool SniffMPEG4(
+ const sp<DataSource> &source, String8 *mimeType, float *confidence) {
uint8_t header[8];
ssize_t n = source->read_at(4, header, sizeof(header));
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index b53bb29..10c4629 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -32,7 +32,8 @@
class MPEG4Writer::Track {
public:
- Track(MPEG4Writer *owner, const sp<MetaData> &meta, MediaSource *source);
+ Track(MPEG4Writer *owner,
+ const sp<MetaData> &meta, const sp<MediaSource> &source);
~Track();
void start();
@@ -44,7 +45,7 @@
private:
MPEG4Writer *mOwner;
sp<MetaData> mMeta;
- MediaSource *mSource;
+ sp<MediaSource> mSource;
volatile bool mDone;
pthread_t mThread;
@@ -83,7 +84,8 @@
mTracks.clear();
}
-void MPEG4Writer::addSource(const sp<MetaData> &meta, MediaSource *source) {
+void MPEG4Writer::addSource(
+ const sp<MetaData> &meta, const sp<MediaSource> &source) {
Track *track = new Track(this, meta, source);
mTracks.push_back(track);
}
@@ -255,7 +257,8 @@
////////////////////////////////////////////////////////////////////////////////
MPEG4Writer::Track::Track(
- MPEG4Writer *owner, const sp<MetaData> &meta, MediaSource *source)
+ MPEG4Writer *owner,
+ const sp<MetaData> &meta, const sp<MediaSource> &source)
: mOwner(owner),
mMeta(meta),
mSource(source),
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index bc66794..5f78e12 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -27,7 +27,8 @@
namespace android {
// static
-MediaExtractor *MediaExtractor::Create(DataSource *source, const char *mime) {
+sp<MediaExtractor> MediaExtractor::Create(
+ const sp<DataSource> &source, const char *mime) {
String8 tmp;
if (mime == NULL) {
float confidence;
diff --git a/media/libstagefright/MediaPlayerImpl.cpp b/media/libstagefright/MediaPlayerImpl.cpp
index f2e62f5..2d7b62837b 100644
--- a/media/libstagefright/MediaPlayerImpl.cpp
+++ b/media/libstagefright/MediaPlayerImpl.cpp
@@ -34,32 +34,28 @@
#include <media/stagefright/MediaPlayerImpl.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MmapSource.h>
+#include <media/stagefright/OMXCodec.h>
#include <media/stagefright/OMXDecoder.h>
#include <media/stagefright/ShoutcastSource.h>
#include <media/stagefright/TimeSource.h>
#include <ui/PixelFormat.h>
#include <ui/Surface.h>
+#define USE_OMX_CODEC 1
+
namespace android {
MediaPlayerImpl::MediaPlayerImpl(const char *uri)
: mInitCheck(NO_INIT),
- mExtractor(NULL),
mTimeSource(NULL),
- mAudioSource(NULL),
- mAudioDecoder(NULL),
mAudioPlayer(NULL),
- mVideoSource(NULL),
- mVideoDecoder(NULL),
mVideoWidth(0),
mVideoHeight(0),
mVideoPosition(0),
mDuration(0),
mPlaying(false),
mPaused(false),
- mSeeking(false),
- mFrameSize(0),
- mUseSoftwareColorConversion(false) {
+ mSeeking(false) {
LOGI("MediaPlayerImpl(%s)", uri);
DataSource::RegisterDefaultSniffers();
@@ -78,7 +74,7 @@
mVideoDecoder = CameraSource::Create();
#endif
} else {
- DataSource *source = NULL;
+ sp<DataSource> source;
if (!strncasecmp("file://", uri, 7)) {
source = new MmapSource(uri + 7);
} else if (!strncasecmp("http://", uri, 7)) {
@@ -103,22 +99,15 @@
MediaPlayerImpl::MediaPlayerImpl(int fd, int64_t offset, int64_t length)
: mInitCheck(NO_INIT),
- mExtractor(NULL),
mTimeSource(NULL),
- mAudioSource(NULL),
- mAudioDecoder(NULL),
mAudioPlayer(NULL),
- mVideoSource(NULL),
- mVideoDecoder(NULL),
mVideoWidth(0),
mVideoHeight(0),
mVideoPosition(0),
mDuration(0),
mPlaying(false),
mPaused(false),
- mSeeking(false),
- mFrameSize(0),
- mUseSoftwareColorConversion(false) {
+ mSeeking(false) {
LOGI("MediaPlayerImpl(%d, %lld, %lld)", fd, offset, length);
DataSource::RegisterDefaultSniffers();
@@ -148,23 +137,6 @@
stop();
setSurface(NULL);
- LOGV("Shutting down audio.");
- delete mAudioDecoder;
- mAudioDecoder = NULL;
-
- delete mAudioSource;
- mAudioSource = NULL;
-
- LOGV("Shutting down video.");
- delete mVideoDecoder;
- mVideoDecoder = NULL;
-
- delete mVideoSource;
- mVideoSource = NULL;
-
- delete mExtractor;
- mExtractor = NULL;
-
if (mInitCheck == OK) {
mClient.disconnect();
}
@@ -384,12 +356,11 @@
void MediaPlayerImpl::init() {
if (mExtractor != NULL) {
- int num_tracks;
- assert(mExtractor->countTracks(&num_tracks) == OK);
+ size_t num_tracks = mExtractor->countTracks();
mDuration = 0;
- for (int i = 0; i < num_tracks; ++i) {
+ for (size_t i = 0; i < num_tracks; ++i) {
const sp<MetaData> meta = mExtractor->getTrackMetaData(i);
assert(meta != NULL);
@@ -411,10 +382,7 @@
continue;
}
- MediaSource *source;
- if (mExtractor->getTrack(i, &source) != OK) {
- continue;
- }
+ sp<MediaSource> source = mExtractor->getTrack(i);
int32_t units, scale;
if (meta->findInt32(kKeyDuration, &units)
@@ -434,17 +402,22 @@
}
}
-void MediaPlayerImpl::setAudioSource(MediaSource *source) {
+void MediaPlayerImpl::setAudioSource(const sp<MediaSource> &source) {
LOGI("setAudioSource");
mAudioSource = source;
sp<MetaData> meta = source->getFormat();
- mAudioDecoder = OMXDecoder::Create(&mClient, meta);
- mAudioDecoder->setSource(source);
+#if !USE_OMX_CODEC
+ mAudioDecoder = OMXDecoder::Create(
+ &mClient, meta, false /* createEncoder */, source);
+#else
+ mAudioDecoder = OMXCodec::Create(
+ mClient.interface(), meta, false /* createEncoder */, source);
+#endif
}
-void MediaPlayerImpl::setVideoSource(MediaSource *source) {
+void MediaPlayerImpl::setVideoSource(const sp<MediaSource> &source) {
LOGI("setVideoSource");
mVideoSource = source;
@@ -456,8 +429,13 @@
success = meta->findInt32(kKeyHeight, &mVideoHeight);
assert(success);
- mVideoDecoder = OMXDecoder::Create(&mClient, meta);
- ((OMXDecoder *)mVideoDecoder)->setSource(source);
+#if !USE_OMX_CODEC
+ mVideoDecoder = OMXDecoder::Create(
+ &mClient, meta, false /* createEncoder */, source);
+#else
+ mVideoDecoder = OMXCodec::Create(
+ mClient.interface(), meta, false /* createEncoder */, source);
+#endif
if (mISurface.get() != NULL || mSurface.get() != NULL) {
depopulateISurface();
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index 3e7cf3c..5423ffa 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -132,7 +132,7 @@
}
Mutex::Autolock autoLock(mLock);
- ssize_t index = mObservers.indexOfKey(msg.u.buffer_data.node);
+ ssize_t index = mObservers.indexOfKey(msg.node);
if (index >= 0) {
mObservers.editValueAt(index)->postMessage(msg);
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
new file mode 100644
index 0000000..35d599c
--- /dev/null
+++ b/media/libstagefright/OMXCodec.cpp
@@ -0,0 +1,1962 @@
+/*
+ * 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.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "OMXCodec"
+#include <utils/Log.h>
+
+#include <binder/IServiceManager.h>
+#include <binder/MemoryDealer.h>
+#include <binder/ProcessState.h>
+#include <media/IMediaPlayerService.h>
+#include <media/stagefright/ESDS.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaBufferGroup.h>
+#include <media/stagefright/MediaDebug.h>
+#include <media/stagefright/MediaExtractor.h>
+#include <media/stagefright/MetaData.h>
+#include <media/stagefright/MmapSource.h>
+#include <media/stagefright/OMXCodec.h>
+#include <utils/Vector.h>
+
+#include <OMX_Audio.h>
+#include <OMX_Component.h>
+
+namespace android {
+
+struct CodecInfo {
+ const char *mime;
+ const char *codec;
+};
+
+static const CodecInfo kDecoderInfo[] = {
+ { "image/jpeg", "OMX.TI.JPEG.decode" },
+ { "audio/mpeg", "OMX.TI.MP3.decode" },
+ { "audio/mpeg", "OMX.PV.mp3dec" },
+ { "audio/3gpp", "OMX.TI.AMR.decode" },
+ { "audio/3gpp", "OMX.PV.amrdec" },
+ { "audio/mp4a-latm", "OMX.TI.AAC.decode" },
+ { "audio/mp4a-latm", "OMX.PV.aacdec" },
+ { "video/mp4v-es", "OMX.qcom.video.decoder.mpeg4" },
+ { "video/mp4v-es", "OMX.TI.Video.Decoder" },
+ { "video/mp4v-es", "OMX.PV.mpeg4dec" },
+ { "video/3gpp", "OMX.qcom.video.decoder.h263" },
+ { "video/3gpp", "OMX.TI.Video.Decoder" },
+ { "video/3gpp", "OMX.PV.h263dec" },
+ { "video/avc", "OMX.qcom.video.decoder.avc" },
+ { "video/avc", "OMX.TI.Video.Decoder" },
+ { "video/avc", "OMX.PV.avcdec" },
+};
+
+static const CodecInfo kEncoderInfo[] = {
+ { "audio/3gpp", "OMX.TI.AMR.encode" },
+ { "audio/3gpp", "OMX.PV.amrencnb" },
+ { "audio/mp4a-latm", "OMX.TI.AAC.encode" },
+ { "audio/mp4a-latm", "OMX.PV.aacenc" },
+ { "video/mp4v-es", "OMX.qcom.video.encoder.mpeg4" },
+ { "video/mp4v-es", "OMX.TI.Video.encoder" },
+ { "video/mp4v-es", "OMX.PV.mpeg4enc" },
+ { "video/3gpp", "OMX.qcom.video.encoder.h263" },
+ { "video/3gpp", "OMX.TI.Video.encoder" },
+ { "video/3gpp", "OMX.PV.h263enc" },
+ { "video/avc", "OMX.TI.Video.encoder" },
+ { "video/avc", "OMX.PV.avcenc" },
+};
+
+struct OMXCodecObserver : public BnOMXObserver {
+ OMXCodecObserver(const wp<OMXCodec> &target)
+ : mTarget(target) {
+ }
+
+ // from IOMXObserver
+ virtual void on_message(const omx_message &msg) {
+ sp<OMXCodec> codec = mTarget.promote();
+
+ if (codec.get() != NULL) {
+ codec->on_message(msg);
+ }
+ }
+
+protected:
+ virtual ~OMXCodecObserver() {}
+
+private:
+ wp<OMXCodec> mTarget;
+
+ OMXCodecObserver(const OMXCodecObserver &);
+ OMXCodecObserver &operator=(const OMXCodecObserver &);
+};
+
+static const char *GetCodec(const CodecInfo *info, size_t numInfos,
+ const char *mime, int index) {
+ CHECK(index >= 0);
+ for(size_t i = 0; i < numInfos; ++i) {
+ if (!strcasecmp(mime, info[i].mime)) {
+ if (index == 0) {
+ return info[i].codec;
+ }
+
+ --index;
+ }
+ }
+
+ return NULL;
+}
+
+// static
+sp<OMXCodec> OMXCodec::Create(
+ const sp<IOMX> &omx,
+ const sp<MetaData> &meta, bool createEncoder,
+ const sp<MediaSource> &source) {
+ const char *mime;
+ bool success = meta->findCString(kKeyMIMEType, &mime);
+ CHECK(success);
+
+ const char *componentName = NULL;
+ IOMX::node_id node = 0;
+ for (int index = 0;; ++index) {
+ if (createEncoder) {
+ componentName = GetCodec(
+ kEncoderInfo, sizeof(kEncoderInfo) / sizeof(kEncoderInfo[0]),
+ mime, index);
+ } else {
+ componentName = GetCodec(
+ kDecoderInfo, sizeof(kDecoderInfo) / sizeof(kDecoderInfo[0]),
+ mime, index);
+ }
+
+ if (!componentName) {
+ return NULL;
+ }
+
+ LOGV("Attempting to allocate OMX node '%s'", componentName);
+
+ status_t err = omx->allocate_node(componentName, &node);
+ if (err == OK) {
+ break;
+ }
+ }
+
+ uint32_t quirks = 0;
+ if (!strcmp(componentName, "OMX.PV.avcdec")) {
+ quirks |= kWantsRawNALFrames;
+ }
+ if (!strcmp(componentName, "OMX.TI.MP3.decode")) {
+ quirks |= kNeedsFlushBeforeDisable;
+ }
+ if (!strcmp(componentName, "OMX.TI.AAC.decode")) {
+ quirks |= kNeedsFlushBeforeDisable;
+ }
+ if (!strncmp(componentName, "OMX.qcom.video.encoder.", 23)) {
+ quirks |= kRequiresLoadedToIdleAfterAllocation;
+ quirks |= kRequiresAllocateBufferOnInputPorts;
+ }
+
+ sp<OMXCodec> codec = new OMXCodec(
+ omx, node, quirks, createEncoder, mime, componentName,
+ source);
+
+ uint32_t type;
+ const void *data;
+ size_t size;
+ if (meta->findData(kKeyESDS, &type, &data, &size)) {
+ ESDS esds((const char *)data, size);
+ CHECK_EQ(esds.InitCheck(), OK);
+
+ const void *codec_specific_data;
+ size_t codec_specific_data_size;
+ esds.getCodecSpecificInfo(
+ &codec_specific_data, &codec_specific_data_size);
+
+ printf("found codec-specific data of size %d\n",
+ codec_specific_data_size);
+
+ codec->addCodecSpecificData(
+ codec_specific_data, codec_specific_data_size);
+ } else if (meta->findData(kKeyAVCC, &type, &data, &size)) {
+ printf("found avcc of size %d\n", size);
+
+ const uint8_t *ptr = (const uint8_t *)data + 6;
+ size -= 6;
+ while (size >= 2) {
+ size_t length = ptr[0] << 8 | ptr[1];
+
+ ptr += 2;
+ size -= 2;
+
+ // printf("length = %d, size = %d\n", length, size);
+
+ CHECK(size >= length);
+
+ codec->addCodecSpecificData(ptr, length);
+
+ ptr += length;
+ size -= length;
+
+ if (size <= 1) {
+ break;
+ }
+
+ ptr++; // XXX skip trailing 0x01 byte???
+ --size;
+ }
+ }
+
+ if (!strcasecmp("audio/3gpp", mime)) {
+ codec->setAMRFormat();
+ }
+ if (!createEncoder && !strcasecmp("audio/mp4a-latm", mime)) {
+ codec->setAACFormat();
+ }
+ if (!strncasecmp(mime, "video/", 6)) {
+ int32_t width, height;
+ bool success = meta->findInt32(kKeyWidth, &width);
+ success = success && meta->findInt32(kKeyHeight, &height);
+ assert(success);
+
+ if (createEncoder) {
+ codec->setVideoInputFormat(mime, width, height);
+ } else {
+ codec->setVideoOutputFormat(mime, width, height);
+ }
+ }
+ if (!strcasecmp(mime, "image/jpeg")
+ && !strcmp(componentName, "OMX.TI.JPEG.decode")) {
+ OMX_COLOR_FORMATTYPE format =
+ OMX_COLOR_Format32bitARGB8888;
+ // OMX_COLOR_FormatYUV420PackedPlanar;
+ // OMX_COLOR_FormatCbYCrY;
+ // OMX_COLOR_FormatYUV411Planar;
+
+ int32_t width, height;
+ bool success = meta->findInt32(kKeyWidth, &width);
+ success = success && meta->findInt32(kKeyHeight, &height);
+ assert(success);
+
+ codec->setImageOutputFormat(format, width, height);
+ }
+
+ codec->initOutputFormat(meta);
+
+ return codec;
+}
+
+status_t OMXCodec::setVideoPortFormatType(
+ OMX_U32 portIndex,
+ OMX_VIDEO_CODINGTYPE compressionFormat,
+ OMX_COLOR_FORMATTYPE colorFormat) {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE format;
+ format.nSize = sizeof(format);
+ format.nVersion.s.nVersionMajor = 1;
+ format.nVersion.s.nVersionMinor = 1;
+ format.nPortIndex = portIndex;
+ format.nIndex = 0;
+ bool found = false;
+
+ OMX_U32 index = 0;
+ for (;;) {
+ format.nIndex = index;
+ status_t err = mOMX->get_parameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+
+ if (err != OK) {
+ return err;
+ }
+
+ // The following assertion is violated by TI's video decoder.
+ // assert(format.nIndex == index);
+
+#if 1
+ LOGI("portIndex: %ld, index: %ld, eCompressionFormat=%d eColorFormat=%d",
+ portIndex,
+ index, format.eCompressionFormat, format.eColorFormat);
+#endif
+
+ if (!strcmp("OMX.TI.Video.encoder", mComponentName)) {
+ if (portIndex == kPortIndexInput
+ && colorFormat == format.eColorFormat) {
+ // eCompressionFormat does not seem right.
+ found = true;
+ break;
+ }
+ if (portIndex == kPortIndexOutput
+ && compressionFormat == format.eCompressionFormat) {
+ // eColorFormat does not seem right.
+ found = true;
+ break;
+ }
+ }
+
+ if (format.eCompressionFormat == compressionFormat
+ && format.eColorFormat == colorFormat) {
+ found = true;
+ break;
+ }
+
+ ++index;
+ }
+
+ if (!found) {
+ return UNKNOWN_ERROR;
+ }
+
+ LOGI("found a match.");
+ status_t err = mOMX->set_parameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+
+ return err;
+}
+
+void OMXCodec::setVideoInputFormat(
+ const char *mime, OMX_U32 width, OMX_U32 height) {
+ LOGI("setVideoInputFormat width=%ld, height=%ld", width, height);
+
+ OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
+ if (!strcasecmp("video/avc", mime)) {
+ compressionFormat = OMX_VIDEO_CodingAVC;
+ } else if (!strcasecmp("video/mp4v-es", mime)) {
+ compressionFormat = OMX_VIDEO_CodingMPEG4;
+ } else if (!strcasecmp("video/3gpp", mime)) {
+ compressionFormat = OMX_VIDEO_CodingH263;
+ } else {
+ LOGE("Not a supported video mime type: %s", mime);
+ CHECK(!"Should not be here. Not a supported video mime type.");
+ }
+
+ OMX_COLOR_FORMATTYPE colorFormat =
+ 0 ? OMX_COLOR_FormatYCbYCr : OMX_COLOR_FormatCbYCrY;
+
+ if (!strncmp("OMX.qcom.video.encoder.", mComponentName, 23)) {
+ colorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ }
+
+ setVideoPortFormatType(
+ kPortIndexInput, OMX_VIDEO_CodingUnused,
+ colorFormat);
+
+ setVideoPortFormatType(
+ kPortIndexOutput, compressionFormat, OMX_COLOR_FormatUnused);
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
+
+ def.nSize = sizeof(def);
+ def.nVersion.s.nVersionMajor = 1;
+ def.nVersion.s.nVersionMinor = 1;
+ def.nPortIndex = kPortIndexOutput;
+
+ status_t err = mOMX->get_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ CHECK_EQ(err, OK);
+ CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
+
+ video_def->nFrameWidth = width;
+ video_def->nFrameHeight = height;
+
+ video_def->eCompressionFormat = compressionFormat;
+ video_def->eColorFormat = OMX_COLOR_FormatUnused;
+
+ err = mOMX->set_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, OK);
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ def.nSize = sizeof(def);
+ def.nVersion.s.nVersionMajor = 1;
+ def.nVersion.s.nVersionMinor = 1;
+ def.nPortIndex = kPortIndexInput;
+
+ err = mOMX->get_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, OK);
+
+ def.nBufferSize = (width * height * 2); // (width * height * 3) / 2;
+ LOGI("setting nBufferSize = %ld", def.nBufferSize);
+
+ CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
+
+ video_def->nFrameWidth = width;
+ video_def->nFrameHeight = height;
+ video_def->eCompressionFormat = OMX_VIDEO_CodingUnused;
+ video_def->eColorFormat = colorFormat;
+
+ err = mOMX->set_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, OK);
+}
+
+void OMXCodec::setVideoOutputFormat(
+ const char *mime, OMX_U32 width, OMX_U32 height) {
+ LOGI("setVideoOutputFormat width=%ld, height=%ld", width, height);
+
+ // Enabling this code appears to be the right thing(tm), but,...
+ // the TI decoder then loses the ability to output YUV420 and only outputs
+ // YCbYCr (16bit)
+ if (!strcmp("OMX.TI.Video.Decoder", mComponentName)
+ && !strcasecmp("video/avc", mime)) {
+ OMX_PARAM_COMPONENTROLETYPE role;
+ role.nSize = sizeof(role);
+ role.nVersion.s.nVersionMajor = 1;
+ role.nVersion.s.nVersionMinor = 1;
+ strncpy((char *)role.cRole, "video_decoder.avc",
+ OMX_MAX_STRINGNAME_SIZE - 1);
+ role.cRole[OMX_MAX_STRINGNAME_SIZE - 1] = '\0';
+
+ status_t err = mOMX->set_parameter(
+ mNode, OMX_IndexParamStandardComponentRole,
+ &role, sizeof(role));
+ CHECK_EQ(err, OK);
+ }
+
+ OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
+ if (!strcasecmp("video/avc", mime)) {
+ compressionFormat = OMX_VIDEO_CodingAVC;
+ } else if (!strcasecmp("video/mp4v-es", mime)) {
+ compressionFormat = OMX_VIDEO_CodingMPEG4;
+ } else if (!strcasecmp("video/3gpp", mime)) {
+ compressionFormat = OMX_VIDEO_CodingH263;
+ } else {
+ LOGE("Not a supported video mime type: %s", mime);
+ CHECK(!"Should not be here. Not a supported video mime type.");
+ }
+
+ setVideoPortFormatType(
+ kPortIndexInput, compressionFormat, OMX_COLOR_FormatUnused);
+
+#if 1
+ {
+ OMX_VIDEO_PARAM_PORTFORMATTYPE format;
+ format.nSize = sizeof(format);
+ format.nVersion.s.nVersionMajor = 1;
+ format.nVersion.s.nVersionMinor = 1;
+ format.nPortIndex = kPortIndexOutput;
+ format.nIndex = 0;
+
+ status_t err = mOMX->get_parameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+ CHECK_EQ(err, OK);
+ CHECK_EQ(format.eCompressionFormat, OMX_VIDEO_CodingUnused);
+
+ static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
+
+ CHECK(format.eColorFormat == OMX_COLOR_FormatYUV420Planar
+ || format.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar
+ || format.eColorFormat == OMX_COLOR_FormatCbYCrY
+ || format.eColorFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar);
+
+ err = mOMX->set_parameter(
+ mNode, OMX_IndexParamVideoPortFormat,
+ &format, sizeof(format));
+ CHECK_EQ(err, OK);
+ }
+#endif
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
+
+ def.nSize = sizeof(def);
+ def.nVersion.s.nVersionMajor = 1;
+ def.nVersion.s.nVersionMinor = 1;
+ def.nPortIndex = kPortIndexInput;
+
+ status_t err = mOMX->get_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ CHECK_EQ(err, OK);
+
+#if 1
+ // XXX Need a (much) better heuristic to compute input buffer sizes.
+ const size_t X = 64 * 1024;
+ if (def.nBufferSize < X) {
+ def.nBufferSize = X;
+ }
+#endif
+
+ CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
+
+ video_def->nFrameWidth = width;
+ video_def->nFrameHeight = height;
+
+ video_def->eColorFormat = OMX_COLOR_FormatUnused;
+
+ err = mOMX->set_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, OK);
+
+ ////////////////////////////////////////////////////////////////////////////
+
+ def.nSize = sizeof(def);
+ def.nVersion.s.nVersionMajor = 1;
+ def.nVersion.s.nVersionMinor = 1;
+ def.nPortIndex = kPortIndexOutput;
+
+ err = mOMX->get_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, OK);
+ CHECK_EQ(def.eDomain, OMX_PortDomainVideo);
+
+#if 0
+ def.nBufferSize =
+ (((width + 15) & -16) * ((height + 15) & -16) * 3) / 2; // YUV420
+#endif
+
+ video_def->nFrameWidth = width;
+ video_def->nFrameHeight = height;
+
+ err = mOMX->set_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, OK);
+}
+
+
+OMXCodec::OMXCodec(
+ const sp<IOMX> &omx, IOMX::node_id node, uint32_t quirks,
+ bool isEncoder,
+ const char *mime,
+ const char *componentName,
+ const sp<MediaSource> &source)
+ : mOMX(omx),
+ mNode(node),
+ mQuirks(quirks),
+ mIsEncoder(isEncoder),
+ mMIME(strdup(mime)),
+ mComponentName(strdup(componentName)),
+ mSource(source),
+ mCodecSpecificDataIndex(0),
+ mDealer(new MemoryDealer(5 * 1024 * 1024)),
+ mState(LOADED),
+ mSignalledEOS(false),
+ mNoMoreOutputData(false),
+ mSeekTimeUs(-1) {
+ mPortStatus[kPortIndexInput] = ENABLED;
+ mPortStatus[kPortIndexOutput] = ENABLED;
+
+ mObserver = new OMXCodecObserver(this);
+ mOMX->observe_node(mNode, mObserver);
+}
+
+OMXCodec::~OMXCodec() {
+ CHECK_EQ(mState, LOADED);
+
+ status_t err = mOMX->observe_node(mNode, NULL);
+ CHECK_EQ(err, OK);
+
+ err = mOMX->free_node(mNode);
+ CHECK_EQ(err, OK);
+
+ mNode = NULL;
+ setState(DEAD);
+
+ clearCodecSpecificData();
+
+ free(mComponentName);
+ mComponentName = NULL;
+
+ free(mMIME);
+ mMIME = NULL;
+}
+
+status_t OMXCodec::init() {
+ Mutex::Autolock autoLock(mLock);
+
+ CHECK_EQ(mState, LOADED);
+
+ status_t err;
+ if (!(mQuirks & kRequiresLoadedToIdleAfterAllocation)) {
+ err = mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
+ CHECK_EQ(err, OK);
+
+ setState(LOADED_TO_IDLE);
+ }
+
+ err = allocateBuffers();
+ CHECK_EQ(err, OK);
+
+ if (mQuirks & kRequiresLoadedToIdleAfterAllocation) {
+ err = mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
+ CHECK_EQ(err, OK);
+
+ setState(LOADED_TO_IDLE);
+ }
+
+ while (mState != EXECUTING && mState != ERROR) {
+ mAsyncCompletion.wait(mLock);
+ }
+
+ return mState == ERROR ? UNKNOWN_ERROR : OK;
+}
+
+// static
+bool OMXCodec::isIntermediateState(State state) {
+ return state == LOADED_TO_IDLE
+ || state == IDLE_TO_EXECUTING
+ || state == EXECUTING_TO_IDLE
+ || state == IDLE_TO_LOADED
+ || state == RECONFIGURING;
+}
+
+status_t OMXCodec::allocateBuffers() {
+ status_t err = allocateBuffersOnPort(kPortIndexInput);
+
+ if (err != OK) {
+ return err;
+ }
+
+ return allocateBuffersOnPort(kPortIndexOutput);
+}
+
+status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ def.nSize = sizeof(def);
+ def.nVersion.s.nVersionMajor = 1;
+ def.nVersion.s.nVersionMinor = 1;
+ def.nVersion.s.nRevision = 0;
+ def.nVersion.s.nStep = 0;
+ def.nPortIndex = portIndex;
+
+ status_t err = mOMX->get_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+
+ if (err != OK) {
+ return err;
+ }
+
+ for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
+ sp<IMemory> mem = mDealer->allocate(def.nBufferSize);
+ CHECK(mem.get() != NULL);
+
+ IOMX::buffer_id buffer;
+ if (portIndex == kPortIndexInput
+ && (mQuirks & kRequiresAllocateBufferOnInputPorts)) {
+ err = mOMX->allocate_buffer_with_backup(
+ mNode, portIndex, mem, &buffer);
+ } else {
+ err = mOMX->use_buffer(mNode, portIndex, mem, &buffer);
+ }
+
+ if (err != OK) {
+ LOGE("allocate_buffer_with_backup failed");
+ return err;
+ }
+
+ BufferInfo info;
+ info.mBuffer = buffer;
+ info.mOwnedByComponent = false;
+ info.mMem = mem;
+ info.mMediaBuffer = NULL;
+
+ if (portIndex == kPortIndexOutput) {
+ info.mMediaBuffer = new MediaBuffer(mem->pointer(), mem->size());
+ info.mMediaBuffer->setObserver(this);
+ }
+
+ mPortBuffers[portIndex].push(info);
+
+ LOGV("allocated buffer %p on %s port", buffer,
+ portIndex == kPortIndexInput ? "input" : "output");
+ }
+
+ dumpPortStatus(portIndex);
+
+ return OK;
+}
+
+void OMXCodec::on_message(const omx_message &msg) {
+ Mutex::Autolock autoLock(mLock);
+
+ switch (msg.type) {
+ case omx_message::EVENT:
+ {
+ onEvent(
+ msg.u.event_data.event, msg.u.event_data.data1,
+ msg.u.event_data.data2);
+
+ break;
+ }
+
+ case omx_message::EMPTY_BUFFER_DONE:
+ {
+ IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
+
+ LOGV("EMPTY_BUFFER_DONE(buffer: %p)", buffer);
+
+ Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
+ size_t i = 0;
+ while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
+ ++i;
+ }
+
+ CHECK(i < buffers->size());
+ if (!(*buffers)[i].mOwnedByComponent) {
+ LOGW("We already own input buffer %p, yet received "
+ "an EMPTY_BUFFER_DONE.", buffer);
+ }
+
+ buffers->editItemAt(i).mOwnedByComponent = false;
+
+ if (mPortStatus[kPortIndexInput] == DISABLING) {
+ LOGV("Port is disabled, freeing buffer %p", buffer);
+
+ status_t err =
+ mOMX->free_buffer(mNode, kPortIndexInput, buffer);
+ CHECK_EQ(err, OK);
+
+ buffers->removeAt(i);
+ } else if (mPortStatus[kPortIndexInput] != SHUTTING_DOWN) {
+ CHECK_EQ(mPortStatus[kPortIndexInput], ENABLED);
+ drainInputBuffer(&buffers->editItemAt(i));
+ }
+
+ break;
+ }
+
+ case omx_message::FILL_BUFFER_DONE:
+ {
+ IOMX::buffer_id buffer = msg.u.extended_buffer_data.buffer;
+ OMX_U32 flags = msg.u.extended_buffer_data.flags;
+
+ LOGV("FILL_BUFFER_DONE(buffer: %p, size: %ld, flags: 0x%08lx)",
+ buffer,
+ msg.u.extended_buffer_data.range_length,
+ flags);
+
+ LOGV("FILL_BUFFER_DONE(timestamp: %lld us (%.2f secs))",
+ msg.u.extended_buffer_data.timestamp,
+ msg.u.extended_buffer_data.timestamp / 1E6);
+
+ Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
+ size_t i = 0;
+ while (i < buffers->size() && (*buffers)[i].mBuffer != buffer) {
+ ++i;
+ }
+
+ CHECK(i < buffers->size());
+ BufferInfo *info = &buffers->editItemAt(i);
+
+ if (!info->mOwnedByComponent) {
+ LOGW("We already own output buffer %p, yet received "
+ "a FILL_BUFFER_DONE.", buffer);
+ }
+
+ info->mOwnedByComponent = false;
+
+ if (mPortStatus[kPortIndexOutput] == DISABLING) {
+ LOGV("Port is disabled, freeing buffer %p", buffer);
+
+ status_t err =
+ mOMX->free_buffer(mNode, kPortIndexOutput, buffer);
+ CHECK_EQ(err, OK);
+
+ buffers->removeAt(i);
+ } else if (flags & OMX_BUFFERFLAG_EOS) {
+ LOGV("No more output data.");
+ mNoMoreOutputData = true;
+ mBufferFilled.signal();
+ } else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) {
+ CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
+
+ MediaBuffer *buffer = info->mMediaBuffer;
+
+ buffer->set_range(
+ msg.u.extended_buffer_data.range_offset,
+ msg.u.extended_buffer_data.range_length);
+
+ buffer->meta_data()->clear();
+
+ buffer->meta_data()->setInt32(
+ kKeyTimeUnits,
+ (msg.u.extended_buffer_data.timestamp + 500) / 1000);
+
+ buffer->meta_data()->setInt32(
+ kKeyTimeScale, 1000);
+
+ if (msg.u.extended_buffer_data.flags & OMX_BUFFERFLAG_SYNCFRAME) {
+ buffer->meta_data()->setInt32(kKeyIsSyncFrame, true);
+ }
+
+ buffer->meta_data()->setPointer(
+ kKeyPlatformPrivate,
+ msg.u.extended_buffer_data.platform_private);
+
+ buffer->meta_data()->setPointer(
+ kKeyBufferID,
+ msg.u.extended_buffer_data.buffer);
+
+ mFilledBuffers.push_back(i);
+ mBufferFilled.signal();
+ }
+
+ break;
+ }
+
+ default:
+ {
+ CHECK(!"should not be here.");
+ break;
+ }
+ }
+}
+
+void OMXCodec::onEvent(OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
+ switch (event) {
+ case OMX_EventCmdComplete:
+ {
+ onCmdComplete((OMX_COMMANDTYPE)data1, data2);
+ break;
+ }
+
+ case OMX_EventError:
+ {
+ LOGE("ERROR(%ld, %ld)", data1, data2);
+
+ setState(ERROR);
+ break;
+ }
+
+ case OMX_EventPortSettingsChanged:
+ {
+ onPortSettingsChanged(data1);
+ break;
+ }
+
+ case OMX_EventBufferFlag:
+ {
+ LOGV("EVENT_BUFFER_FLAG(%ld)", data1);
+
+ if (data1 == kPortIndexOutput) {
+ mNoMoreOutputData = true;
+ }
+ break;
+ }
+
+ default:
+ {
+ LOGV("EVENT(%d, %ld, %ld)", event, data1, data2);
+ break;
+ }
+ }
+}
+
+void OMXCodec::onCmdComplete(OMX_COMMANDTYPE cmd, OMX_U32 data) {
+ switch (cmd) {
+ case OMX_CommandStateSet:
+ {
+ onStateChange((OMX_STATETYPE)data);
+ break;
+ }
+
+ case OMX_CommandPortDisable:
+ {
+ OMX_U32 portIndex = data;
+ LOGV("PORT_DISABLED(%ld)", portIndex);
+
+ CHECK(mState == EXECUTING || mState == RECONFIGURING);
+ CHECK_EQ(mPortStatus[portIndex], DISABLING);
+ CHECK_EQ(mPortBuffers[portIndex].size(), 0);
+
+ mPortStatus[portIndex] = DISABLED;
+
+ if (mState == RECONFIGURING) {
+ CHECK_EQ(portIndex, kPortIndexOutput);
+
+ enablePortAsync(portIndex);
+
+ status_t err = allocateBuffersOnPort(portIndex);
+ CHECK_EQ(err, OK);
+ }
+ break;
+ }
+
+ case OMX_CommandPortEnable:
+ {
+ OMX_U32 portIndex = data;
+ LOGV("PORT_ENABLED(%ld)", portIndex);
+
+ CHECK(mState == EXECUTING || mState == RECONFIGURING);
+ CHECK_EQ(mPortStatus[portIndex], ENABLING);
+
+ mPortStatus[portIndex] = ENABLED;
+
+ if (mState == RECONFIGURING) {
+ CHECK_EQ(portIndex, kPortIndexOutput);
+
+ setState(EXECUTING);
+
+ fillOutputBuffers();
+ }
+ break;
+ }
+
+ case OMX_CommandFlush:
+ {
+ OMX_U32 portIndex = data;
+
+ LOGV("FLUSH_DONE(%ld)", portIndex);
+
+ CHECK_EQ(mPortStatus[portIndex], SHUTTING_DOWN);
+ mPortStatus[portIndex] = ENABLED;
+
+ CHECK_EQ(countBuffersWeOwn(mPortBuffers[portIndex]),
+ mPortBuffers[portIndex].size());
+
+ if (mState == RECONFIGURING) {
+ CHECK_EQ(portIndex, kPortIndexOutput);
+
+ disablePortAsync(portIndex);
+ } else {
+ // We're flushing both ports in preparation for seeking.
+
+ if (mPortStatus[kPortIndexInput] == ENABLED
+ && mPortStatus[kPortIndexOutput] == ENABLED) {
+ LOGV("Finished flushing both ports, now continuing from"
+ " seek-time.");
+
+ drainInputBuffers();
+ fillOutputBuffers();
+ }
+ }
+
+ break;
+ }
+
+ default:
+ {
+ LOGV("CMD_COMPLETE(%d, %ld)", cmd, data);
+ break;
+ }
+ }
+}
+
+void OMXCodec::onStateChange(OMX_STATETYPE newState) {
+ switch (newState) {
+ case OMX_StateIdle:
+ {
+ LOGV("Now Idle.");
+ if (mState == LOADED_TO_IDLE) {
+ status_t err = mOMX->send_command(
+ mNode, OMX_CommandStateSet, OMX_StateExecuting);
+
+ CHECK_EQ(err, OK);
+
+ setState(IDLE_TO_EXECUTING);
+ } else {
+ CHECK_EQ(mState, EXECUTING_TO_IDLE);
+
+ CHECK_EQ(
+ countBuffersWeOwn(mPortBuffers[kPortIndexInput]),
+ mPortBuffers[kPortIndexInput].size());
+
+ CHECK_EQ(
+ countBuffersWeOwn(mPortBuffers[kPortIndexOutput]),
+ mPortBuffers[kPortIndexOutput].size());
+
+ status_t err = mOMX->send_command(
+ mNode, OMX_CommandStateSet, OMX_StateLoaded);
+
+ CHECK_EQ(err, OK);
+
+ err = freeBuffersOnPort(kPortIndexInput);
+ CHECK_EQ(err, OK);
+
+ err = freeBuffersOnPort(kPortIndexOutput);
+ CHECK_EQ(err, OK);
+
+ mPortStatus[kPortIndexInput] = ENABLED;
+ mPortStatus[kPortIndexOutput] = ENABLED;
+
+ setState(IDLE_TO_LOADED);
+ }
+ break;
+ }
+
+ case OMX_StateExecuting:
+ {
+ CHECK_EQ(mState, IDLE_TO_EXECUTING);
+
+ LOGV("Now Executing.");
+
+ setState(EXECUTING);
+
+ drainInputBuffers();
+ fillOutputBuffers();
+ break;
+ }
+
+ case OMX_StateLoaded:
+ {
+ CHECK_EQ(mState, IDLE_TO_LOADED);
+
+ LOGV("Now Loaded.");
+
+ setState(LOADED);
+ break;
+ }
+
+ default:
+ {
+ CHECK(!"should not be here.");
+ break;
+ }
+ }
+}
+
+// static
+size_t OMXCodec::countBuffersWeOwn(const Vector<BufferInfo> &buffers) {
+ size_t n = 0;
+ for (size_t i = 0; i < buffers.size(); ++i) {
+ if (!buffers[i].mOwnedByComponent) {
+ ++n;
+ }
+ }
+
+ return n;
+}
+
+status_t OMXCodec::freeBuffersOnPort(
+ OMX_U32 portIndex, bool onlyThoseWeOwn) {
+ Vector<BufferInfo> *buffers = &mPortBuffers[portIndex];
+
+ status_t stickyErr = OK;
+
+ for (size_t i = buffers->size(); i-- > 0;) {
+ BufferInfo *info = &buffers->editItemAt(i);
+
+ if (onlyThoseWeOwn && info->mOwnedByComponent) {
+ continue;
+ }
+
+ CHECK_EQ(info->mOwnedByComponent, false);
+
+ status_t err =
+ mOMX->free_buffer(mNode, portIndex, info->mBuffer);
+
+ if (err != OK) {
+ stickyErr = err;
+ }
+
+ if (info->mMediaBuffer != NULL) {
+ info->mMediaBuffer->setObserver(NULL);
+
+ // Make sure nobody but us owns this buffer at this point.
+ CHECK_EQ(info->mMediaBuffer->refcount(), 0);
+
+ info->mMediaBuffer->release();
+ }
+
+ buffers->removeAt(i);
+ }
+
+ CHECK(onlyThoseWeOwn || buffers->isEmpty());
+
+ return stickyErr;
+}
+
+void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) {
+ LOGV("PORT_SETTINGS_CHANGED(%ld)", portIndex);
+
+ CHECK_EQ(mState, EXECUTING);
+ CHECK_EQ(portIndex, kPortIndexOutput);
+ setState(RECONFIGURING);
+
+ if (mQuirks & kNeedsFlushBeforeDisable) {
+ flushPortAsync(portIndex);
+ } else {
+ disablePortAsync(portIndex);
+ }
+}
+
+void OMXCodec::flushPortAsync(OMX_U32 portIndex) {
+ CHECK(mState == EXECUTING || mState == RECONFIGURING);
+
+ CHECK_EQ(mPortStatus[portIndex], ENABLED);
+ mPortStatus[portIndex] = SHUTTING_DOWN;
+
+ status_t err =
+ mOMX->send_command(mNode, OMX_CommandFlush, portIndex);
+ CHECK_EQ(err, OK);
+}
+
+void OMXCodec::disablePortAsync(OMX_U32 portIndex) {
+ CHECK(mState == EXECUTING || mState == RECONFIGURING);
+
+ CHECK_EQ(mPortStatus[portIndex], ENABLED);
+ mPortStatus[portIndex] = DISABLING;
+
+ status_t err =
+ mOMX->send_command(mNode, OMX_CommandPortDisable, portIndex);
+ CHECK_EQ(err, OK);
+
+ freeBuffersOnPort(portIndex, true);
+}
+
+void OMXCodec::enablePortAsync(OMX_U32 portIndex) {
+ CHECK(mState == EXECUTING || mState == RECONFIGURING);
+
+ CHECK_EQ(mPortStatus[portIndex], DISABLED);
+ mPortStatus[portIndex] = ENABLING;
+
+ status_t err =
+ mOMX->send_command(mNode, OMX_CommandPortEnable, portIndex);
+ CHECK_EQ(err, OK);
+}
+
+void OMXCodec::fillOutputBuffers() {
+ CHECK_EQ(mState, EXECUTING);
+
+ Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
+ for (size_t i = 0; i < buffers->size(); ++i) {
+ fillOutputBuffer(&buffers->editItemAt(i));
+ }
+}
+
+void OMXCodec::drainInputBuffers() {
+ CHECK_EQ(mState, EXECUTING);
+
+ Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
+ for (size_t i = 0; i < buffers->size(); ++i) {
+ drainInputBuffer(&buffers->editItemAt(i));
+ }
+}
+
+void OMXCodec::drainInputBuffer(BufferInfo *info) {
+ CHECK_EQ(info->mOwnedByComponent, false);
+
+ if (mSignalledEOS) {
+ return;
+ }
+
+ if (mCodecSpecificDataIndex < mCodecSpecificData.size()) {
+ const CodecSpecificData *specific =
+ mCodecSpecificData[mCodecSpecificDataIndex];
+
+ size_t size = specific->mSize;
+
+ if (!strcasecmp(mMIME, "video/avc")
+ && !(mQuirks & kWantsRawNALFrames)) {
+ static const uint8_t kNALStartCode[4] =
+ { 0x00, 0x00, 0x00, 0x01 };
+
+ CHECK(info->mMem->size() >= specific->mSize + 4);
+
+ size += 4;
+
+ memcpy(info->mMem->pointer(), kNALStartCode, 4);
+ memcpy((uint8_t *)info->mMem->pointer() + 4,
+ specific->mData, specific->mSize);
+ } else {
+ CHECK(info->mMem->size() >= specific->mSize);
+ memcpy(info->mMem->pointer(), specific->mData, specific->mSize);
+ }
+
+ mOMX->empty_buffer(
+ mNode, info->mBuffer, 0, size,
+ OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_CODECCONFIG,
+ 0);
+
+ info->mOwnedByComponent = true;
+
+ ++mCodecSpecificDataIndex;
+ return;
+ }
+
+ MediaBuffer *srcBuffer;
+ status_t err;
+ if (mSeekTimeUs >= 0) {
+ MediaSource::ReadOptions options;
+ options.setSeekTo(mSeekTimeUs);
+ mSeekTimeUs = -1;
+
+ err = mSource->read(&srcBuffer, &options);
+ } else {
+ err = mSource->read(&srcBuffer);
+ }
+
+ OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
+ OMX_TICKS timestamp = 0;
+ size_t srcLength = 0;
+
+ if (err != OK) {
+ LOGV("signalling end of input stream.");
+ flags |= OMX_BUFFERFLAG_EOS;
+
+ mSignalledEOS = true;
+ } else {
+ srcLength = srcBuffer->range_length();
+
+ if (info->mMem->size() < srcLength) {
+ LOGE("info->mMem->size() = %d, srcLength = %d",
+ info->mMem->size(), srcLength);
+ }
+ CHECK(info->mMem->size() >= srcLength);
+ memcpy(info->mMem->pointer(),
+ (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
+ srcLength);
+
+ int32_t units, scale;
+ if (srcBuffer->meta_data()->findInt32(kKeyTimeUnits, &units)
+ && srcBuffer->meta_data()->findInt32(kKeyTimeScale, &scale)) {
+ timestamp = ((OMX_TICKS)units * 1000000) / scale;
+
+ LOGV("Calling empty_buffer on buffer %p (length %d)",
+ info->mBuffer, srcLength);
+ LOGV("Calling empty_buffer with timestamp %lld us (%.2f secs)",
+ timestamp, timestamp / 1E6);
+ }
+ }
+
+ mOMX->empty_buffer(
+ mNode, info->mBuffer, 0, srcLength,
+ flags, timestamp);
+
+ info->mOwnedByComponent = true;
+
+ if (srcBuffer != NULL) {
+ srcBuffer->release();
+ srcBuffer = NULL;
+ }
+}
+
+void OMXCodec::fillOutputBuffer(BufferInfo *info) {
+ CHECK_EQ(info->mOwnedByComponent, false);
+
+ LOGV("Calling fill_buffer on buffer %p", info->mBuffer);
+ mOMX->fill_buffer(mNode, info->mBuffer);
+
+ info->mOwnedByComponent = true;
+}
+
+void OMXCodec::drainInputBuffer(IOMX::buffer_id buffer) {
+ Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
+ for (size_t i = 0; i < buffers->size(); ++i) {
+ if ((*buffers)[i].mBuffer == buffer) {
+ drainInputBuffer(&buffers->editItemAt(i));
+ return;
+ }
+ }
+
+ CHECK(!"should not be here.");
+}
+
+void OMXCodec::fillOutputBuffer(IOMX::buffer_id buffer) {
+ Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
+ for (size_t i = 0; i < buffers->size(); ++i) {
+ if ((*buffers)[i].mBuffer == buffer) {
+ fillOutputBuffer(&buffers->editItemAt(i));
+ return;
+ }
+ }
+
+ CHECK(!"should not be here.");
+}
+
+void OMXCodec::setState(State newState) {
+ mState = newState;
+ mAsyncCompletion.signal();
+
+ // This may cause some spurious wakeups but is necessary to
+ // unblock the reader if we enter ERROR state.
+ mBufferFilled.signal();
+}
+
+void OMXCodec::setAMRFormat() {
+ if (!mIsEncoder) {
+ OMX_AUDIO_PARAM_AMRTYPE def;
+ def.nSize = sizeof(def);
+ def.nVersion.s.nVersionMajor = 1;
+ def.nVersion.s.nVersionMinor = 1;
+ def.nPortIndex = kPortIndexInput;
+
+ status_t err =
+ mOMX->get_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+
+ CHECK_EQ(err, OK);
+
+ def.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
+ def.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0;
+
+ err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAmr, &def, sizeof(def));
+ CHECK_EQ(err, OK);
+ }
+
+ ////////////////////////
+
+ if (mIsEncoder) {
+ sp<MetaData> format = mSource->getFormat();
+ int32_t sampleRate;
+ int32_t numChannels;
+ CHECK(format->findInt32(kKeySampleRate, &sampleRate));
+ CHECK(format->findInt32(kKeyChannelCount, &numChannels));
+
+ OMX_AUDIO_PARAM_PCMMODETYPE pcmParams;
+ pcmParams.nSize = sizeof(pcmParams);
+ pcmParams.nVersion.s.nVersionMajor = 1;
+ pcmParams.nVersion.s.nVersionMinor = 1;
+ pcmParams.nPortIndex = kPortIndexInput;
+
+ status_t err = mOMX->get_parameter(
+ mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+
+ CHECK_EQ(err, OK);
+
+ pcmParams.nChannels = numChannels;
+ pcmParams.eNumData = OMX_NumericalDataSigned;
+ pcmParams.bInterleaved = OMX_TRUE;
+ pcmParams.nBitPerSample = 16;
+ pcmParams.nSamplingRate = sampleRate;
+ pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
+
+ if (numChannels == 1) {
+ pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelCF;
+ } else {
+ CHECK_EQ(numChannels, 2);
+
+ pcmParams.eChannelMapping[0] = OMX_AUDIO_ChannelLF;
+ pcmParams.eChannelMapping[1] = OMX_AUDIO_ChannelRF;
+ }
+
+ err = mOMX->set_parameter(
+ mNode, OMX_IndexParamAudioPcm, &pcmParams, sizeof(pcmParams));
+
+ CHECK_EQ(err, OK);
+ }
+}
+
+void OMXCodec::setAACFormat() {
+ OMX_AUDIO_PARAM_AACPROFILETYPE def;
+ def.nSize = sizeof(def);
+ def.nVersion.s.nVersionMajor = 1;
+ def.nVersion.s.nVersionMinor = 1;
+ def.nPortIndex = kPortIndexInput;
+
+ status_t err =
+ mOMX->get_parameter(mNode, OMX_IndexParamAudioAac, &def, sizeof(def));
+ CHECK_EQ(err, OK);
+
+ def.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
+
+ err = mOMX->set_parameter(mNode, OMX_IndexParamAudioAac, &def, sizeof(def));
+ CHECK_EQ(err, OK);
+}
+
+void OMXCodec::setImageOutputFormat(
+ OMX_COLOR_FORMATTYPE format, OMX_U32 width, OMX_U32 height) {
+ LOGV("setImageOutputFormat(%ld, %ld)", width, height);
+
+#if 0
+ OMX_INDEXTYPE index;
+ status_t err = mOMX->get_extension_index(
+ mNode, "OMX.TI.JPEG.decode.Config.OutputColorFormat", &index);
+ CHECK_EQ(err, OK);
+
+ err = mOMX->set_config(mNode, index, &format, sizeof(format));
+ CHECK_EQ(err, OK);
+#endif
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ def.nSize = sizeof(def);
+ def.nVersion.s.nVersionMajor = 1;
+ def.nVersion.s.nVersionMinor = 1;
+ def.nPortIndex = kPortIndexOutput;
+
+ status_t err = mOMX->get_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, OK);
+
+ CHECK_EQ(def.eDomain, OMX_PortDomainImage);
+
+ OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
+
+ CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
+ imageDef->eColorFormat = format;
+ imageDef->nFrameWidth = width;
+ imageDef->nFrameHeight = height;
+
+ switch (format) {
+ case OMX_COLOR_FormatYUV420PackedPlanar:
+ case OMX_COLOR_FormatYUV411Planar:
+ {
+ def.nBufferSize = (width * height * 3) / 2;
+ break;
+ }
+
+ case OMX_COLOR_FormatCbYCrY:
+ {
+ def.nBufferSize = width * height * 2;
+ break;
+ }
+
+ case OMX_COLOR_Format32bitARGB8888:
+ {
+ def.nBufferSize = width * height * 4;
+ break;
+ }
+
+ default:
+ CHECK(!"Should not be here. Unknown color format.");
+ break;
+ }
+
+ err = mOMX->set_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, OK);
+
+ ////
+
+ def.nPortIndex = kPortIndexInput;
+
+ err = mOMX->get_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, OK);
+
+ CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingJPEG);
+ imageDef->nFrameWidth = width;
+ imageDef->nFrameHeight = height;
+
+ def.nBufferSize = 128 * 1024;
+ def.nBufferCountActual = def.nBufferCountMin;
+
+ err = mOMX->set_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, OK);
+}
+
+void OMXCodec::addCodecSpecificData(const void *data, size_t size) {
+ CodecSpecificData *specific =
+ (CodecSpecificData *)malloc(sizeof(CodecSpecificData) + size - 1);
+
+ specific->mSize = size;
+ memcpy(specific->mData, data, size);
+
+ mCodecSpecificData.push(specific);
+}
+
+void OMXCodec::clearCodecSpecificData() {
+ for (size_t i = 0; i < mCodecSpecificData.size(); ++i) {
+ free(mCodecSpecificData.editItemAt(i));
+ }
+ mCodecSpecificData.clear();
+ mCodecSpecificDataIndex = 0;
+}
+
+status_t OMXCodec::start(MetaData *) {
+ if (mState != LOADED) {
+ return UNKNOWN_ERROR;
+ }
+
+ sp<MetaData> params = new MetaData;
+ if (!strcasecmp(mMIME, "video/avc") && !(mQuirks & kWantsRawNALFrames)) {
+ params->setInt32(kKeyNeedsNALFraming, true);
+ }
+ status_t err = mSource->start(params.get());
+
+ if (err != OK) {
+ return err;
+ }
+
+ mCodecSpecificDataIndex = 0;
+ mSignalledEOS = false;
+ mNoMoreOutputData = false;
+ mSeekTimeUs = -1;
+ mFilledBuffers.clear();
+
+ return init();
+}
+
+status_t OMXCodec::stop() {
+ LOGI("stop");
+
+ Mutex::Autolock autoLock(mLock);
+
+ while (isIntermediateState(mState)) {
+ mAsyncCompletion.wait(mLock);
+ }
+
+ switch (mState) {
+ case LOADED:
+ case ERROR:
+ break;
+
+ case EXECUTING:
+ {
+ setState(EXECUTING_TO_IDLE);
+
+ mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
+ mPortStatus[kPortIndexOutput] = SHUTTING_DOWN;
+
+ status_t err =
+ mOMX->send_command(mNode, OMX_CommandStateSet, OMX_StateIdle);
+ CHECK_EQ(err, OK);
+
+ while (mState != LOADED && mState != ERROR) {
+ mAsyncCompletion.wait(mLock);
+ }
+
+ break;
+ }
+
+ default:
+ {
+ CHECK(!"should not be here.");
+ break;
+ }
+ }
+
+ mSource->stop();
+
+ return OK;
+}
+
+sp<MetaData> OMXCodec::getFormat() {
+ return mOutputFormat;
+}
+
+status_t OMXCodec::read(
+ MediaBuffer **buffer, const ReadOptions *options) {
+ *buffer = NULL;
+
+ Mutex::Autolock autoLock(mLock);
+
+ if (mState != EXECUTING && mState != RECONFIGURING) {
+ return UNKNOWN_ERROR;
+ }
+
+ int64_t seekTimeUs;
+ if (options && options->getSeekTo(&seekTimeUs)) {
+ LOGV("seeking to %lld us (%.2f secs)", seekTimeUs, seekTimeUs / 1E6);
+
+ mSignalledEOS = false;
+ mNoMoreOutputData = false;
+
+ CHECK(seekTimeUs >= 0);
+ mSeekTimeUs = seekTimeUs;
+
+ mFilledBuffers.clear();
+
+ CHECK_EQ(mState, EXECUTING);
+
+ flushPortAsync(kPortIndexInput);
+ flushPortAsync(kPortIndexOutput);
+ }
+
+ while (mState != ERROR && !mNoMoreOutputData && mFilledBuffers.empty()) {
+ mBufferFilled.wait(mLock);
+ }
+
+ if (mState == ERROR) {
+ return UNKNOWN_ERROR;
+ }
+
+ if (mFilledBuffers.empty()) {
+ return ERROR_END_OF_STREAM;
+ }
+
+ size_t index = *mFilledBuffers.begin();
+ mFilledBuffers.erase(mFilledBuffers.begin());
+
+ BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(index);
+ info->mMediaBuffer->add_ref();
+ *buffer = info->mMediaBuffer;
+
+ return OK;
+}
+
+void OMXCodec::signalBufferReturned(MediaBuffer *buffer) {
+ Mutex::Autolock autoLock(mLock);
+
+ Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexOutput];
+ for (size_t i = 0; i < buffers->size(); ++i) {
+ BufferInfo *info = &buffers->editItemAt(i);
+
+ if (info->mMediaBuffer == buffer) {
+ CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
+ fillOutputBuffer(info);
+ return;
+ }
+ }
+
+ CHECK(!"should not be here.");
+}
+
+static const char *imageCompressionFormatString(OMX_IMAGE_CODINGTYPE type) {
+ static const char *kNames[] = {
+ "OMX_IMAGE_CodingUnused",
+ "OMX_IMAGE_CodingAutoDetect",
+ "OMX_IMAGE_CodingJPEG",
+ "OMX_IMAGE_CodingJPEG2K",
+ "OMX_IMAGE_CodingEXIF",
+ "OMX_IMAGE_CodingTIFF",
+ "OMX_IMAGE_CodingGIF",
+ "OMX_IMAGE_CodingPNG",
+ "OMX_IMAGE_CodingLZW",
+ "OMX_IMAGE_CodingBMP",
+ };
+
+ size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
+
+ if (type < 0 || (size_t)type >= numNames) {
+ return "UNKNOWN";
+ } else {
+ return kNames[type];
+ }
+}
+
+static const char *colorFormatString(OMX_COLOR_FORMATTYPE type) {
+ static const char *kNames[] = {
+ "OMX_COLOR_FormatUnused",
+ "OMX_COLOR_FormatMonochrome",
+ "OMX_COLOR_Format8bitRGB332",
+ "OMX_COLOR_Format12bitRGB444",
+ "OMX_COLOR_Format16bitARGB4444",
+ "OMX_COLOR_Format16bitARGB1555",
+ "OMX_COLOR_Format16bitRGB565",
+ "OMX_COLOR_Format16bitBGR565",
+ "OMX_COLOR_Format18bitRGB666",
+ "OMX_COLOR_Format18bitARGB1665",
+ "OMX_COLOR_Format19bitARGB1666",
+ "OMX_COLOR_Format24bitRGB888",
+ "OMX_COLOR_Format24bitBGR888",
+ "OMX_COLOR_Format24bitARGB1887",
+ "OMX_COLOR_Format25bitARGB1888",
+ "OMX_COLOR_Format32bitBGRA8888",
+ "OMX_COLOR_Format32bitARGB8888",
+ "OMX_COLOR_FormatYUV411Planar",
+ "OMX_COLOR_FormatYUV411PackedPlanar",
+ "OMX_COLOR_FormatYUV420Planar",
+ "OMX_COLOR_FormatYUV420PackedPlanar",
+ "OMX_COLOR_FormatYUV420SemiPlanar",
+ "OMX_COLOR_FormatYUV422Planar",
+ "OMX_COLOR_FormatYUV422PackedPlanar",
+ "OMX_COLOR_FormatYUV422SemiPlanar",
+ "OMX_COLOR_FormatYCbYCr",
+ "OMX_COLOR_FormatYCrYCb",
+ "OMX_COLOR_FormatCbYCrY",
+ "OMX_COLOR_FormatCrYCbY",
+ "OMX_COLOR_FormatYUV444Interleaved",
+ "OMX_COLOR_FormatRawBayer8bit",
+ "OMX_COLOR_FormatRawBayer10bit",
+ "OMX_COLOR_FormatRawBayer8bitcompressed",
+ "OMX_COLOR_FormatL2",
+ "OMX_COLOR_FormatL4",
+ "OMX_COLOR_FormatL8",
+ "OMX_COLOR_FormatL16",
+ "OMX_COLOR_FormatL24",
+ "OMX_COLOR_FormatL32",
+ "OMX_COLOR_FormatYUV420PackedSemiPlanar",
+ "OMX_COLOR_FormatYUV422PackedSemiPlanar",
+ "OMX_COLOR_Format18BitBGR666",
+ "OMX_COLOR_Format24BitARGB6666",
+ "OMX_COLOR_Format24BitABGR6666",
+ };
+
+ size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
+
+ static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
+
+ if (type == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
+ return "OMX_QCOM_COLOR_FormatYVU420SemiPlanar";
+ } else if (type < 0 || (size_t)type >= numNames) {
+ return "UNKNOWN";
+ } else {
+ return kNames[type];
+ }
+}
+
+static const char *videoCompressionFormatString(OMX_VIDEO_CODINGTYPE type) {
+ static const char *kNames[] = {
+ "OMX_VIDEO_CodingUnused",
+ "OMX_VIDEO_CodingAutoDetect",
+ "OMX_VIDEO_CodingMPEG2",
+ "OMX_VIDEO_CodingH263",
+ "OMX_VIDEO_CodingMPEG4",
+ "OMX_VIDEO_CodingWMV",
+ "OMX_VIDEO_CodingRV",
+ "OMX_VIDEO_CodingAVC",
+ "OMX_VIDEO_CodingMJPEG",
+ };
+
+ size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
+
+ if (type < 0 || (size_t)type >= numNames) {
+ return "UNKNOWN";
+ } else {
+ return kNames[type];
+ }
+}
+
+static const char *audioCodingTypeString(OMX_AUDIO_CODINGTYPE type) {
+ static const char *kNames[] = {
+ "OMX_AUDIO_CodingUnused",
+ "OMX_AUDIO_CodingAutoDetect",
+ "OMX_AUDIO_CodingPCM",
+ "OMX_AUDIO_CodingADPCM",
+ "OMX_AUDIO_CodingAMR",
+ "OMX_AUDIO_CodingGSMFR",
+ "OMX_AUDIO_CodingGSMEFR",
+ "OMX_AUDIO_CodingGSMHR",
+ "OMX_AUDIO_CodingPDCFR",
+ "OMX_AUDIO_CodingPDCEFR",
+ "OMX_AUDIO_CodingPDCHR",
+ "OMX_AUDIO_CodingTDMAFR",
+ "OMX_AUDIO_CodingTDMAEFR",
+ "OMX_AUDIO_CodingQCELP8",
+ "OMX_AUDIO_CodingQCELP13",
+ "OMX_AUDIO_CodingEVRC",
+ "OMX_AUDIO_CodingSMV",
+ "OMX_AUDIO_CodingG711",
+ "OMX_AUDIO_CodingG723",
+ "OMX_AUDIO_CodingG726",
+ "OMX_AUDIO_CodingG729",
+ "OMX_AUDIO_CodingAAC",
+ "OMX_AUDIO_CodingMP3",
+ "OMX_AUDIO_CodingSBC",
+ "OMX_AUDIO_CodingVORBIS",
+ "OMX_AUDIO_CodingWMA",
+ "OMX_AUDIO_CodingRA",
+ "OMX_AUDIO_CodingMIDI",
+ };
+
+ size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
+
+ if (type < 0 || (size_t)type >= numNames) {
+ return "UNKNOWN";
+ } else {
+ return kNames[type];
+ }
+}
+
+static const char *audioPCMModeString(OMX_AUDIO_PCMMODETYPE type) {
+ static const char *kNames[] = {
+ "OMX_AUDIO_PCMModeLinear",
+ "OMX_AUDIO_PCMModeALaw",
+ "OMX_AUDIO_PCMModeMULaw",
+ };
+
+ size_t numNames = sizeof(kNames) / sizeof(kNames[0]);
+
+ if (type < 0 || (size_t)type >= numNames) {
+ return "UNKNOWN";
+ } else {
+ return kNames[type];
+ }
+}
+
+
+void OMXCodec::dumpPortStatus(OMX_U32 portIndex) {
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ def.nSize = sizeof(def);
+ def.nVersion.s.nVersionMajor = 1;
+ def.nVersion.s.nVersionMinor = 1;
+ def.nPortIndex = portIndex;
+
+ status_t err = mOMX->get_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, OK);
+
+ printf("%s Port = {\n", portIndex == kPortIndexInput ? "Input" : "Output");
+
+ CHECK((portIndex == kPortIndexInput && def.eDir == OMX_DirInput)
+ || (portIndex == kPortIndexOutput && def.eDir == OMX_DirOutput));
+
+ printf(" nBufferCountActual = %ld\n", def.nBufferCountActual);
+ printf(" nBufferCountMin = %ld\n", def.nBufferCountMin);
+ printf(" nBufferSize = %ld\n", def.nBufferSize);
+
+ switch (def.eDomain) {
+ case OMX_PortDomainImage:
+ {
+ const OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
+
+ printf("\n");
+ printf(" // Image\n");
+ printf(" nFrameWidth = %ld\n", imageDef->nFrameWidth);
+ printf(" nFrameHeight = %ld\n", imageDef->nFrameHeight);
+ printf(" nStride = %ld\n", imageDef->nStride);
+
+ printf(" eCompressionFormat = %s\n",
+ imageCompressionFormatString(imageDef->eCompressionFormat));
+
+ printf(" eColorFormat = %s\n",
+ colorFormatString(imageDef->eColorFormat));
+
+ break;
+ }
+
+ case OMX_PortDomainVideo:
+ {
+ OMX_VIDEO_PORTDEFINITIONTYPE *videoDef = &def.format.video;
+
+ printf("\n");
+ printf(" // Video\n");
+ printf(" nFrameWidth = %ld\n", videoDef->nFrameWidth);
+ printf(" nFrameHeight = %ld\n", videoDef->nFrameHeight);
+ printf(" nStride = %ld\n", videoDef->nStride);
+
+ printf(" eCompressionFormat = %s\n",
+ videoCompressionFormatString(videoDef->eCompressionFormat));
+
+ printf(" eColorFormat = %s\n",
+ colorFormatString(videoDef->eColorFormat));
+
+ break;
+ }
+
+ case OMX_PortDomainAudio:
+ {
+ OMX_AUDIO_PORTDEFINITIONTYPE *audioDef = &def.format.audio;
+
+ printf("\n");
+ printf(" // Audio\n");
+ printf(" eEncoding = %s\n",
+ audioCodingTypeString(audioDef->eEncoding));
+
+ if (audioDef->eEncoding == OMX_AUDIO_CodingPCM) {
+ OMX_AUDIO_PARAM_PCMMODETYPE params;
+ params.nSize = sizeof(params);
+ params.nVersion.s.nVersionMajor = 1;
+ params.nVersion.s.nVersionMinor = 1;
+ params.nPortIndex = portIndex;
+
+ err = mOMX->get_parameter(
+ mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
+ CHECK_EQ(err, OK);
+
+ printf(" nSamplingRate = %ld\n", params.nSamplingRate);
+ printf(" nChannels = %ld\n", params.nChannels);
+ printf(" bInterleaved = %d\n", params.bInterleaved);
+ printf(" nBitPerSample = %ld\n", params.nBitPerSample);
+
+ printf(" eNumData = %s\n",
+ params.eNumData == OMX_NumericalDataSigned
+ ? "signed" : "unsigned");
+
+ printf(" ePCMMode = %s\n", audioPCMModeString(params.ePCMMode));
+ }
+
+ break;
+ }
+
+ default:
+ {
+ printf(" // Unknown\n");
+ break;
+ }
+ }
+
+ printf("}\n");
+}
+
+void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
+ mOutputFormat = new MetaData;
+ mOutputFormat->setCString(kKeyDecoderComponent, mComponentName);
+
+ OMX_PARAM_PORTDEFINITIONTYPE def;
+ def.nSize = sizeof(def);
+ def.nVersion.s.nVersionMajor = 1;
+ def.nVersion.s.nVersionMinor = 1;
+ def.nPortIndex = kPortIndexOutput;
+
+ status_t err = mOMX->get_parameter(
+ mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ CHECK_EQ(err, OK);
+
+ switch (def.eDomain) {
+ case OMX_PortDomainImage:
+ {
+ OMX_IMAGE_PORTDEFINITIONTYPE *imageDef = &def.format.image;
+ CHECK_EQ(imageDef->eCompressionFormat, OMX_IMAGE_CodingUnused);
+
+ mOutputFormat->setCString(kKeyMIMEType, "image/raw");
+ mOutputFormat->setInt32(kKeyColorFormat, imageDef->eColorFormat);
+ mOutputFormat->setInt32(kKeyWidth, imageDef->nFrameWidth);
+ mOutputFormat->setInt32(kKeyHeight, imageDef->nFrameHeight);
+ break;
+ }
+
+ case OMX_PortDomainAudio:
+ {
+ OMX_AUDIO_PORTDEFINITIONTYPE *audio_def = &def.format.audio;
+
+ CHECK_EQ(audio_def->eEncoding, OMX_AUDIO_CodingPCM);
+
+ OMX_AUDIO_PARAM_PCMMODETYPE params;
+ params.nSize = sizeof(params);
+ params.nVersion.s.nVersionMajor = 1;
+ params.nVersion.s.nVersionMinor = 1;
+ params.nPortIndex = kPortIndexOutput;
+
+ err = mOMX->get_parameter(
+ mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
+ CHECK_EQ(err, OK);
+
+ CHECK_EQ(params.eNumData, OMX_NumericalDataSigned);
+ CHECK_EQ(params.nBitPerSample, 16);
+ CHECK_EQ(params.ePCMMode, OMX_AUDIO_PCMModeLinear);
+
+ int32_t numChannels, sampleRate;
+ inputFormat->findInt32(kKeyChannelCount, &numChannels);
+ inputFormat->findInt32(kKeySampleRate, &sampleRate);
+
+ mOutputFormat->setCString(kKeyMIMEType, "audio/raw");
+ mOutputFormat->setInt32(kKeyChannelCount, numChannels);
+ mOutputFormat->setInt32(kKeySampleRate, sampleRate);
+ break;
+ }
+
+ case OMX_PortDomainVideo:
+ {
+ OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
+
+ if (video_def->eCompressionFormat == OMX_VIDEO_CodingUnused) {
+ mOutputFormat->setCString(kKeyMIMEType, "video/raw");
+ } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingMPEG4) {
+ mOutputFormat->setCString(kKeyMIMEType, "video/mp4v-es");
+ } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingH263) {
+ mOutputFormat->setCString(kKeyMIMEType, "video/3gpp");
+ } else if (video_def->eCompressionFormat == OMX_VIDEO_CodingAVC) {
+ mOutputFormat->setCString(kKeyMIMEType, "video/avc");
+ } else {
+ CHECK(!"Unknown compression format.");
+ }
+
+ if (!strcmp(mComponentName, "OMX.PV.avcdec")) {
+ // This component appears to be lying to me.
+ mOutputFormat->setInt32(
+ kKeyWidth, (video_def->nFrameWidth + 15) & -16);
+ mOutputFormat->setInt32(
+ kKeyHeight, (video_def->nFrameHeight + 15) & -16);
+ } else {
+ mOutputFormat->setInt32(kKeyWidth, video_def->nFrameWidth);
+ mOutputFormat->setInt32(kKeyHeight, video_def->nFrameHeight);
+ }
+
+ mOutputFormat->setInt32(kKeyColorFormat, video_def->eColorFormat);
+ break;
+ }
+
+ default:
+ {
+ CHECK(!"should not be here, neither audio nor video.");
+ break;
+ }
+ }
+}
+
+} // namespace android
diff --git a/media/libstagefright/OMXDecoder.cpp b/media/libstagefright/OMXDecoder.cpp
index a00872f..94cca43 100644
--- a/media/libstagefright/OMXDecoder.cpp
+++ b/media/libstagefright/OMXDecoder.cpp
@@ -102,9 +102,10 @@
}
// static
-OMXDecoder *OMXDecoder::Create(
+sp<OMXDecoder> OMXDecoder::Create(
OMXClient *client, const sp<MetaData> &meta,
- bool createEncoder) {
+ bool createEncoder,
+ const sp<MediaSource> &source) {
const char *mime;
bool success = meta->findCString(kKeyMIMEType, &mime);
assert(success);
@@ -158,8 +159,9 @@
quirks |= kRequiresLoadedToIdleAfterAllocation;
}
- OMXDecoder *decoder = new OMXDecoder(
- client, node, mime, codec, createEncoder, quirks);
+ sp<OMXDecoder> decoder = new OMXDecoder(
+ client, node, mime, codec, createEncoder, quirks,
+ source);
uint32_t type;
const void *data;
@@ -213,7 +215,8 @@
OMXDecoder::OMXDecoder(OMXClient *client, IOMX::node_id node,
const char *mime, const char *codec,
bool is_encoder,
- uint32_t quirks)
+ uint32_t quirks,
+ const sp<MediaSource> &source)
: mClient(client),
mOMX(mClient->interface()),
mNode(node),
@@ -223,7 +226,7 @@
mIsAVC(!strcasecmp(mime, "video/avc")),
mIsEncoder(is_encoder),
mQuirks(quirks),
- mSource(NULL),
+ mSource(source),
mCodecSpecificDataIterator(mCodecSpecificData.begin()),
mState(OMX_StateLoaded),
mPortStatusMask(kPortStatusActive << 2 | kPortStatusActive),
@@ -237,6 +240,8 @@
mBuffers.push(); // input buffers
mBuffers.push(); // output buffers
+
+ setup();
}
OMXDecoder::~OMXDecoder() {
@@ -263,15 +268,6 @@
mComponentName = NULL;
}
-void OMXDecoder::setSource(MediaSource *source) {
- Mutex::Autolock autoLock(mLock);
-
- assert(mSource == NULL);
-
- mSource = source;
- setup();
-}
-
status_t OMXDecoder::start(MetaData *) {
assert(!mStarted);
@@ -580,6 +576,10 @@
OMX_COLOR_FORMATTYPE colorFormat =
0 ? OMX_COLOR_FormatYCbYCr : OMX_COLOR_FormatCbYCrY;
+ if (!strncmp("OMX.qcom.video.encoder.", mComponentName, 23)) {
+ colorFormat = OMX_COLOR_FormatYUV420SemiPlanar;
+ }
+
setVideoPortFormatType(
kPortIndexInput, OMX_VIDEO_CodingUnused,
colorFormat);
@@ -1621,7 +1621,7 @@
void OMXDecoder::postEmptyBufferDone(IOMX::buffer_id buffer) {
omx_message msg;
msg.type = omx_message::EMPTY_BUFFER_DONE;
- msg.u.buffer_data.node = mNode;
+ msg.node = mNode;
msg.u.buffer_data.buffer = buffer;
postMessage(msg);
}
@@ -1629,7 +1629,7 @@
void OMXDecoder::postInitialFillBuffer(IOMX::buffer_id buffer) {
omx_message msg;
msg.type = omx_message::INITIAL_FILL_BUFFER;
- msg.u.buffer_data.node = mNode;
+ msg.node = mNode;
msg.u.buffer_data.buffer = buffer;
postMessage(msg);
}
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index 8f1fa67..75bfde3 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -31,7 +31,7 @@
static const uint32_t kSampleSizeType32 = FOURCC('s', 't', 's', 'z');
static const uint32_t kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');
-SampleTable::SampleTable(DataSource *source)
+SampleTable::SampleTable(const sp<DataSource> &source)
: mDataSource(source),
mChunkOffsetOffset(-1),
mChunkOffsetType(0),
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index d44e3a3..39fa27e 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -75,6 +75,102 @@
NodeMeta &operator=(const NodeMeta &);
};
+////////////////////////////////////////////////////////////////////////////////
+
+struct OMX::CallbackDispatcher : public RefBase {
+ CallbackDispatcher();
+
+ void post(const omx_message &msg);
+
+protected:
+ virtual ~CallbackDispatcher();
+
+private:
+ Mutex mLock;
+ bool mDone;
+ Condition mQueueChanged;
+ List<omx_message> mQueue;
+
+ pthread_t mThread;
+
+ void dispatch(const omx_message &msg);
+
+ static void *ThreadWrapper(void *me);
+ void threadEntry();
+
+ CallbackDispatcher(const CallbackDispatcher &);
+ CallbackDispatcher &operator=(const CallbackDispatcher &);
+};
+
+OMX::CallbackDispatcher::CallbackDispatcher()
+ : mDone(false) {
+ pthread_attr_t attr;
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+ pthread_create(&mThread, &attr, ThreadWrapper, this);
+
+ pthread_attr_destroy(&attr);
+}
+
+OMX::CallbackDispatcher::~CallbackDispatcher() {
+ {
+ Mutex::Autolock autoLock(mLock);
+
+ mDone = true;
+ mQueueChanged.signal();
+ }
+
+ void *dummy;
+ pthread_join(mThread, &dummy);
+}
+
+void OMX::CallbackDispatcher::post(const omx_message &msg) {
+ Mutex::Autolock autoLock(mLock);
+ mQueue.push_back(msg);
+ mQueueChanged.signal();
+}
+
+void OMX::CallbackDispatcher::dispatch(const omx_message &msg) {
+ NodeMeta *meta = static_cast<NodeMeta *>(msg.node);
+
+ sp<IOMXObserver> observer = meta->observer();
+ if (observer.get() != NULL) {
+ observer->on_message(msg);
+ }
+}
+
+// static
+void *OMX::CallbackDispatcher::ThreadWrapper(void *me) {
+ static_cast<CallbackDispatcher *>(me)->threadEntry();
+
+ return NULL;
+}
+
+void OMX::CallbackDispatcher::threadEntry() {
+ for (;;) {
+ omx_message msg;
+
+ {
+ Mutex::Autolock autoLock(mLock);
+ while (!mDone && mQueue.empty()) {
+ mQueueChanged.wait(mLock);
+ }
+
+ if (mDone) {
+ break;
+ }
+
+ msg = *mQueue.begin();
+ mQueue.erase(mQueue.begin());
+ }
+
+ dispatch(msg);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
class BufferMeta {
public:
BufferMeta(OMX *owner, const sp<IMemory> &mem, bool is_backup = false)
@@ -154,7 +250,8 @@
return meta->owner()->OnFillBufferDone(meta, pBuffer);
}
-OMX::OMX() {
+OMX::OMX()
+ : mDispatcher(new CallbackDispatcher) {
}
status_t OMX::list_nodes(List<String8> *list) {
@@ -249,6 +346,29 @@
return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
}
+status_t OMX::get_config(
+ node_id node, OMX_INDEXTYPE index,
+ void *params, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ NodeMeta *meta = static_cast<NodeMeta *>(node);
+ OMX_ERRORTYPE err = OMX_GetConfig(meta->handle(), index, params);
+
+ return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
+}
+
+status_t OMX::set_config(
+ node_id node, OMX_INDEXTYPE index,
+ const void *params, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ NodeMeta *meta = static_cast<NodeMeta *>(node);
+ OMX_ERRORTYPE err =
+ OMX_SetConfig(meta->handle(), index, const_cast<void *>(params));
+
+ return (err != OMX_ErrorNone) ? UNKNOWN_ERROR : OK;
+}
+
status_t OMX::use_buffer(
node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
buffer_id *buffer) {
@@ -357,15 +477,12 @@
omx_message msg;
msg.type = omx_message::EVENT;
- msg.u.event_data.node = meta;
+ msg.node = meta;
msg.u.event_data.event = eEvent;
msg.u.event_data.data1 = nData1;
msg.u.event_data.data2 = nData2;
- sp<IOMXObserver> observer = meta->observer();
- if (observer.get() != NULL) {
- observer->on_message(msg);
- }
+ mDispatcher->post(msg);
return OMX_ErrorNone;
}
@@ -376,13 +493,10 @@
omx_message msg;
msg.type = omx_message::EMPTY_BUFFER_DONE;
- msg.u.buffer_data.node = meta;
+ msg.node = meta;
msg.u.buffer_data.buffer = pBuffer;
- sp<IOMXObserver> observer = meta->observer();
- if (observer.get() != NULL) {
- observer->on_message(msg);
- }
+ mDispatcher->post(msg);
return OMX_ErrorNone;
}
@@ -395,7 +509,7 @@
omx_message msg;
msg.type = omx_message::FILL_BUFFER_DONE;
- msg.u.extended_buffer_data.node = meta;
+ msg.node = meta;
msg.u.extended_buffer_data.buffer = pBuffer;
msg.u.extended_buffer_data.range_offset = pBuffer->nOffset;
msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen;
@@ -403,10 +517,7 @@
msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp;
msg.u.extended_buffer_data.platform_private = pBuffer->pPlatformPrivate;
- sp<IOMXObserver> observer = meta->observer();
- if (observer.get() != NULL) {
- observer->on_message(msg);
- }
+ mDispatcher->post(msg);
return OMX_ErrorNone;
}
@@ -455,6 +566,20 @@
assert(err == OMX_ErrorNone);
}
+status_t OMX::get_extension_index(
+ node_id node,
+ const char *parameter_name,
+ OMX_INDEXTYPE *index) {
+ NodeMeta *node_meta = static_cast<NodeMeta *>(node);
+
+ OMX_ERRORTYPE err =
+ OMX_GetExtensionIndex(
+ node_meta->handle(),
+ const_cast<char *>(parameter_name), index);
+
+ return err == OMX_ErrorNone ? OK : UNKNOWN_ERROR;
+}
+
////////////////////////////////////////////////////////////////////////////////
sp<IOMXRenderer> OMX::createRenderer(
diff --git a/media/libstagefright/omx/OMX.h b/media/libstagefright/omx/OMX.h
index 8ac311c..6325f79 100644
--- a/media/libstagefright/omx/OMX.h
+++ b/media/libstagefright/omx/OMX.h
@@ -44,6 +44,14 @@
node_id node, OMX_INDEXTYPE index,
const void *params, size_t size);
+ virtual status_t get_config(
+ node_id node, OMX_INDEXTYPE index,
+ void *params, size_t size);
+
+ virtual status_t set_config(
+ node_id node, OMX_INDEXTYPE index,
+ const void *params, size_t size);
+
virtual status_t use_buffer(
node_id node, OMX_U32 port_index, const sp<IMemory> ¶ms,
buffer_id *buffer);
@@ -70,6 +78,11 @@
OMX_U32 range_offset, OMX_U32 range_length,
OMX_U32 flags, OMX_TICKS timestamp);
+ virtual status_t get_extension_index(
+ node_id node,
+ const char *parameter_name,
+ OMX_INDEXTYPE *index);
+
virtual sp<IOMXRenderer> createRenderer(
const sp<ISurface> &surface,
const char *componentName,
@@ -82,6 +95,9 @@
Mutex mLock;
+ struct CallbackDispatcher;
+ sp<CallbackDispatcher> mDispatcher;
+
static OMX_ERRORTYPE OnEvent(
OMX_IN OMX_HANDLETYPE hComponent,
OMX_IN OMX_PTR pAppData,
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
index e76967d..3f2bc39 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
@@ -372,81 +372,81 @@
public static final String META_DATA_MP3 [][] = {
{"/sdcard/media_api/metaDataTestMedias/MP3/ID3V1_ID3V2.mp3", "1/10", "ID3V2.3 Album", "ID3V2.3 Artist",
"ID3V2.3 Lyricist", "ID3V2.3 Composer", null, "Blues",
- "ID3V2.3 Title", "1234", "295", "1"},
+ "ID3V2.3 Title", "1234", "295", "1", null},
{"/sdcard/media_api/metaDataTestMedias/MP3/ID3V2.mp3", "1/10", "ID3V2.3 Album", "ID3V2.3 Artist",
"ID3V2.3 Lyricist", "ID3V2.3 Composer", null, "Blues",
- "ID3V2.3 Title", "1234", "287", "1"},
+ "ID3V2.3 Title", "1234", "287", "1", null},
{"/sdcard/media_api/metaDataTestMedias/MP3/ID3V1.mp3", "1", "test ID3V1 Album", "test ID3V1 Artist",
- null, null, null, "255", "test ID3V1 Title", "1234", "231332", "1"},
+ null, null, null, "255", "test ID3V1 Title", "1234", "231332", "1", null},
{"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V1.mp3" , null, null, null,
- null, null, null, null, null, null, "231330", "1"},
+ null, null, null, null, null, null, "231330", "1", null},
//The corrupted TALB field in id3v2 would not switch to id3v1 tag automatically
{"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TALB.mp3", "01", null, "ID3V2.3 Artist",
"ID3V2.3 Lyricist", "ID3V2.3 Composer", null,
- "Blues", "ID3V2.3 Title", "1234", "295", "1"},
+ "Blues", "ID3V2.3 Title", "1234", "295", "1", null},
{"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TCOM.mp3", "01", "ID3V2.3 Album",
"ID3V2.3 Artist", "ID3V2.3 Lyricist", null, null,
- "Blues", "ID3V2.3 Title", "1234", "295", "1"},
+ "Blues", "ID3V2.3 Title", "1234", "295", "1", null},
{"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TCOM_2.mp3", "01", "ID3V2.3 Album",
- "ID3V2.3 Artist", null, null, null, "Blues", "ID3V2.3 Title", "1234", "295", "1"},
+ "ID3V2.3 Artist", null, null, null, "Blues", "ID3V2.3 Title", "1234", "295", "1", null},
{"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TRCK.mp3", "dd", "ID3V2.3 Album",
"ID3V2.3 Artist", "ID3V2.3 Lyricist", "ID3V2.3 Composer", null,
- "Blues", "ID3V2.3 Title", "1234", "295", "1"},
+ "Blues", "ID3V2.3 Title", "1234", "295", "1", null},
{"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TRCK_2.mp3", "01", "ID3V2.3 Album",
- "ID3V2.3 Artist", null, null, null, "255", "ID3V2.3 Title", "1234", "295", "1"},
+ "ID3V2.3 Artist", null, null, null, "255", "ID3V2.3 Title", "1234", "295", "1", null},
{"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TYER.mp3", "01", "ID3V2.3 Album",
- "ID3V2.3 Artist", null, null, null, null, "ID3V2.3 Title", "9999", "295", "1"},
+ "ID3V2.3 Artist", null, null, null, null, "ID3V2.3 Title", "9999", "295", "1", null},
{"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TYER_2.mp3", "01", "ID3V2.3 Album",
"ID3V2.3 Artist", "ID3V2.3 Lyricist", "ID3V2.3 Composer", null,
- "Blues", "ID3V2.3 Title", null, "295", "1"},
+ "Blues", "ID3V2.3 Title", null, "295", "1", null},
{"/sdcard/media_api/metaDataTestMedias/MP3/Corrupted_ID3V2_TIT.mp3", null, null, null,
- null, null, null, null, null, null, "295", "1"}
+ null, null, null, null, null, null, "295", "1", null}
};
public static final String META_DATA_OTHERS [][] = {
{"/sdcard/media_api/metaDataTestMedias/3GP/cat.3gp", null, null, null,
null, null, "20080309T002415.000Z", null,
- null, null, "1404928", "2"},
+ null, null, "1404928", "2", null},
{"/sdcard/media_api/metaDataTestMedias/AMR/AMR_NB.amr", null, null, null,
null, null, null, null,
- null, null, "126540", "1"},
+ null, null, "126540", "1", null},
{"/sdcard/media_api/metaDataTestMedias/AMRWB/AMR_WB.amr", null, null, null,
null, null, null, null,
- null, null, "231180", "1"},
- {"/sdcard/media_api/metaDataTestMedias/M4A/Jaws Of Life_ver1.m4a", null, "Suspended Animation",
+ null, null, "231180", "1", null},
+ {"/sdcard/media_api/metaDataTestMedias/M4A/Jaws Of Life_ver1.m4a", "1/8", "Suspended Animation",
"John Petrucci", null, null, "20070510T125223.000Z",
- null, null, "2005", "231180", "1"},
+ "13", "Jaws Of Life", "2005", "19815424", "1", "m4a composer"},
{"/sdcard/media_api/metaDataTestMedias/M4V/sample_iPod.m4v", null, null,
null, null, null, "20051220T202015.000Z",
- null, null, null, "3771392", "2"},
+ null, null, null, "3771392", "2", null},
{"/sdcard/media_api/metaDataTestMedias/MIDI/MIDI.mid", null, "Suspended Animation",
"John Petrucci", null, null, "20070510T125223.000Z",
- null, null, "2005", "231180", "1"},
- {"/sdcard/media_api/metaDataTestMedias/MP4/kung_fu_panda_h264.mp4", null, "mp4 album Kung Fu Panda",
+ null, null, "2005", "231180", "1", null},
+ {"/sdcard/media_api/metaDataTestMedias/MP4/kung_fu_panda_h264.mp4", "2/0", "mp4 album Kung Fu Panda",
"mp4 artist Kung Fu Panda", null, null, "20080517T091451.000Z",
- "41", "Kung Fu Panda", "2008", "5667840", "2"},
+ "41", "Kung Fu Panda", "2008", "5667840", "2", "mp4 composer"},
{"/sdcard/media_api/metaDataTestMedias/OGG/Ring_Classic_02.ogg", null, "Suspended Animation",
"John Petrucci", null, null, "20070510T125223.000Z",
- null, null, "2005", "231180", "1"},
+ null, null, "2005", "231180", "1", null},
{"/sdcard/media_api/metaDataTestMedias/OGG/When You Say Nothing At All.ogg",
null, "Suspended Animation", "John Petrucci",
- null, null, "20070510T125223.000Z", null, null, "2005", "231180", "1"},
+ null, null, "20070510T125223.000Z", null, null, "2005", "231180", "1", null},
{"/sdcard/media_api/metaDataTestMedias/WAV/Im With You.wav", null, null,
null, null, null, null,
- null, null, null, "224000", "1"},
+ null, null, null, "224000", "1", null},
{"/sdcard/media_api/metaDataTestMedias/WMA/WMA9.wma", "6", "Ten Songs in the Key of Betrayal",
"Alien Crime Syndicate", "Alien Crime Syndicate",
"wma 9 Composer", "20040521T175729.483Z",
- "Rock", "Run for the Money", "2004", "134479", "1"},
+ "Rock", "Run for the Money", "2004", "134479", "1", null},
{"/sdcard/media_api/metaDataTestMedias/WMA/WMA10.wma", "09", "wma 10 Album",
"wma 10 Album Artist", "wma 10 Artist", "wma 10 Composer", "20070705T063625.097Z",
- "Acid Jazz", "wma 10 Title", "2010", "126574", "1"},
+ "Acid Jazz", "wma 10 Title", "2010", "126574", "1", null},
{"/sdcard/media_api/metaDataTestMedias/WMV/bugs.wmv", "8", "wmv 9 Album",
null, "wmv 9 Artist ", null, "20051122T155247.540Z",
- null, "Looney Tunes - Hare-Breadth Hurry", "2005", "193482", "2"},
+ null, "Looney Tunes - Hare-Breadth Hurry", "2005", "193482", "2", null},
{"/sdcard/media_api/metaDataTestMedias/WMV/clips_ver7.wmv", "50", "wmv 7 Album",
null, "Hallau Shoots & Company", null, "20020226T170045.891Z",
- null, "CODEC Shootout", "1986", "43709", "2"}
+ null, "CODEC Shootout", "1986", "43709", "2", null}
};
//output recorded video
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java
index 3715913..1bf4958 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMetadataTest.java
@@ -36,7 +36,7 @@
FILE_PATH,CD_TRACK, ALBUM,
ARTIST, AUTHOR, COMPOSER,
DATE, GENRE, TITLE,
- YEAR, DURATION, NUM_TRACKS
+ YEAR, DURATION, NUM_TRACKS, WRITER
}
public static enum MP3_TEST_FILE{
@@ -130,8 +130,6 @@
validateMetatData(non_mp3_test_file.AMRWB.ordinal(), MediaNames.META_DATA_OTHERS);
}
- //Bug# 1440173 - skip this test case now
- @Suppress
@MediumTest
public static void testM4A1_Metadata() throws Exception {
validateMetatData(non_mp3_test_file.M4A1.ordinal(), MediaNames.META_DATA_OTHERS);
@@ -254,6 +252,10 @@
Log.v(TAG, "Track : "+ value);
assertEquals(TAG,meta_data_file[fileIndex][meta.NUM_TRACKS.ordinal()], value);
+ value = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_WRITER);
+ Log.v(TAG, "Writer : "+ value);
+ assertEquals(TAG,meta_data_file[fileIndex][meta.WRITER.ordinal()], value);
+
retriever.release();
}
}
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index ccb27cc..132473a3 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -204,7 +204,6 @@
// underlying surface is created and destroyed
SurfaceHolder holder = getHolder();
holder.addCallback(this);
- holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
}
/**
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 64b82eb..03e764c 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -50,7 +50,7 @@
#define VERSION_MAJOR 1
#define VERSION_MINOR 4
static char const * const gVendorString = "Android";
-static char const * const gVersionString = "1.31 Android META-EGL";
+static char const * const gVersionString = "1.4 Android META-EGL";
static char const * const gClientApiString = "OpenGL ES";
static char const * const gExtensionString =
"EGL_KHR_image "
@@ -326,32 +326,6 @@
// ----------------------------------------------------------------------------
-/*
- * To "loose" the GPU, use something like
- * gEGLImpl[IMPL_HARDWARE].hooks = &gHooks[IMPL_CONTEXT_LOST];
- *
- */
-
-static int gl_context_lost() {
- setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]);
- return 0;
-}
-static int egl_context_lost() {
- setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]);
- return EGL_FALSE;
-}
-static EGLBoolean egl_context_lost_swap_buffers(void*, void*) {
- usleep(100000); // don't use all the CPU
- setGlThreadSpecific(&gHooks[IMPL_CONTEXT_LOST]);
- return EGL_FALSE;
-}
-static GLint egl_context_lost_get_error() {
- return EGL_CONTEXT_LOST;
-}
-static int ext_context_lost() {
- return 0;
-}
-
static void gl_no_context() {
tls_t* tls = getTLS();
if (tls->logCallWithNoContext == EGL_TRUE) {
@@ -471,87 +445,82 @@
return i->images[c->impl];
}
+// ----------------------------------------------------------------------------
-EGLDisplay egl_init_displays(NativeDisplayType display)
+// this mutex protects:
+// d->dpys[]
+// egl_init_drivers_locked()
+//
+static pthread_mutex_t gInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
+
+EGLBoolean egl_init_drivers_locked()
{
if (sEarlyInitState) {
- return EGL_NO_DISPLAY;
+ // initialized by static ctor. should be set here.
+ return EGL_FALSE;
}
- uint32_t index = uint32_t(display);
- if (index >= NUM_DISPLAYS) {
- return EGL_NO_DISPLAY;
- }
-
- EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
- egl_display_t* d = &gDisplay[index];
-
// get our driver loader
- Loader& loader(Loader::getInstance());
+ Loader& loader(Loader::getInstance());
- // dynamically load all our EGL implementations for that display
- // and call into the real eglGetGisplay()
- egl_connection_t* cnx = &gEGLImpl[IMPL_SOFTWARE];
+ // dynamically load all our EGL implementations for all displays
+ // and retrieve the corresponding EGLDisplay
+ // if that fails, don't use this driver.
+ // TODO: currently we only deal with EGL_DEFAULT_DISPLAY
+ egl_connection_t* cnx;
+ egl_display_t* d = &gDisplay[0];
+
+ cnx = &gEGLImpl[IMPL_SOFTWARE];
if (cnx->dso == 0) {
cnx->hooks = &gHooks[IMPL_SOFTWARE];
- cnx->dso = loader.open(display, 0, cnx->hooks);
- }
- if (cnx->dso && d->dpys[IMPL_SOFTWARE]==EGL_NO_DISPLAY) {
- d->dpys[IMPL_SOFTWARE] = cnx->hooks->egl.eglGetDisplay(display);
- LOGE_IF(d->dpys[IMPL_SOFTWARE]==EGL_NO_DISPLAY,
- "No EGLDisplay for software EGL!");
+ cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx->hooks);
+ if (cnx->dso) {
+ EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
+ d->dpys[IMPL_SOFTWARE] = dpy;
+ if (dpy == EGL_NO_DISPLAY) {
+ loader.close(cnx->dso);
+ cnx->dso = NULL;
+ }
+ }
}
cnx = &gEGLImpl[IMPL_HARDWARE];
- if (cnx->dso == 0 && cnx->unavailable == 0) {
+ if (cnx->dso == 0) {
char value[PROPERTY_VALUE_MAX];
property_get("debug.egl.hw", value, "1");
if (atoi(value) != 0) {
cnx->hooks = &gHooks[IMPL_HARDWARE];
- cnx->dso = loader.open(display, 1, cnx->hooks);
+ cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx->hooks);
+ if (cnx->dso) {
+ EGLDisplay dpy = cnx->hooks->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
+ d->dpys[IMPL_HARDWARE] = dpy;
+ if (dpy == EGL_NO_DISPLAY) {
+ loader.close(cnx->dso);
+ cnx->dso = NULL;
+ }
+ }
} else {
LOGD("3D hardware acceleration is disabled");
}
}
- if (cnx->dso && d->dpys[IMPL_HARDWARE]==EGL_NO_DISPLAY) {
- android_memset32(
- (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].gl,
- (uint32_t)((void*)gl_context_lost),
- sizeof(gHooks[IMPL_CONTEXT_LOST].gl));
- android_memset32(
- (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].egl,
- (uint32_t)((void*)egl_context_lost),
- sizeof(gHooks[IMPL_CONTEXT_LOST].egl));
- android_memset32(
- (uint32_t*)(void*)&gHooks[IMPL_CONTEXT_LOST].ext,
- (uint32_t)((void*)ext_context_lost),
- sizeof(gHooks[IMPL_CONTEXT_LOST].ext));
-
- gHooks[IMPL_CONTEXT_LOST].egl.eglSwapBuffers =
- egl_context_lost_swap_buffers;
-
- gHooks[IMPL_CONTEXT_LOST].egl.eglGetError =
- egl_context_lost_get_error;
-
- gHooks[IMPL_CONTEXT_LOST].egl.eglTerminate =
- gHooks[IMPL_HARDWARE].egl.eglTerminate;
-
- d->dpys[IMPL_HARDWARE] = cnx->hooks->egl.eglGetDisplay(display);
- if (d->dpys[IMPL_HARDWARE] == EGL_NO_DISPLAY) {
- LOGE("h/w accelerated eglGetDisplay() failed (%s)",
- egl_strerror(cnx->hooks->egl.eglGetError()));
-
- loader.close(cnx->dso);
- cnx->dso = 0;
- // in case of failure, we want to make sure we don't try again
- // as it's expensive.
- cnx->unavailable = 1;
- }
+
+ if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) {
+ return EGL_FALSE;
}
- return dpy;
+ return EGL_TRUE;
}
+EGLBoolean egl_init_drivers()
+{
+ EGLBoolean res;
+ pthread_mutex_lock(&gInitDriverMutex);
+ res = egl_init_drivers_locked();
+ pthread_mutex_unlock(&gInitDriverMutex);
+ return res;
+}
// ----------------------------------------------------------------------------
}; // namespace android
@@ -561,7 +530,17 @@
EGLDisplay eglGetDisplay(NativeDisplayType display)
{
- return egl_init_displays(display);
+ uint32_t index = uint32_t(display);
+ if (index >= NUM_DISPLAYS) {
+ return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+ }
+
+ if (egl_init_drivers() == EGL_FALSE) {
+ return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
+ }
+
+ EGLDisplay dpy = EGLDisplay(uintptr_t(display) + 1LU);
+ return dpy;
}
// ----------------------------------------------------------------------------
@@ -648,31 +627,25 @@
EGLBoolean eglTerminate(EGLDisplay dpy)
{
+ // NOTE: don't unload the drivers b/c some APIs can be called
+ // after eglTerminate() has been called. eglTerminate() only
+ // terminates an EGLDisplay, not a EGL itself.
+
egl_display_t* const dp = get_display(dpy);
if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
if (android_atomic_dec(&dp->refs) != 1)
return EGL_TRUE;
-
- Loader& loader(Loader::getInstance());
EGLBoolean res = EGL_FALSE;
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
egl_connection_t* const cnx = &gEGLImpl[i];
if (cnx->dso) {
cnx->hooks->egl.eglTerminate(dp->dpys[i]);
-
- /* REVISIT: it's unclear what to do if eglTerminate() fails,
- * on one end we shouldn't care, on the other end if it fails
- * it might not be safe to call dlclose() (there could be some
- * threads around). */
-
+ // REVISIT: it's unclear what to do if eglTerminate() fails
free(dp->configs[i]);
free((void*)dp->queryString[i].extensions);
dp->numConfigs[i] = 0;
dp->dpys[i] = EGL_NO_DISPLAY;
-
- loader.close(cnx->dso);
- cnx->dso = 0;
res = EGL_TRUE;
}
}
@@ -1022,12 +995,18 @@
EGLContext eglGetCurrentContext(void)
{
+ // could be called before eglInitialize(), but we wouldn't have a context
+ // then, and this function would correctly return EGL_NO_CONTEXT.
+
EGLContext ctx = getContext();
return ctx;
}
EGLSurface eglGetCurrentSurface(EGLint readdraw)
{
+ // could be called before eglInitialize(), but we wouldn't have a context
+ // then, and this function would correctly return EGL_NO_SURFACE.
+
EGLContext ctx = getContext();
if (ctx) {
egl_context_t const * const c = get_context(ctx);
@@ -1043,6 +1022,9 @@
EGLDisplay eglGetCurrentDisplay(void)
{
+ // could be called before eglInitialize(), but we wouldn't have a context
+ // then, and this function would correctly return EGL_NO_DISPLAY.
+
EGLContext ctx = getContext();
if (ctx) {
egl_context_t const * const c = get_context(ctx);
@@ -1054,6 +1036,9 @@
EGLBoolean eglWaitGL(void)
{
+ // could be called before eglInitialize(), but we wouldn't have a context
+ // then, and this function would return GL_TRUE, which isn't wrong.
+
EGLBoolean res = EGL_TRUE;
EGLContext ctx = getContext();
if (ctx) {
@@ -1071,6 +1056,9 @@
EGLBoolean eglWaitNative(EGLint engine)
{
+ // could be called before eglInitialize(), but we wouldn't have a context
+ // then, and this function would return GL_TRUE, which isn't wrong.
+
EGLBoolean res = EGL_TRUE;
EGLContext ctx = getContext();
if (ctx) {
@@ -1107,9 +1095,11 @@
// eglGetProcAddress() could be the very first function called
// in which case we must make sure we've initialized ourselves, this
// happens the first time egl_get_display() is called.
-
- if (egl_init_displays(EGL_DEFAULT_DISPLAY) == EGL_NO_DISPLAY)
- return NULL;
+
+ if (egl_init_drivers() == EGL_FALSE) {
+ setError(EGL_BAD_PARAMETER, NULL);
+ return NULL;
+ }
__eglMustCastToProperFunctionPointerType addr;
addr = findProcAddress(procname, gExtentionMap, NELEM(gExtentionMap));
@@ -1275,6 +1265,8 @@
EGLBoolean eglWaitClient(void)
{
+ // could be called before eglInitialize(), but we wouldn't have a context
+ // then, and this function would return GL_TRUE, which isn't wrong.
EGLBoolean res = EGL_TRUE;
EGLContext ctx = getContext();
if (ctx) {
@@ -1296,6 +1288,10 @@
EGLBoolean eglBindAPI(EGLenum api)
{
+ if (egl_init_drivers() == EGL_FALSE) {
+ return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+
// bind this API on all EGLs
EGLBoolean res = EGL_TRUE;
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
@@ -1313,6 +1309,10 @@
EGLenum eglQueryAPI(void)
{
+ if (egl_init_drivers() == EGL_FALSE) {
+ return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+ }
+
for (int i=0 ; i<IMPL_NUM_DRIVERS_IMPLEMENTATIONS ; i++) {
egl_connection_t* const cnx = &gEGLImpl[i];
if (cnx->dso) {
diff --git a/opengl/libs/egl_impl.h b/opengl/libs/egl_impl.h
index c5f753d..ac286cb 100644
--- a/opengl/libs/egl_impl.h
+++ b/opengl/libs/egl_impl.h
@@ -35,7 +35,6 @@
gl_hooks_t * hooks;
EGLint major;
EGLint minor;
- int unavailable;
};
EGLAPI EGLImageKHR egl_get_image_for_current_context(EGLImageKHR image);
diff --git a/opengl/libs/hooks.h b/opengl/libs/hooks.h
index 37292ee..8c0357e 100644
--- a/opengl/libs/hooks.h
+++ b/opengl/libs/hooks.h
@@ -60,12 +60,8 @@
enum {
IMPL_HARDWARE = 0,
IMPL_SOFTWARE,
-
IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
-
- IMPL_CONTEXT_LOST = IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
- IMPL_NO_CONTEXT,
-
+ IMPL_NO_CONTEXT = IMPL_NUM_DRIVERS_IMPLEMENTATIONS,
IMPL_NUM_IMPLEMENTATIONS
};
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index a5bd254..56a279a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -30,7 +30,7 @@
import android.backup.BackupDataInput;
import android.backup.BackupDataOutput;
import android.backup.BackupHelperAgent;
-import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothAdapter;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
@@ -393,7 +393,7 @@
}
private void enableBluetooth(boolean enable) {
- BluetoothDevice bt = (BluetoothDevice) getSystemService(Context.BLUETOOTH_SERVICE);
+ BluetoothAdapter bt = (BluetoothAdapter) getSystemService(Context.BLUETOOTH_SERVICE);
if (bt != null) {
if (!enable) {
bt.disable();
diff --git a/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java b/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java
index 3cd2cc4..b854f86 100644
--- a/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java
+++ b/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java
@@ -113,7 +113,7 @@
// TODO(fredq) fix the hardcoded type
final Account account = new Account(accountName, "com.google.GAIA");
c = context.getContentResolver().query(SubscribedFeeds.Feeds.CONTENT_URI,
- null, where, new String[]{account.mName, account.mType, feed}, null);
+ null, where, new String[]{account.name, account.type, feed}, null);
if (c.getCount() == 0) {
Log.w(TAG, "received tickle for non-existent feed: "
+ "account " + accountName + ", feed " + feed);
@@ -171,12 +171,12 @@
try {
ContentValues values = new ContentValues();
for (Account account : accounts) {
- values.put(SyncConstValue._SYNC_ACCOUNT, account.mName);
- values.put(SyncConstValue._SYNC_ACCOUNT_TYPE, account.mType);
+ values.put(SyncConstValue._SYNC_ACCOUNT, account.name);
+ values.put(SyncConstValue._SYNC_ACCOUNT_TYPE, account.type);
contentResolver.update(SubscribedFeeds.Feeds.CONTENT_URI, values,
SubscribedFeeds.Feeds._SYNC_ACCOUNT + "=? AND "
+ SubscribedFeeds.Feeds._SYNC_ACCOUNT_TYPE + "=?",
- new String[] {account.mName, account.mType});
+ new String[] {account.name, account.type});
}
} catch (SQLiteFullException e) {
Log.w(TAG, "disk full while trying to mark the feeds as dirty, skipping");
diff --git a/packages/TtsService/jni/android_tts_SynthProxy.cpp b/packages/TtsService/jni/android_tts_SynthProxy.cpp
index a4090cf..1793587 100644
--- a/packages/TtsService/jni/android_tts_SynthProxy.cpp
+++ b/packages/TtsService/jni/android_tts_SynthProxy.cpp
@@ -26,16 +26,25 @@
#include <android_runtime/AndroidRuntime.h>
#include <tts/TtsEngine.h>
#include <media/AudioTrack.h>
+#include <math.h>
#include <dlfcn.h>
#define DEFAULT_TTS_RATE 16000
#define DEFAULT_TTS_FORMAT AudioSystem::PCM_16_BIT
#define DEFAULT_TTS_NB_CHANNELS 1
-#define DEFAULT_TTS_BUFFERSIZE 1024
+#define DEFAULT_TTS_BUFFERSIZE 2048
// TODO use the TTS stream type when available
#define DEFAULT_TTS_STREAM_TYPE AudioSystem::MUSIC
+// EQ + BOOST parameters
+#define FILTER_LOWSHELF_ATTENUATION -18.0f // in dB
+#define FILTER_TRANSITION_FREQ 1100.0f // in Hz
+#define FILTER_SHELF_SLOPE 1.0f // Q
+#define FILTER_GAIN 6.0f // linear gain
+// such a huge gain is justified by how much energy in the low frequencies is "wasted" at the output
+// of the synthesis. The low shelving filter removes it, leaving room for amplification.
+
#define USAGEMODE_PLAY_IMMEDIATELY 0
#define USAGEMODE_WRITE_TO_FILE 1
@@ -57,6 +66,79 @@
};
// ----------------------------------------------------------------------------
+// EQ data
+double amp;
+double w;
+double sinw;
+double cosw;
+double beta;
+double a0, a1, a2, b0, b1, b2;
+double m_fa, m_fb, m_fc, m_fd, m_fe;
+double x0; // x[n]
+double x1; // x[n-1]
+double x2; // x[n-2]
+double out0;// y[n]
+double out1;// y[n-1]
+double out2;// y[n-2]
+
+void initializeEQ() {
+
+ amp = float(pow(10.0, FILTER_LOWSHELF_ATTENUATION / 40.0));
+ w = 2.0 * M_PI * (FILTER_TRANSITION_FREQ / DEFAULT_TTS_RATE);
+ sinw = float(sin(w));
+ cosw = float(cos(w));
+ beta = float(sqrt(amp)/FILTER_SHELF_SLOPE);
+
+ // initialize low-shelf parameters
+ b0 = amp * ((amp+1.0F) - ((amp-1.0F)*cosw) + (beta*sinw));
+ b1 = 2.0F * amp * ((amp-1.0F) - ((amp+1.0F)*cosw));
+ b2 = amp * ((amp+1.0F) - ((amp-1.0F)*cosw) - (beta*sinw));
+ a0 = (amp+1.0F) + ((amp-1.0F)*cosw) + (beta*sinw);
+ a1 = 2.0F * ((amp-1.0F) + ((amp+1.0F)*cosw));
+ a2 = -((amp+1.0F) + ((amp-1.0F)*cosw) - (beta*sinw));
+
+ m_fa = FILTER_GAIN * b0/a0;
+ m_fb = FILTER_GAIN * b1/a0;
+ m_fc = FILTER_GAIN * b2/a0;
+ m_fd = a1/a0;
+ m_fe = a2/a0;
+}
+
+void initializeFilter() {
+ x0 = 0.0f;
+ x1 = 0.0f;
+ x2 = 0.0f;
+ out0 = 0.0f;
+ out1 = 0.0f;
+ out2 = 0.0f;
+}
+
+void applyFilter(int16_t* buffer, size_t sampleCount) {
+
+ for (size_t i=0 ; i<sampleCount ; i++) {
+
+ x0 = (double) buffer[i];
+
+ out0 = (m_fa*x0) + (m_fb*x1) + (m_fc*x2) + (m_fd*out1) + (m_fe*out2);
+
+ x2 = x1;
+ x1 = x0;
+
+ out2 = out1;
+ out1 = out0;
+
+ if (out0 > 32767.0f) {
+ buffer[i] = 32767;
+ } else if (out0 < -32768.0f) {
+ buffer[i] = -32768;
+ } else {
+ buffer[i] = (int16_t) out0;
+ }
+ }
+}
+
+
+// ----------------------------------------------------------------------------
static fields_t javaTTSFields;
// TODO move to synth member once we have multiple simultaneous engines running
@@ -198,12 +280,13 @@
if (wav == NULL) {
delete pForAfter;
- LOGI("Null: speech has completed");
+ LOGV("Null: speech has completed");
}
if (bufferSize > 0) {
prepAudioTrack(pJniData, pForAfter->streamType, rate, (AudioSystem::audio_format)format, channel);
if (pJniData->mAudioOut) {
+ applyFilter((int16_t*)wav, bufferSize/2);
pJniData->mAudioOut->write(wav, bufferSize);
memset(wav, 0, bufferSize);
//LOGV("AudioTrack wrote: %d bytes", bufferSize);
@@ -212,13 +295,14 @@
}
}
} else if (pForAfter->usageMode == USAGEMODE_WRITE_TO_FILE) {
- LOGV("Save to file");
+ //LOGV("Save to file");
if (wav == NULL) {
delete pForAfter;
LOGV("Null: speech has completed");
return TTS_CALLBACK_HALT;
}
if (bufferSize > 0){
+ applyFilter((int16_t*)wav, bufferSize/2);
fwrite(wav, 1, bufferSize, pForAfter->outputFile);
memset(wav, 0, bufferSize);
}
@@ -289,6 +373,8 @@
env->SetIntField(thiz, javaTTSFields.synthProxyFieldJniData,
(int)pJniStorage);
+ initializeEQ();
+
env->ReleaseStringUTFChars(nativeSoLib, nativeSoLibNativeString);
}
@@ -479,6 +565,8 @@
return result;
}
+ initializeFilter();
+
Mutex::Autolock l(engineMutex);
// Retrieve audio parameters before writing the file header
@@ -583,6 +671,8 @@
return result;
}
+ initializeFilter();
+
Mutex::Autolock l(engineMutex);
SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 1c60058..72a1192 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -100,6 +100,9 @@
// a process dies
private List mFeatureUsers;
+ private boolean mSystemReady;
+ private ArrayList<Intent> mDeferredBroadcasts;
+
private class NetworkAttributes {
/**
* Class for holding settings read from resources.
@@ -820,7 +823,7 @@
(newNet == null || !newNet.isAvailable() ? "" : " other=" +
newNet.getNetworkInfo().getTypeName()));
- mContext.sendStickyBroadcast(intent);
+ sendStickyBroadcast(intent);
/*
* If the failover network is already connected, then immediately send
* out a followup broadcast indicating successful failover
@@ -843,7 +846,7 @@
intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
info.getExtraInfo());
}
- mContext.sendStickyBroadcast(intent);
+ sendStickyBroadcast(intent);
}
/**
@@ -882,7 +885,33 @@
intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
info.setFailover(false);
}
- mContext.sendStickyBroadcast(intent);
+ sendStickyBroadcast(intent);
+ }
+
+ private void sendStickyBroadcast(Intent intent) {
+ synchronized(this) {
+ if (mSystemReady) {
+ mContext.sendStickyBroadcast(intent);
+ } else {
+ if (mDeferredBroadcasts == null) {
+ mDeferredBroadcasts = new ArrayList<Intent>();
+ }
+ mDeferredBroadcasts.add(intent);
+ }
+ }
+ }
+
+ void systemReady() {
+ synchronized(this) {
+ mSystemReady = true;
+ if (mDeferredBroadcasts != null) {
+ int count = mDeferredBroadcasts.size();
+ for (int i = 0; i < count; i++) {
+ mContext.sendStickyBroadcast(mDeferredBroadcasts.get(i));
+ }
+ mDeferredBroadcasts = null;
+ }
+ }
}
private void handleConnect(NetworkInfo info) {
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
new file mode 100644
index 0000000..68ff416
--- /dev/null
+++ b/services/java/com/android/server/DockObserver.java
@@ -0,0 +1,115 @@
+/*
+ * 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.
+ */
+
+package com.android.server;
+
+import android.app.ActivityManagerNative;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Message;
+import android.os.UEventObserver;
+import android.util.Log;
+
+import java.io.FileReader;
+import java.io.FileNotFoundException;
+
+/**
+ * <p>DockObserver monitors for a docking station.
+ */
+class DockObserver extends UEventObserver {
+ private static final String TAG = DockObserver.class.getSimpleName();
+ private static final boolean LOG = false;
+
+ private static final String DOCK_UEVENT_MATCH = "DEVPATH=/devices/virtual/switch/dock";
+ private static final String DOCK_STATE_PATH = "/sys/class/switch/dock/state";
+
+ private int mDockState;
+ private boolean mPendingIntent;
+
+ private final Context mContext;
+
+ public DockObserver(Context context) {
+ mContext = context;
+
+ startObserving(DOCK_UEVENT_MATCH);
+
+ init(); // set initial status
+ }
+
+ @Override
+ public void onUEvent(UEventObserver.UEvent event) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "Dock UEVENT: " + event.toString());
+ }
+
+ try {
+ update(Integer.parseInt(event.get("SWITCH_STATE")));
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Could not parse switch state from event " + event);
+ }
+ }
+
+ private synchronized final void init() {
+ char[] buffer = new char[1024];
+
+ int newState = mDockState;
+ try {
+ FileReader file = new FileReader(DOCK_STATE_PATH);
+ int len = file.read(buffer, 0, 1024);
+ newState = Integer.valueOf((new String(buffer, 0, len)).trim());
+
+ } catch (FileNotFoundException e) {
+ Log.w(TAG, "This kernel does not have dock station support");
+ } catch (Exception e) {
+ Log.e(TAG, "" , e);
+ }
+
+ update(newState);
+ }
+
+ private synchronized final void update(int newState) {
+ if (newState != mDockState) {
+ mDockState = newState;
+
+ mPendingIntent = true;
+ mHandler.sendEmptyMessage(0);
+ }
+ }
+
+ private synchronized final void sendIntent() {
+ // Pack up the values and broadcast them to everyone
+ Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
+
+ // TODO: Should we require a permission?
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "Broadcasting dock state " + mDockState);
+ }
+ ActivityManagerNative.broadcastStickyIntent(intent, null);
+ }
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ if (mPendingIntent) {
+ sendIntent();
+ mPendingIntent = false;
+ }
+ }
+ };
+}
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index fab97b1..2201b55 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -1100,6 +1100,11 @@
}
public boolean sendExtraCommand(String provider, String command, Bundle extras) {
+ if (provider == null) {
+ // throw NullPointerException to remain compatible with previous implementation
+ throw new NullPointerException();
+ }
+
// first check for permission to the provider
checkPermissionsSafe(provider);
// and check for ACCESS_LOCATION_EXTRA_COMMANDS
@@ -1110,7 +1115,7 @@
synchronized (mLock) {
LocationProviderProxy proxy = mProvidersByName.get(provider);
- if (provider == null) {
+ if (proxy == null) {
return false;
}
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 447e9fa..1249289 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -2054,7 +2054,15 @@
if (event.values[0] == 0.0) {
goToSleep(milliseconds);
} else {
- userActivity(milliseconds, false);
+ // proximity sensor negative events user activity.
+ // temporarily set mUserActivityAllowed to true so this will work
+ // even when the keyguard is on.
+ synchronized (mLocks) {
+ boolean savedActivityAllowed = mUserActivityAllowed;
+ mUserActivityAllowed = true;
+ userActivity(milliseconds, false);
+ mUserActivityAllowed = savedActivityAllowed;
+ }
}
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 8919ccc..98f35f4 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -36,7 +36,7 @@
import android.provider.Contacts.People;
import android.provider.Settings;
import android.server.BluetoothA2dpService;
-import android.server.BluetoothDeviceService;
+import android.server.BluetoothService;
import android.server.search.SearchManagerService;
import android.util.EventLog;
import android.util.Log;
@@ -85,12 +85,14 @@
HardwareService hardware = null;
PowerManagerService power = null;
BatteryService battery = null;
+ ConnectivityService connectivity = null;
IPackageManager pm = null;
Context context = null;
WindowManagerService wm = null;
- BluetoothDeviceService bluetooth = null;
+ BluetoothService bluetooth = null;
BluetoothA2dpService bluetoothA2dp = null;
HeadsetObserver headset = null;
+ DockObserver dock = null;
// Critical services...
try {
@@ -174,9 +176,9 @@
ServiceManager.addService(Context.BLUETOOTH_SERVICE, null);
} else {
Log.i(TAG, "Starting Bluetooth Service.");
- bluetooth = new BluetoothDeviceService(context);
- bluetooth.init();
+ bluetooth = new BluetoothService(context);
ServiceManager.addService(Context.BLUETOOTH_SERVICE, bluetooth);
+ bluetooth.initAfterRegistration();
bluetoothA2dp = new BluetoothA2dpService(context, bluetooth);
ServiceManager.addService(BluetoothA2dpService.BLUETOOTH_A2DP_SERVICE,
bluetoothA2dp);
@@ -196,6 +198,7 @@
InputMethodManagerService imm = null;
AppWidgetService appWidget = null;
NotificationManagerService notification = null;
+ WallpaperManagerService wallpaper = null;
if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
try {
@@ -230,8 +233,8 @@
try {
Log.i(TAG, "Starting Connectivity Service.");
- ServiceManager.addService(Context.CONNECTIVITY_SERVICE,
- ConnectivityService.getInstance(context));
+ connectivity = ConnectivityService.getInstance(context);
+ ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
} catch (Throwable e) {
Log.e(TAG, "Failure starting Connectivity Service", e);
}
@@ -302,7 +305,8 @@
try {
Log.i(TAG, "Starting Wallpaper Service");
- ServiceManager.addService(Context.WALLPAPER_SERVICE, new WallpaperManagerService(context));
+ wallpaper = new WallpaperManagerService(context);
+ ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper);
} catch (Throwable e) {
Log.e(TAG, "Failure starting Wallpaper Service", e);
}
@@ -323,6 +327,14 @@
}
try {
+ Log.i(TAG, "Starting DockObserver");
+ // Listen for dock station changes
+ dock = new DockObserver(context);
+ } catch (Throwable e) {
+ Log.e(TAG, "Failure starting DockObserver", e);
+ }
+
+ try {
Log.i(TAG, "Starting Backup Service");
ServiceManager.addService(Context.BACKUP_SERVICE, new BackupManagerService(context));
} catch (Throwable e) {
@@ -381,7 +393,9 @@
} catch (RemoteException e) {
}
- battery.systemReady();
+ if (wallpaper != null) wallpaper.systemReady();
+ if (battery != null) battery.systemReady();
+ if (connectivity != null) connectivity.systemReady();
Watchdog.getInstance().start();
Looper.loop();
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index 06565c7..6047742 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -38,6 +38,7 @@
import android.os.ParcelFileDescriptor;
import android.os.RemoteCallbackList;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.service.wallpaper.IWallpaperConnection;
import android.service.wallpaper.IWallpaperEngine;
import android.service.wallpaper.IWallpaperService;
@@ -59,6 +60,7 @@
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
+import com.android.internal.service.wallpaper.ImageWallpaper;
import com.android.internal.util.FastXmlSerializer;
class WallpaperManagerService extends IWallpaperManager.Stub {
@@ -67,10 +69,16 @@
Object mLock = new Object();
- private static final File WALLPAPER_DIR = new File(
+ /**
+ * Minimum time between crashes of a wallpaper service for us to consider
+ * restarting it vs. just reverting to the static wallpaper.
+ */
+ static final long MIN_WALLPAPER_CRASH_TIME = 10000;
+
+ static final File WALLPAPER_DIR = new File(
"/data/data/com.android.settings/files");
- private static final String WALLPAPER = "wallpaper";
- private static final File WALLPAPER_FILE = new File(WALLPAPER_DIR, WALLPAPER);
+ static final String WALLPAPER = "wallpaper";
+ static final File WALLPAPER_FILE = new File(WALLPAPER_DIR, WALLPAPER);
/**
* List of callbacks registered they should each be notified
@@ -115,6 +123,7 @@
String mName = "";
ComponentName mWallpaperComponent;
WallpaperConnection mWallpaperConnection;
+ long mLastDiedTime;
class WallpaperConnection extends IWallpaperConnection.Stub
implements ServiceConnection {
@@ -135,6 +144,14 @@
synchronized (mLock) {
mService = null;
mEngine = null;
+ if (mWallpaperConnection == this) {
+ Log.w(TAG, "Wallpaper service gone: " + mWallpaperComponent);
+ if ((mLastDiedTime+MIN_WALLPAPER_CRASH_TIME)
+ < SystemClock.uptimeMillis()) {
+ Log.w(TAG, "Reverting to built-in wallpaper!");
+ bindWallpaperComponentLocked(null);
+ }
+ }
}
}
@@ -172,12 +189,34 @@
mWallpaperObserver.stopWatching();
}
+ public void systemReady() {
+ synchronized (mLock) {
+ try {
+ bindWallpaperComponentLocked(mWallpaperComponent);
+ } catch (RuntimeException e) {
+ Log.w(TAG, "Failure starting previous wallpaper", e);
+ try {
+ bindWallpaperComponentLocked(null);
+ } catch (RuntimeException e2) {
+ Log.w(TAG, "Failure starting default wallpaper", e2);
+ clearWallpaperComponentLocked();
+ }
+ }
+ }
+ }
+
public void clearWallpaper() {
synchronized (mLock) {
File f = WALLPAPER_FILE;
if (f.exists()) {
f.delete();
}
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ bindWallpaperComponentLocked(null);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
}
@@ -229,12 +268,17 @@
public ParcelFileDescriptor setWallpaper(String name) {
checkPermission(android.Manifest.permission.SET_WALLPAPER);
synchronized (mLock) {
- ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name);
- if (pfd != null) {
- clearWallpaperComponentLocked();
- saveSettingsLocked();
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name);
+ if (pfd != null) {
+ bindWallpaperComponentLocked(null);
+ saveSettingsLocked();
+ }
+ return pfd;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
- return pfd;
}
}
@@ -256,16 +300,47 @@
synchronized (mLock) {
final long ident = Binder.clearCallingIdentity();
try {
- ServiceInfo si = mContext.getPackageManager().getServiceInfo(name,
- PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS);
- if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
- throw new SecurityException("Selected service does not require "
- + android.Manifest.permission.BIND_WALLPAPER
- + ": " + name);
+ bindWallpaperComponentLocked(name);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
+ void bindWallpaperComponentLocked(ComponentName name) {
+ // Has the component changed?
+ if (mWallpaperConnection != null) {
+ if (mWallpaperComponent == null) {
+ if (name == null) {
+ // Still using default wallpaper.
+ return;
}
-
+ } else if (mWallpaperComponent.equals(name)) {
+ // Changing to same wallpaper.
+ return;
+ }
+ }
+
+ try {
+ ComponentName realName = name;
+ if (realName == null) {
+ // The default component is our static image wallpaper.
+ realName = new ComponentName("android",
+ ImageWallpaper.class.getName());
+ //clearWallpaperComponentLocked();
+ //return;
+ }
+ ServiceInfo si = mContext.getPackageManager().getServiceInfo(realName,
+ PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS);
+ if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
+ throw new SecurityException("Selected service does not require "
+ + android.Manifest.permission.BIND_WALLPAPER
+ + ": " + realName);
+ }
+
+ Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
+ if (name != null) {
// Make sure the selected service is actually a wallpaper service.
- Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
List<ResolveInfo> ris = mContext.getPackageManager()
.queryIntentServices(intent, 0);
for (int i=0; i<ris.size(); i++) {
@@ -278,33 +353,32 @@
}
if (ris != null) {
throw new SecurityException("Selected service is not a wallpaper: "
- + name);
+ + realName);
}
-
- // Bind the service!
- WallpaperConnection newConn = new WallpaperConnection();
- intent.setComponent(name);
- if (!mContext.bindService(intent, newConn,
- Context.BIND_AUTO_CREATE)) {
- throw new IllegalArgumentException("Unable to bind service: "
- + name);
- }
-
- clearWallpaperComponentLocked();
- mWallpaperComponent = null;
- mWallpaperConnection = newConn;
- try {
- if (DEBUG) Log.v(TAG, "Adding window token: " + newConn.mToken);
- mIWindowManager.addWindowToken(newConn.mToken,
- WindowManager.LayoutParams.TYPE_WALLPAPER);
- } catch (RemoteException e) {
- }
-
- } catch (PackageManager.NameNotFoundException e) {
- throw new IllegalArgumentException("Unknown component " + name);
- } finally {
- Binder.restoreCallingIdentity(ident);
}
+
+ // Bind the service!
+ WallpaperConnection newConn = new WallpaperConnection();
+ intent.setComponent(realName);
+ if (!mContext.bindService(intent, newConn,
+ Context.BIND_AUTO_CREATE)) {
+ throw new IllegalArgumentException("Unable to bind service: "
+ + name);
+ }
+
+ clearWallpaperComponentLocked();
+ mWallpaperComponent = name;
+ mWallpaperConnection = newConn;
+ mLastDiedTime = SystemClock.uptimeMillis();
+ try {
+ if (DEBUG) Log.v(TAG, "Adding window token: " + newConn.mToken);
+ mIWindowManager.addWindowToken(newConn.mToken,
+ WindowManager.LayoutParams.TYPE_WALLPAPER);
+ } catch (RemoteException e) {
+ }
+
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new IllegalArgumentException("Unknown component " + name);
}
}
@@ -327,7 +401,7 @@
conn.mService.attach(conn, conn.mToken, mWidth, mHeight);
} catch (RemoteException e) {
Log.w(TAG, "Failed attaching wallpaper; clearing", e);
- clearWallpaperComponentLocked();
+ bindWallpaperComponentLocked(null);
}
}
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index fae987a..2dc747e 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -1209,8 +1209,9 @@
ssid = "";
}
- // bssid is the hash key
- scanResult = mScanResultCache.get(bssid);
+ // bssid + ssid is the hash key
+ String key = bssid + ssid;
+ scanResult = mScanResultCache.get(key);
if (scanResult != null) {
scanResult.level = level;
scanResult.SSID = ssid;
@@ -1222,7 +1223,7 @@
scanResult =
new ScanResult(
ssid, bssid, flags, level, frequency);
- mScanResultCache.put(bssid, scanResult);
+ mScanResultCache.put(key, scanResult);
}
}
} else {
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index b0f049e..988c3d5 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -34,8 +34,6 @@
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
-import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_GPU;
-import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_HARDWARE;
import static android.view.WindowManager.LayoutParams.MEMORY_TYPE_PUSH_BUFFERS;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
@@ -141,6 +139,7 @@
static final boolean DEBUG_APP_TRANSITIONS = false;
static final boolean DEBUG_STARTING_WINDOW = false;
static final boolean DEBUG_REORDER = false;
+ static final boolean DEBUG_WALLPAPER = false;
static final boolean SHOW_TRANSACTIONS = false;
static final boolean MEASURE_LATENCY = false;
static private LatencyTimer lt;
@@ -1189,16 +1188,26 @@
while (i > 0) {
i--;
w = (WindowState)localmWindows.get(i);
- if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isReadyForDisplay()) {
+ if ((w.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0 && w.isReadyForDisplay()
+ && !w.mDrawPending && !w.mCommitDrawPending) {
visible = true;
break;
}
}
if (!visible) w = null;
+ if (DEBUG_WALLPAPER && mWallpaperTarget != w) {
+ Log.v(TAG, "New wallpaper target: " + w);
+ }
mWallpaperTarget = w;
if (visible) {
+ // The window is visible to the compositor... but is it visible
+ // to the user? That is what the wallpaper cares about.
+ visible = !w.mObscured;
+
+ // If the wallpaper target is animating, we may need to copy
+ // its layer adjustment.
mWallpaperAnimLayerAdjustment = w.mAppToken != null
? w.mAppToken.animLayerAdjustment : 0;
@@ -1238,7 +1247,8 @@
WindowState wallpaper = token.windows.get(curWallpaperIndex);
if (visible) {
- updateWallpaperOffsetLocked(mWallpaperTarget, wallpaper, dw, dh);
+ updateWallpaperOffsetLocked(mWallpaperTarget,
+ wallpaper, dw, dh);
}
// First, make sure the client has the current visibility
@@ -1246,7 +1256,7 @@
if (wallpaper.mWallpaperVisible != visible) {
wallpaper.mWallpaperVisible = visible;
try {
- if (DEBUG_VISIBILITY) Log.v(TAG,
+ if (DEBUG_VISIBILITY || DEBUG_WALLPAPER) Log.v(TAG,
"Setting visibility of wallpaper " + wallpaper
+ ": " + visible);
wallpaper.mClient.dispatchAppVisibility(visible);
@@ -1255,8 +1265,8 @@
}
wallpaper.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
- if (DEBUG_LAYERS) Log.v(TAG, "Wallpaper win " + wallpaper
- + " anim layer: " + wallpaper.mAnimLayer);
+ if (DEBUG_LAYERS || DEBUG_WALLPAPER) Log.v(TAG, "Wallpaper win "
+ + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
// First, if this window is at the current index, then all
// is well.
@@ -1278,6 +1288,9 @@
}
// Now stick it in.
+ if (DEBUG_WALLPAPER) Log.v(TAG, "Moving wallpaper " + wallpaper
+ + " from " + oldIndex + " to " + i);
+
localmWindows.add(i, wallpaper);
changed = true;
}
@@ -1287,7 +1300,8 @@
}
void setWallpaperAnimLayerAdjustmentLocked(int adj) {
- if (DEBUG_LAYERS) Log.v(TAG, "Setting wallpaper layer adj to " + adj);
+ if (DEBUG_LAYERS || DEBUG_WALLPAPER) Log.v(TAG,
+ "Setting wallpaper layer adj to " + adj);
mWallpaperAnimLayerAdjustment = adj;
int curTokenIndex = mWallpaperTokens.size();
while (curTokenIndex > 0) {
@@ -1298,8 +1312,8 @@
curWallpaperIndex--;
WindowState wallpaper = token.windows.get(curWallpaperIndex);
wallpaper.mAnimLayer = wallpaper.mLayer + adj;
- if (DEBUG_LAYERS) Log.v(TAG, "Wallpaper win " + wallpaper
- + " anim layer: " + wallpaper.mAnimLayer);
+ if (DEBUG_LAYERS || DEBUG_WALLPAPER) Log.v(TAG, "Wallpaper win "
+ + wallpaper + " anim layer: " + wallpaper.mAnimLayer);
}
}
}
@@ -1307,27 +1321,38 @@
boolean updateWallpaperOffsetLocked(WindowState target,
WindowState wallpaperWin, int dw, int dh) {
boolean changed = false;
+ boolean rawChanged = false;
if (target.mWallpaperX >= 0) {
int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
int offset = availw > 0 ? -(int)(availw*target.mWallpaperX+.5f) : 0;
changed = wallpaperWin.mXOffset != offset;
if (changed) {
+ if (DEBUG_WALLPAPER) Log.v(TAG, "Update wallpaper "
+ + wallpaperWin + " x: " + offset);
wallpaperWin.mXOffset = offset;
}
+ if (wallpaperWin.mWallpaperX != target.mWallpaperX) {
+ wallpaperWin.mWallpaperX = target.mWallpaperX;
+ rawChanged = true;
+ }
}
+
if (target.mWallpaperY >= 0) {
int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
int offset = availh > 0 ? -(int)(availh*target.mWallpaperY+.5f) : 0;
if (wallpaperWin.mYOffset != offset) {
+ if (DEBUG_WALLPAPER) Log.v(TAG, "Update wallpaper "
+ + wallpaperWin + " y: " + offset);
changed = true;
wallpaperWin.mYOffset = offset;
}
+ if (wallpaperWin.mWallpaperY != target.mWallpaperY) {
+ wallpaperWin.mWallpaperY = target.mWallpaperY;
+ rawChanged = true;
+ }
}
- if (wallpaperWin.mWallpaperX != target.mWallpaperX
- || wallpaperWin.mWallpaperY != target.mWallpaperY) {
- wallpaperWin.mWallpaperX = target.mWallpaperX;
- wallpaperWin.mWallpaperY = target.mWallpaperY;
+ if (rawChanged) {
try {
wallpaperWin.mClient.dispatchWallpaperOffsets(
wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY);
@@ -1365,6 +1390,32 @@
return changed;
}
+ void sendPointerToWallpaperLocked(WindowState srcWin,
+ MotionEvent pointer, long eventTime) {
+ int curTokenIndex = mWallpaperTokens.size();
+ while (curTokenIndex > 0) {
+ curTokenIndex--;
+ WindowToken token = mWallpaperTokens.get(curTokenIndex);
+ int curWallpaperIndex = token.windows.size();
+ while (curWallpaperIndex > 0) {
+ curWallpaperIndex--;
+ WindowState wallpaper = token.windows.get(curWallpaperIndex);
+ if ((wallpaper.mAttrs.flags &
+ WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
+ continue;
+ }
+ try {
+ MotionEvent ev = MotionEvent.obtainNoHistory(pointer);
+ ev.offsetLocation(srcWin.mFrame.left-wallpaper.mFrame.left,
+ srcWin.mFrame.top-wallpaper.mFrame.top);
+ wallpaper.mClient.dispatchPointer(ev, eventTime, false);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failure sending pointer to wallpaper", e);
+ }
+ }
+ }
+ }
+
public int addWindow(Session session, IWindow client,
WindowManager.LayoutParams attrs, int viewVisibility,
Rect outContentInsets) {
@@ -1653,6 +1704,8 @@
}
private void removeWindowInnerLocked(Session session, WindowState win) {
+ mKeyWaiter.finishedKey(session, win.mClient, true,
+ KeyWaiter.RETURN_NOTHING);
mKeyWaiter.releasePendingPointerLocked(win.mSession);
mKeyWaiter.releasePendingTrackballLocked(win.mSession);
@@ -4319,7 +4372,7 @@
final Rect frame = out.mFrame;
oev.offsetLocation(-(float)frame.left, -(float)frame.top);
try {
- out.mClient.dispatchPointer(oev, eventTime);
+ out.mClient.dispatchPointer(oev, eventTime, false);
} catch (android.os.RemoteException e) {
Log.i(TAG, "WINDOW DIED during outside motion dispatch: " + out);
}
@@ -4332,6 +4385,12 @@
final Rect frame = target.mFrame;
ev.offsetLocation(-(float)frame.left, -(float)frame.top);
mKeyWaiter.bindTargetWindowLocked(target);
+
+ // If we are on top of the wallpaper, then the wallpaper also
+ // gets to see this movement.
+ if (mWallpaperTarget == target) {
+ sendPointerToWallpaperLocked(target, ev, eventTime);
+ }
}
}
@@ -4346,7 +4405,7 @@
lt.sample("6 before svr->client ipc ", System.nanoTime() - eventTimeNano);
}
- target.mClient.dispatchPointer(ev, eventTime);
+ target.mClient.dispatchPointer(ev, eventTime, true);
if (MEASURE_LATENCY) {
lt.sample("7 after svr->client ipc ", System.nanoTime() - eventTimeNano);
@@ -4422,7 +4481,7 @@
}
try {
- focus.mClient.dispatchTrackball(ev, eventTime);
+ focus.mClient.dispatchTrackball(ev, eventTime, true);
return INJECT_SUCCEEDED;
} catch (android.os.RemoteException e) {
Log.i(TAG, "WINDOW DIED during key dispatch: " + focus);
@@ -5197,14 +5256,16 @@
return null;
}
+ MotionEvent res = null;
+ QueuedEvent qev = null;
+ WindowState win = null;
+
synchronized (this) {
if (DEBUG_INPUT) Log.v(
TAG, "finishedKey: client=" + client.asBinder()
+ ", force=" + force + ", last=" + mLastBinder
+ " (token=" + (mLastWin != null ? mLastWin.mToken : null) + ")");
- QueuedEvent qev = null;
- WindowState win = null;
if (returnWhat == RETURN_PENDING_POINTER) {
qev = session.mPendingPointerMove;
win = session.mPendingPointerWindow;
@@ -5234,17 +5295,25 @@
}
if (qev != null) {
- MotionEvent res = (MotionEvent)qev.event;
+ res = (MotionEvent)qev.event;
if (DEBUG_INPUT) Log.v(TAG,
"Returning pending motion: " + res);
mQueue.recycleEvent(qev);
if (win != null && returnWhat == RETURN_PENDING_POINTER) {
res.offsetLocation(-win.mFrame.left, -win.mFrame.top);
}
- return res;
}
- return null;
}
+
+ if (res != null && returnWhat == RETURN_PENDING_POINTER) {
+ synchronized (mWindowMap) {
+ if (mWallpaperTarget == win) {
+ sendPointerToWallpaperLocked(win, res, res.getEventTime());
+ }
+ }
+ }
+
+ return res;
}
void tickle() {
@@ -5996,6 +6065,7 @@
int mAnimLayer;
int mLastLayer;
boolean mHaveFrame;
+ boolean mObscured;
WindowState mNextOutsideTouch;
@@ -6386,11 +6456,7 @@
}
int flags = 0;
- if (mAttrs.memoryType == MEMORY_TYPE_HARDWARE) {
- flags |= Surface.HARDWARE;
- } else if (mAttrs.memoryType == MEMORY_TYPE_GPU) {
- flags |= Surface.GPU;
- } else if (mAttrs.memoryType == MEMORY_TYPE_PUSH_BUFFERS) {
+ if (mAttrs.memoryType == MEMORY_TYPE_PUSH_BUFFERS) {
flags |= Surface.PUSH_BUFFERS;
}
@@ -6770,6 +6836,12 @@
mWallpaperTarget.mAppToken.hasTransformation) {
appTransformation = mWallpaperTarget.mAppToken.transformation;
}
+ if (DEBUG_WALLPAPER && attachedTransformation != null) {
+ Log.v(TAG, "WP target attached xform: " + attachedTransformation);
+ }
+ if (DEBUG_WALLPAPER && appTransformation != null) {
+ Log.v(TAG, "WP target app xform: " + appTransformation);
+ }
}
if (selfTransformation || attachedTransformation != null
@@ -6906,10 +6978,10 @@
if (atoken != null) {
return mSurface != null && mPolicyVisibility && !mDestroying
&& ((!mAttachedHidden && !atoken.hiddenRequested)
- || mAnimating || atoken.animating);
+ || mAnimation != null || atoken.animation != null);
} else {
return mSurface != null && mPolicyVisibility && !mDestroying
- && (!mAttachedHidden || mAnimating);
+ && (!mAttachedHidden || mAnimation != null);
}
}
@@ -6919,10 +6991,12 @@
*/
boolean isReadyForDisplay() {
final AppWindowToken atoken = mAppToken;
- final boolean animating = atoken != null ? atoken.animating : false;
+ final boolean animating = atoken != null
+ ? (atoken.animation != null) : false;
return mSurface != null && mPolicyVisibility && !mDestroying
- && ((!mAttachedHidden && !mRootToken.hidden)
- || mAnimating || animating);
+ && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
+ && !mRootToken.hidden)
+ || mAnimation != null || animating);
}
/** Is the window or its container currently animating? */
@@ -7121,7 +7195,8 @@
pw.print(prefix); pw.print("mViewVisibility=0x");
pw.print(Integer.toHexString(mViewVisibility));
pw.print(" mLastHidden="); pw.print(mLastHidden);
- pw.print(" mHaveFrame="); pw.println(mHaveFrame);
+ pw.print(" mHaveFrame="); pw.print(mHaveFrame);
+ pw.print(" mObscured="); pw.println(mObscured);
if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
pw.print(prefix); pw.print("mPolicyVisibility=");
pw.print(mPolicyVisibility);
@@ -8143,7 +8218,8 @@
for (i=0; i<N; i++) {
WindowState w = (WindowState)mWindows.get(i);
- if (w.mBaseLayer == curBaseLayer || w.mIsFloatingLayer) {
+ if (w.mBaseLayer == curBaseLayer || w.mIsImWindow
+ || (i > 0 && w.mIsWallpaper)) {
curLayer += WINDOW_LAYER_MULTIPLIER;
w.mLayer = curLayer;
} else {
@@ -8825,7 +8901,7 @@
}
// Update effect.
- if (!obscured) {
+ if (!(w.mObscured=obscured)) {
if (w.mSurface != null) {
if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) {
holdScreen = w.mSession;
@@ -8991,6 +9067,7 @@
}
// Destroy the surface of any windows that are no longer visible.
+ boolean wallpaperDestroyed = false;
i = mDestroySurface.size();
if (i > 0) {
do {
@@ -9000,6 +9077,9 @@
if (mInputMethodWindow == win) {
mInputMethodWindow = null;
}
+ if (win == mWallpaperTarget) {
+ wallpaperDestroyed = true;
+ }
win.destroySurfaceLocked();
} while (i > 0);
mDestroySurface.clear();
@@ -9028,7 +9108,12 @@
if (focusDisplayed) {
mH.sendEmptyMessage(H.REPORT_LOSING_FOCUS);
}
- if (animating) {
+ if (wallpaperDestroyed) {
+ wallpaperDestroyed = adjustWallpaperWindowsLocked();
+ }
+ if (wallpaperDestroyed) {
+ requestAnimationLocked(0);
+ } else if (animating) {
requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis());
}
mQueue.setHoldScreenLocked(holdScreen != null);
@@ -9489,6 +9574,7 @@
pw.print(" mFocusedApp="); pw.println(mFocusedApp);
pw.print(" mInputMethodTarget="); pw.println(mInputMethodTarget);
pw.print(" mInputMethodWindow="); pw.println(mInputMethodWindow);
+ pw.print(" mWallpaperTarget="); pw.println(mWallpaperTarget);
pw.print(" mInTouchMode="); pw.println(mInTouchMode);
pw.print(" mSystemBooted="); pw.print(mSystemBooted);
pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index e71d329..33d899a 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -18,7 +18,7 @@
import android.app.AlertDialog;
import android.bluetooth.BluetoothA2dp;
-import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothError;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothIntent;
@@ -473,10 +473,10 @@
mBluetoothData = IconData.makeIcon("bluetooth",
null, com.android.internal.R.drawable.stat_sys_data_bluetooth, 0, 0);
mBluetoothIcon = service.addIcon(mBluetoothData, null);
- BluetoothDevice bluetooth =
- (BluetoothDevice) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
- if (bluetooth != null) {
- mBluetoothEnabled = bluetooth.isEnabled();
+ BluetoothAdapter adapter =
+ (BluetoothAdapter) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
+ if (adapter != null) {
+ mBluetoothEnabled = adapter.isEnabled();
} else {
mBluetoothEnabled = false;
}
@@ -1083,7 +1083,7 @@
if (action.equals(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION)) {
int state = intent.getIntExtra(BluetoothIntent.BLUETOOTH_STATE,
BluetoothError.ERROR);
- mBluetoothEnabled = state == BluetoothDevice.BLUETOOTH_STATE_ON;
+ mBluetoothEnabled = state == BluetoothAdapter.BLUETOOTH_STATE_ON;
} else if (action.equals(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION)) {
mBluetoothHeadsetState = intent.getIntExtra(BluetoothIntent.HEADSET_STATE,
BluetoothHeadset.STATE_ERROR);
diff --git a/services/jni/com_android_server_BatteryService.cpp b/services/jni/com_android_server_BatteryService.cpp
index e4f001f..8e7cadc 100644
--- a/services/jni/com_android_server_BatteryService.cpp
+++ b/services/jni/com_android_server_BatteryService.cpp
@@ -31,6 +31,7 @@
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
+#include <dirent.h>
#if HAVE_ANDROID_OS
#include <linux/ioctl.h>
@@ -38,15 +39,7 @@
namespace android {
-#define AC_ONLINE_PATH "/sys/class/power_supply/ac/online"
-#define USB_ONLINE_PATH "/sys/class/power_supply/usb/online"
-#define BATTERY_STATUS_PATH "/sys/class/power_supply/battery/status"
-#define BATTERY_HEALTH_PATH "/sys/class/power_supply/battery/health"
-#define BATTERY_PRESENT_PATH "/sys/class/power_supply/battery/present"
-#define BATTERY_CAPACITY_PATH "/sys/class/power_supply/battery/capacity"
-#define BATTERY_VOLTAGE_PATH "/sys/class/power_supply/battery/batt_vol"
-#define BATTERY_TEMPERATURE_PATH "/sys/class/power_supply/battery/batt_temp"
-#define BATTERY_TECHNOLOGY_PATH "/sys/class/power_supply/battery/technology"
+#define POWER_SUPPLY_PATH "/sys/class/power_supply"
struct FieldIds {
// members
@@ -77,6 +70,21 @@
};
static BatteryManagerConstants gConstants;
+struct PowerSupplyPaths {
+ char* acOnlinePath;
+ char* usbOnlinePath;
+ char* batteryStatusPath;
+ char* batteryHealthPath;
+ char* batteryPresentPath;
+ char* batteryCapacityPath;
+ char* batteryVoltagePath;
+ char* batteryTemperaturePath;
+ char* batteryTechnologyPath;
+};
+static PowerSupplyPaths gPaths;
+
+static int gVoltageDivisor = 1;
+
static jint getBatteryStatus(const char* status)
{
switch (status[0]) {
@@ -126,6 +134,8 @@
static int readFromFile(const char* path, char* buf, size_t size)
{
+ if (!path)
+ return -1;
int fd = open(path, O_RDONLY, 0);
if (fd == -1) {
LOGE("Could not open '%s'", path);
@@ -171,29 +181,43 @@
env->SetIntField(obj, fieldID, value);
}
+static void setVoltageField(JNIEnv* env, jobject obj, const char* path, jfieldID fieldID)
+{
+ const int SIZE = 128;
+ char buf[SIZE];
+
+ jint value = 0;
+ if (readFromFile(path, buf, SIZE) > 0) {
+ value = atoi(buf);
+ value /= gVoltageDivisor;
+ }
+ env->SetIntField(obj, fieldID, value);
+}
+
+
static void android_server_BatteryService_update(JNIEnv* env, jobject obj)
{
- setBooleanField(env, obj, AC_ONLINE_PATH, gFieldIds.mAcOnline);
- setBooleanField(env, obj, USB_ONLINE_PATH, gFieldIds.mUsbOnline);
- setBooleanField(env, obj, BATTERY_PRESENT_PATH, gFieldIds.mBatteryPresent);
+ setBooleanField(env, obj, gPaths.acOnlinePath, gFieldIds.mAcOnline);
+ setBooleanField(env, obj, gPaths.usbOnlinePath, gFieldIds.mUsbOnline);
+ setBooleanField(env, obj, gPaths.batteryPresentPath, gFieldIds.mBatteryPresent);
- setIntField(env, obj, BATTERY_CAPACITY_PATH, gFieldIds.mBatteryLevel);
- setIntField(env, obj, BATTERY_VOLTAGE_PATH, gFieldIds.mBatteryVoltage);
- setIntField(env, obj, BATTERY_TEMPERATURE_PATH, gFieldIds.mBatteryTemperature);
+ setIntField(env, obj, gPaths.batteryCapacityPath, gFieldIds.mBatteryLevel);
+ setVoltageField(env, obj, gPaths.batteryVoltagePath, gFieldIds.mBatteryVoltage);
+ setIntField(env, obj, gPaths.batteryTemperaturePath, gFieldIds.mBatteryTemperature);
const int SIZE = 128;
char buf[SIZE];
- if (readFromFile(BATTERY_STATUS_PATH, buf, SIZE) > 0)
+ if (readFromFile(gPaths.batteryStatusPath, buf, SIZE) > 0)
env->SetIntField(obj, gFieldIds.mBatteryStatus, getBatteryStatus(buf));
else
env->SetIntField(obj, gFieldIds.mBatteryStatus,
gConstants.statusUnknown);
- if (readFromFile(BATTERY_HEALTH_PATH, buf, SIZE) > 0)
+ if (readFromFile(gPaths.batteryHealthPath, buf, SIZE) > 0)
env->SetIntField(obj, gFieldIds.mBatteryHealth, getBatteryHealth(buf));
- if (readFromFile(BATTERY_TECHNOLOGY_PATH, buf, SIZE) > 0)
+ if (readFromFile(gPaths.batteryTechnologyPath, buf, SIZE) > 0)
env->SetObjectField(obj, gFieldIds.mBatteryTechnology, env->NewStringUTF(buf));
}
@@ -204,6 +228,101 @@
int register_android_server_BatteryService(JNIEnv* env)
{
+ char path[PATH_MAX];
+ struct dirent* entry;
+
+ DIR* dir = opendir(POWER_SUPPLY_PATH);
+ if (dir == NULL) {
+ LOGE("Could not open %s\n", POWER_SUPPLY_PATH);
+ return -1;
+ }
+ while ((entry = readdir(dir))) {
+ const char* name = entry->d_name;
+
+ // ignore "." and ".."
+ if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) {
+ continue;
+ }
+
+ char buf[20];
+ // Look for "type" file in each subdirectory
+ snprintf(path, sizeof(path), "%s/%s/type", POWER_SUPPLY_PATH, name);
+ int length = readFromFile(path, buf, sizeof(buf));
+ if (length > 0) {
+ if (buf[length - 1] == '\n')
+ buf[length - 1] = 0;
+
+ if (strcmp(buf, "Mains") == 0) {
+ snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
+ if (access(path, R_OK) == 0)
+ gPaths.acOnlinePath = strdup(path);
+ }
+ else if (strcmp(buf, "USB") == 0) {
+ snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
+ if (access(path, R_OK) == 0)
+ gPaths.usbOnlinePath = strdup(path);
+ }
+ else if (strcmp(buf, "Battery") == 0) {
+ snprintf(path, sizeof(path), "%s/%s/status", POWER_SUPPLY_PATH, name);
+ if (access(path, R_OK) == 0)
+ gPaths.batteryStatusPath = strdup(path);
+ snprintf(path, sizeof(path), "%s/%s/health", POWER_SUPPLY_PATH, name);
+ if (access(path, R_OK) == 0)
+ gPaths.batteryHealthPath = strdup(path);
+ snprintf(path, sizeof(path), "%s/%s/present", POWER_SUPPLY_PATH, name);
+ if (access(path, R_OK) == 0)
+ gPaths.batteryPresentPath = strdup(path);
+ snprintf(path, sizeof(path), "%s/%s/capacity", POWER_SUPPLY_PATH, name);
+ if (access(path, R_OK) == 0)
+ gPaths.batteryCapacityPath = strdup(path);
+
+ snprintf(path, sizeof(path), "%s/%s/voltage_now", POWER_SUPPLY_PATH, name);
+ if (access(path, R_OK) == 0) {
+ gPaths.batteryVoltagePath = strdup(path);
+ // voltage_now is in microvolts, not millivolts
+ gVoltageDivisor = 1000;
+ } else {
+ snprintf(path, sizeof(path), "%s/%s/batt_vol", POWER_SUPPLY_PATH, name);
+ if (access(path, R_OK) == 0)
+ gPaths.batteryVoltagePath = strdup(path);
+ }
+
+ snprintf(path, sizeof(path), "%s/%s/temp", POWER_SUPPLY_PATH, name);
+ if (access(path, R_OK) == 0) {
+ gPaths.batteryTemperaturePath = strdup(path);
+ } else {
+ snprintf(path, sizeof(path), "%s/%s/batt_temp", POWER_SUPPLY_PATH, name);
+ if (access(path, R_OK) == 0)
+ gPaths.batteryTemperaturePath = strdup(path);
+ }
+
+ snprintf(path, sizeof(path), "%s/%s/technology", POWER_SUPPLY_PATH, name);
+ if (access(path, R_OK) == 0)
+ gPaths.batteryTechnologyPath = strdup(path);
+ }
+ }
+ }
+ closedir(dir);
+
+ if (!gPaths.acOnlinePath)
+ LOGE("acOnlinePath not found");
+ if (!gPaths.usbOnlinePath)
+ LOGE("usbOnlinePath not found");
+ if (!gPaths.batteryStatusPath)
+ LOGE("batteryStatusPath not found");
+ if (!gPaths.batteryHealthPath)
+ LOGE("batteryHealthPath not found");
+ if (!gPaths.batteryPresentPath)
+ LOGE("batteryPresentPath not found");
+ if (!gPaths.batteryCapacityPath)
+ LOGE("batteryCapacityPath not found");
+ if (!gPaths.batteryVoltagePath)
+ LOGE("batteryVoltagePath not found");
+ if (!gPaths.batteryTemperaturePath)
+ LOGE("batteryTemperaturePath not found");
+ if (!gPaths.batteryTechnologyPath)
+ LOGE("batteryTechnologyPath not found");
+
jclass clazz = env->FindClass("com/android/server/BatteryService");
if (clazz == NULL) {
diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
index a3f1ad8..29e89b5 100644
--- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java
@@ -24,14 +24,18 @@
import android.os.RemoteException;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
+import android.text.TextUtils;
import android.util.Log;
+import java.util.ArrayList;
+
/**
* {@hide}
*
*/
public abstract class DataConnectionTracker extends Handler {
- private static final boolean DBG = true;
+ protected static final boolean DBG = true;
+ protected final String LOG_TAG = "DataConnectionTracker";
/**
* IDLE: ready to start data connection setup, default state
@@ -94,9 +98,24 @@
protected static final int EVENT_PS_RESTRICT_ENABLED = 32;
protected static final int EVENT_PS_RESTRICT_DISABLED = 33;
public static final int EVENT_CLEAN_UP_CONNECTION = 34;
+ protected static final int EVENT_CDMA_OTA_PROVISION = 35;
//***** Constants
+ protected static final int APN_INVALID_ID = -1;
+ protected static final int APN_DEFAULT_ID = 0;
+ protected static final int APN_MMS_ID = 1;
+ protected static final int APN_SUPL_ID = 2;
+ protected static final int APN_DUN_ID = 3;
+ protected static final int APN_HIPRI_ID = 4;
+ protected static final int APN_NUM_TYPES = 5;
+
+ protected boolean[] dataEnabled = new boolean[APN_NUM_TYPES];
+ protected int enabledCount = 0;
+
+ /* Currently requested APN type */
+ protected String mRequestedApnType = Phone.APN_TYPE_DEFAULT;
+
/** Retry configuration: A doubling of retry times from 5secs to 30minutes */
protected static final String DEFAULT_DATA_RETRY_CONFIG = "default_randomization=2000,"
+ "5000,10000,20000,40000,80000:5000,160000:5000,"
@@ -146,6 +165,9 @@
protected int mNoRecvPollCount = 0;
protected boolean netStatPollEnabled = false;
+ /** Manage the behavior of data retry after failure */
+ protected final RetryManager mRetryMgr = new RetryManager();
+
// wifi connection status will be updated by sticky intent
protected boolean mIsWifiConnected = false;
@@ -163,6 +185,8 @@
this.phone = phone;
}
+ public abstract void dispose();
+
public Activity getActivity() {
return activity;
}
@@ -202,10 +226,13 @@
if (getDataOnRoamingEnabled() != enabled) {
Settings.Secure.putInt(phone.getContext().getContentResolver(),
Settings.Secure.DATA_ROAMING, enabled ? 1 : 0);
+ if (phone.getServiceState().getRoaming()) {
+ if (enabled) {
+ mRetryMgr.resetRetryCount();
+ }
+ sendMessage(obtainMessage(EVENT_ROAMING_ON));
+ }
}
- Message roamingMsg = phone.getServiceState().getRoaming() ?
- obtainMessage(EVENT_ROAMING_ON) : obtainMessage(EVENT_ROAMING_OFF);
- sendMessage(roamingMsg);
}
//Retrieve the data roaming setting from the shared preferences.
@@ -243,6 +270,9 @@
break;
case EVENT_ROAMING_OFF:
+ if (getDataOnRoamingEnabled() == false) {
+ mRetryMgr.resetRetryCount();
+ }
onRoamingOff();
break;
@@ -291,24 +321,18 @@
* @return {@code false} if data connectivity has been explicitly disabled,
* {@code true} otherwise.
*/
- public abstract boolean getDataEnabled();
+ public boolean getDataEnabled() {
+ return dataEnabled[APN_DEFAULT_ID];
+ }
/**
* Report on whether data connectivity is enabled
* @return {@code false} if data connectivity has been explicitly disabled,
* {@code true} otherwise.
*/
- public abstract boolean getAnyDataEnabled();
-
- /**
- * Prevent mobile data connections from being established,
- * or once again allow mobile data connections. If the state
- * toggles, then either tear down or set up data, as
- * appropriate to match the new state.
- * @param enable indicates whether to enable ({@code true}) or disable ({@code false}) data
- * @return {@code true} if the operation succeeded
- */
- public abstract boolean setDataEnabled(boolean enable);
+ public boolean getAnyDataEnabled() {
+ return (enabledCount != 0);
+ }
protected abstract void startNetStatPoll();
@@ -317,4 +341,162 @@
protected abstract void restartRadio();
protected abstract void log(String s);
+
+ protected int apnTypeToId(String type) {
+ if (TextUtils.equals(type, Phone.APN_TYPE_DEFAULT)) {
+ return APN_DEFAULT_ID;
+ } else if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
+ return APN_MMS_ID;
+ } else if (TextUtils.equals(type, Phone.APN_TYPE_SUPL)) {
+ return APN_SUPL_ID;
+ } else if (TextUtils.equals(type, Phone.APN_TYPE_DUN)) {
+ return APN_DUN_ID;
+ } else if (TextUtils.equals(type, Phone.APN_TYPE_HIPRI)) {
+ return APN_HIPRI_ID;
+ } else {
+ return APN_INVALID_ID;
+ }
+ }
+
+ protected abstract boolean isApnTypeActive(String type);
+
+ protected abstract boolean isApnTypeAvailable(String type);
+
+ protected abstract String[] getActiveApnTypes();
+
+ protected abstract String getActiveApnString();
+
+ public abstract ArrayList<DataConnection> getAllDataConnections();
+
+ protected abstract String getInterfaceName(String apnType);
+
+ protected abstract String getIpAddress(String apnType);
+
+ protected abstract String getGateway(String apnType);
+
+ protected abstract String[] getDnsServers(String apnType);
+
+ protected abstract void setState(State s);
+
+ protected boolean isEnabled(int id) {
+ if (id != APN_INVALID_ID) {
+ return dataEnabled[id];
+ }
+ return false;
+ }
+
+ /**
+ * Ensure that we are connected to an APN of the specified type.
+ * @param type the APN type (currently the only valid values
+ * are {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL})
+ * @return the result of the operation. Success is indicated by
+ * a return value of either {@code Phone.APN_ALREADY_ACTIVE} or
+ * {@code Phone.APN_REQUEST_STARTED}. In the latter case, a broadcast
+ * will be sent by the ConnectivityManager when a connection to
+ * the APN has been established.
+ */
+ public int enableApnType(String type) {
+ int id = apnTypeToId(type);
+ if (id == APN_INVALID_ID) {
+ return Phone.APN_REQUEST_FAILED;
+ }
+
+ // If already active, return
+ if(DBG) Log.d(LOG_TAG, "enableApnType("+type+"), isApnTypeActive = "
+ + isApnTypeActive(type) + " and state = " + state);
+
+ if (isApnTypeActive(type)) {
+ if (state == State.INITING) return Phone.APN_REQUEST_STARTED;
+ else if (state == State.CONNECTED) return Phone.APN_ALREADY_ACTIVE;
+ }
+
+ if (!isApnTypeAvailable(type)) {
+ return Phone.APN_TYPE_NOT_AVAILABLE;
+ }
+
+ setEnabled(id, true);
+ mRequestedApnType = type;
+ sendMessage(obtainMessage(EVENT_ENABLE_NEW_APN));
+ return Phone.APN_REQUEST_STARTED;
+ }
+
+ /**
+ * The APN of the specified type is no longer needed. Ensure that if
+ * use of the default APN has not been explicitly disabled, we are connected
+ * to the default APN.
+ * @param type the APN type. The only valid values are currently
+ * {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}.
+ * @return
+ */
+ public int disableApnType(String type) {
+ if (DBG) Log.d(LOG_TAG, "disableApnType("+type+")");
+ int id = apnTypeToId(type);
+ if (id == APN_INVALID_ID) {
+ return Phone.APN_REQUEST_FAILED;
+ }
+ if (isEnabled(id)) {
+ setEnabled(id, false);
+ if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
+ mRequestedApnType = Phone.APN_TYPE_DEFAULT;
+ if (dataEnabled[APN_DEFAULT_ID]) {
+ return Phone.APN_ALREADY_ACTIVE;
+ } else {
+ return Phone.APN_REQUEST_STARTED;
+ }
+ } else {
+ return Phone.APN_REQUEST_STARTED;
+ }
+ } else {
+ return Phone.APN_REQUEST_FAILED;
+ }
+ }
+
+ protected synchronized void setEnabled(int id, boolean enable) {
+ if (DBG) Log.d(LOG_TAG, "setEnabled(" + id + ", " + enable + ')');
+ if (dataEnabled[id] != enable) {
+ dataEnabled[id] = enable;
+
+ if (enable) {
+ enabledCount++;
+ } else {
+ enabledCount--;
+ }
+
+ if (enabledCount == 0) {
+ setPrivateDataEnabled(false);
+ } else if (enabledCount == 1) {
+ setPrivateDataEnabled(true);
+ }
+ }
+ }
+
+ /**
+ * Prevent mobile data connections from being established,
+ * or once again allow mobile data connections. If the state
+ * toggles, then either tear down or set up data, as
+ * appropriate to match the new state.
+ * <p>This operation only affects the default APN, and if the same APN is
+ * currently being used for MMS traffic, the teardown will not happen
+ * even when {@code enable} is {@code false}.</p>
+ * @param enable indicates whether to enable ({@code true}) or disable ({@code false}) data
+ * @return {@code true} if the operation succeeded
+ */
+ public boolean setDataEnabled(boolean enable) {
+ if (DBG) Log.d(LOG_TAG, "setDataEnabled("+enable+")");
+ setEnabled(APN_DEFAULT_ID, enable);
+ return true;
+ }
+
+ private void setPrivateDataEnabled(boolean enable) {
+ if (DBG) Log.d(LOG_TAG, "setPrivateDataEnabled("+enable+")");
+ if (enable) {
+ sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
+ } else {
+ Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
+ msg.arg1 = 1; // tearDown is true
+ msg.obj = Phone.REASON_DATA_DISABLED;
+ sendMessage(msg);
+ }
+ }
+
}
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index b279527..6f4aef9 100644
--- a/telephony/java/com/android/internal/telephony/PhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/PhoneBase.java
@@ -109,6 +109,7 @@
public CommandsInterface mCM;
protected IccFileHandler mIccFileHandler;
boolean mDnsCheckDisabled = false;
+ public DataConnectionTracker mDataConnection;
/**
* Set a system property, unless we're in unit test mode
@@ -824,4 +825,71 @@
// This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
Log.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
}
+
+ public String getInterfaceName(String apnType) {
+ return mDataConnection.getInterfaceName(apnType);
+ }
+
+ public String getIpAddress(String apnType) {
+ return mDataConnection.getIpAddress(apnType);
+ }
+
+ public boolean isDataConnectivityEnabled() {
+ return mDataConnection.getDataEnabled();
+ }
+
+ public String getGateway(String apnType) {
+ return mDataConnection.getGateway(apnType);
+ }
+
+ public String[] getDnsServers(String apnType) {
+ return mDataConnection.getDnsServers(apnType);
+ }
+
+ public String[] getActiveApnTypes() {
+ return mDataConnection.getActiveApnTypes();
+ }
+
+ public String getActiveApn() {
+ return mDataConnection.getActiveApnString();
+ }
+
+ public int enableApnType(String type) {
+ return mDataConnection.enableApnType(type);
+ }
+
+ public int disableApnType(String type) {
+ return mDataConnection.disableApnType(type);
+ }
+
+ /**
+ * simulateDataConnection
+ *
+ * simulates various data connection states. This messes with
+ * DataConnectionTracker's internal states, but doesn't actually change
+ * the underlying radio connection states.
+ *
+ * @param state Phone.DataState enum.
+ */
+ public void simulateDataConnection(Phone.DataState state) {
+ DataConnectionTracker.State dcState;
+
+ switch (state) {
+ case CONNECTED:
+ dcState = DataConnectionTracker.State.CONNECTED;
+ break;
+ case SUSPENDED:
+ dcState = DataConnectionTracker.State.CONNECTED;
+ break;
+ case DISCONNECTED:
+ dcState = DataConnectionTracker.State.FAILED;
+ break;
+ default:
+ dcState = DataConnectionTracker.State.CONNECTING;
+ break;
+ }
+
+ mDataConnection.setState(dcState);
+ notifyDataConnection(null);
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
index 46b39a5..39806e9 100644
--- a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -116,6 +116,7 @@
protected static final int EVENT_NV_READY = 35;
protected static final int EVENT_ERI_FILE_LOADED = 36;
protected static final int EVENT_OTA_PROVISION_STATUS_CHANGE = 37;
+ protected static final int EVENT_SET_RADIO_POWER_OFF = 38;
//***** Time Zones
protected static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
index 522fa1d..f0c0ea2 100755
--- a/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMAPhone.java
@@ -95,7 +95,6 @@
CdmaCallTracker mCT;
CdmaSMSDispatcher mSMS;
CdmaServiceStateTracker mSST;
- CdmaDataConnectionTracker mDataConnection;
RuimFileHandler mRuimFileHandler;
RuimRecords mRuimRecords;
RuimCard mRuimCard;
@@ -369,42 +368,11 @@
return mCT.backgroundCall;
}
- public String getGateway(String apnType) {
- return mDataConnection.getGateway();
- }
-
public boolean handleInCallMmiCommands(String dialString) {
Log.e(LOG_TAG, "method handleInCallMmiCommands is NOT supported in CDMA!");
return false;
}
- public int enableApnType(String type) {
- // This request is mainly used to enable MMS APN
- // In CDMA there is no need to enable/disable a different APN for MMS
- Log.d(LOG_TAG, "Request to enableApnType("+type+")");
- if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
- return Phone.APN_ALREADY_ACTIVE;
- } else {
- return Phone.APN_REQUEST_FAILED;
- }
- }
-
- public int disableApnType(String type) {
- // This request is mainly used to disable MMS APN
- // In CDMA there is no need to enable/disable a different APN for MMS
- Log.d(LOG_TAG, "Request to disableApnType("+type+")");
- if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
- return Phone.APN_REQUEST_STARTED;
- } else {
- return Phone.APN_REQUEST_FAILED;
- }
- }
-
- public String getActiveApn() {
- Log.d(LOG_TAG, "Request to getActiveApn()");
- return null;
- }
-
public void
setNetworkSelectionModeAutomatic(Message response) {
Log.e(LOG_TAG, "method setNetworkSelectionModeAutomatic is NOT supported in CDMA!");
@@ -481,10 +449,6 @@
return false;
}
- public String getInterfaceName(String apnType) {
- return mDataConnection.getInterfaceName();
- }
-
public CellLocation getCellLocation() {
return mSST.cellLoc;
}
@@ -512,10 +476,6 @@
return false;
}
- public boolean isDataConnectivityEnabled() {
- return mDataConnection.getDataEnabled();
- }
-
public boolean isDataConnectivityPossible() {
boolean noData = mDataConnection.getDataEnabled() &&
getDataConnectionState() == DataState.DISCONNECTED;
@@ -528,10 +488,6 @@
Log.e(LOG_TAG, "setLine1Number: not possible in CDMA");
}
- public String[] getDnsServers(String apnType) {
- return mDataConnection.getDnsServers();
- }
-
public IccCard getIccCard() {
return mRuimCard;
}
@@ -584,10 +540,6 @@
mCT.unregisterForCallWaiting(h);
}
- public String getIpAddress(String apnType) {
- return mDataConnection.getIpAddress();
- }
-
public void
getNeighboringCids(Message response) {
/*
@@ -701,14 +653,6 @@
Log.e(LOG_TAG, "getAvailableNetworks: not possible in CDMA");
}
- public String[] getActiveApnTypes() {
- String[] result;
- Log.d(LOG_TAG, "Request to getActiveApn()");
- result = new String[1];
- result[0] = Phone.APN_TYPE_DEFAULT;
- return result;
- }
-
public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete) {
Log.e(LOG_TAG, "setOutgoingCallerIdDisplay: not possible in CDMA");
}
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index 38bc24d..d02d33e 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -48,6 +48,7 @@
import com.android.internal.telephony.DataConnectionTracker;
import com.android.internal.telephony.RetryManager;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.TelephonyEventLog;
import java.util.ArrayList;
@@ -56,8 +57,7 @@
* {@hide}
*/
public final class CdmaDataConnectionTracker extends DataConnectionTracker {
- private static final String LOG_TAG = "CDMA";
- private static final boolean DBG = true;
+ protected final String LOG_TAG = "CDMA";
private CDMAPhone mCdmaPhone;
@@ -76,15 +76,6 @@
/** Currently active CdmaDataConnection */
private CdmaDataConnection mActiveDataConnection;
- /** Manage the behavior of data retry after failure */
- private final RetryManager mRetryMgr = new RetryManager();
-
- /** Defined cdma connection profiles */
- private static final int EXTERNAL_NETWORK_DEFAULT_ID = 0;
- private static final int EXTERNAL_NETWORK_NUM_TYPES = 1;
-
- private boolean[] dataEnabled = new boolean[EXTERNAL_NETWORK_NUM_TYPES];
-
/**
* Pool size of CdmaDataConnection objects.
*/
@@ -103,6 +94,11 @@
private static final int DATA_CONNECTION_ACTIVE_PH_LINK_DOWN = 1;
private static final int DATA_CONNECTION_ACTIVE_PH_LINK_UP = 2;
+ private static final String[] mSupportedApnTypes = {
+ Phone.APN_TYPE_DEFAULT,
+ Phone.APN_TYPE_MMS,
+ Phone.APN_TYPE_HIPRI };
+
// Possibly promoate to base class, the only difference is
// the INTENT_RECONNECT_ALARM action is a different string.
// Do consider technology changes if it is promoted.
@@ -163,6 +159,7 @@
p.mSST.registerForCdmaDataConnectionDetached(this, EVENT_CDMA_DATA_DETACHED, null);
p.mSST.registerForRoamingOn(this, EVENT_ROAMING_ON, null);
p.mSST.registerForRoamingOff(this, EVENT_ROAMING_OFF, null);
+ p.mCM.registerForCdmaOtaProvision(this, EVENT_CDMA_OTA_PROVISION, null);
this.netstat = INetStatService.Stub.asInterface(ServiceManager.getService("netstat"));
@@ -183,9 +180,12 @@
// and 2) whether the RIL will setup the baseband to auto-PS attach.
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
- dataEnabled[EXTERNAL_NETWORK_DEFAULT_ID] =
+ dataEnabled[APN_DEFAULT_ID] =
!sp.getBoolean(CDMAPhone.DATA_DISABLED_ON_BOOT_KEY, false);
- noAutoAttach = !dataEnabled[EXTERNAL_NETWORK_DEFAULT_ID];
+ if (dataEnabled[APN_DEFAULT_ID]) {
+ enabledCount++;
+ }
+ noAutoAttach = !dataEnabled[APN_DEFAULT_ID];
if (!mRetryMgr.configure(SystemProperties.get("ro.cdma.data_retry_config"))) {
if (!mRetryMgr.configure(DEFAULT_DATA_RETRY_CONFIG)) {
@@ -210,6 +210,7 @@
mCdmaPhone.mSST.unregisterForCdmaDataConnectionDetached(this);
mCdmaPhone.mSST.unregisterForRoamingOn(this);
mCdmaPhone.mSST.unregisterForRoamingOff(this);
+ phone.mCM.unregisterForCdmaOtaProvision(this);
phone.getContext().unregisterReceiver(this.mIntentReceiver);
destroyAllDataConnectionList();
@@ -219,7 +220,7 @@
if(DBG) Log.d(LOG_TAG, "CdmaDataConnectionTracker finalized");
}
- void setState(State s) {
+ protected void setState(State s) {
if (DBG) log ("setState: " + s);
if (state != s) {
if (s == State.INITING) { // request Data connection context
@@ -236,39 +237,33 @@
state = s;
}
- public int enableApnType(String type) {
- // This request is mainly used to enable MMS APN
- // In CDMA there is no need to enable/disable a different APN for MMS
- Log.d(LOG_TAG, "Request to enableApnType("+type+")");
- if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
- return Phone.APN_ALREADY_ACTIVE;
- } else if (TextUtils.equals(type, Phone.APN_TYPE_SUPL)) {
- Log.w(LOG_TAG, "Phone.APN_TYPE_SUPL not enabled for CDMA");
- return Phone.APN_REQUEST_FAILED;
- } else {
- return Phone.APN_REQUEST_FAILED;
+ @Override
+ protected boolean isApnTypeActive(String type) {
+ return (isApnTypeAvailable(type) &&
+ mCdmaPhone.mSST.getCurrentCdmaDataConnectionState() ==
+ ServiceState.STATE_IN_SERVICE);
+ }
+
+ @Override
+ protected boolean isApnTypeAvailable(String type) {
+ for (String s : mSupportedApnTypes) {
+ if (TextUtils.equals(type, s)) {
+ return true;
+ }
}
+ return false;
}
- public int disableApnType(String type) {
- // This request is mainly used to disable MMS APN
- // In CDMA there is no need to enable/disable a different APN for MMS
- Log.d(LOG_TAG, "Request to disableApnType("+type+")");
- if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
- return Phone.APN_REQUEST_STARTED;
- } else {
- return Phone.APN_REQUEST_FAILED;
+ protected String[] getActiveApnTypes() {
+ if (mCdmaPhone.mSST.getCurrentCdmaDataConnectionState() ==
+ ServiceState.STATE_IN_SERVICE) {
+ return mSupportedApnTypes.clone();
}
+ return new String[0];
}
- private boolean isEnabled(int cdmaDataProfile) {
- return dataEnabled[cdmaDataProfile];
- }
-
- private void setEnabled(int cdmaDataProfile, boolean enable) {
- Log.d(LOG_TAG, "setEnabled(" + cdmaDataProfile + ", " + enable + ')');
- dataEnabled[cdmaDataProfile] = enable;
- Log.d(LOG_TAG, "dataEnabled[DEFAULT_PROFILE]=" + dataEnabled[EXTERNAL_NETWORK_DEFAULT_ID]);
+ protected String getActiveApnString() {
+ return null;
}
/**
@@ -294,54 +289,6 @@
return true;
}
- /**
- * Prevent mobile data connections from being established,
- * or once again allow mobile data connections. If the state
- * toggles, then either tear down or set up data, as
- * appropriate to match the new state.
- * <p>This operation only affects the default connection
- * @param enable indicates whether to enable ({@code true}) or disable ({@code false}) data
- * @return {@code true} if the operation succeeded
- */
- public boolean setDataEnabled(boolean enable) {
-
- boolean isEnabled = isEnabled(EXTERNAL_NETWORK_DEFAULT_ID);
-
- Log.d(LOG_TAG, "setDataEnabled("+enable+") isEnabled=" + isEnabled);
- if (!isEnabled && enable) {
- setEnabled(EXTERNAL_NETWORK_DEFAULT_ID, true);
- sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
- } else if (!enable) {
- setEnabled(EXTERNAL_NETWORK_DEFAULT_ID, false);
- Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
- msg.arg1 = 1; // tearDown is true
- msg.obj = Phone.REASON_DATA_DISABLED;
- sendMessage(msg);
- }
- return true;
- }
-
- /**
- * Report the current state of data connectivity (enabled or disabled)
- * @return {@code false} if data connectivity has been explicitly disabled,
- * {@code true} otherwise.
- */
- public boolean getDataEnabled() {
- return dataEnabled[EXTERNAL_NETWORK_DEFAULT_ID];
- }
-
- /**
- * Report on whether data connectivity is enabled
- * @return {@code false} if data connectivity has been explicitly disabled,
- * {@code true} otherwise.
- */
- public boolean getAnyDataEnabled() {
- for (int i=0; i < EXTERNAL_NETWORK_NUM_TYPES; i++) {
- if (isEnabled(i)) return true;
- }
- return false;
- }
-
private boolean isDataAllowed() {
boolean roaming = phone.getServiceState().getRoaming();
return getAnyDataEnabled() && (!roaming || getDataOnRoamingEnabled());
@@ -499,7 +446,7 @@
protected void restartRadio() {
Log.d(LOG_TAG, "************TURN OFF RADIO**************");
- cleanUpConnection(true, Phone.REASON_RADIO_TURNED_OFF);
+ cleanUpConnection(true, Phone.REASON_CDMA_DATA_DETACHED);
phone.mCM.setRadioPower(false, null);
/* Note: no need to call setRadioPower(true). Assuming the desired
* radio power state is still ON (as tracked by ServiceStateTracker),
@@ -771,6 +718,10 @@
reason = (String) ar.userObj;
}
setState(State.IDLE);
+
+ CdmaServiceStateTracker ssTracker = mCdmaPhone.mSST;
+ ssTracker.processPendingRadioPowerOffAfterDataOff();
+
phone.notifyDataConnection(reason);
if (retryAfterDisconnected(reason)) {
trySetupData(reason);
@@ -849,6 +800,22 @@
}
}
+ private void onCdmaOtaProvision(AsyncResult ar) {
+ if (ar.exception != null) {
+ int [] otaPrivision = (int [])ar.result;
+ if ((otaPrivision != null) && (otaPrivision.length > 1)) {
+ switch (otaPrivision[0]) {
+ case Phone.CDMA_OTA_PROVISION_STATUS_COMMITTED:
+ case Phone.CDMA_OTA_PROVISION_STATUS_OTAPA_STOPPED:
+ mRetryMgr.resetRetryCount();
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
private void writeEventLogCdmaDataDrop() {
CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation());
int bsid = (loc != null) ? loc.getBaseStationId() : -1;
@@ -901,28 +868,28 @@
}
}
- String getInterfaceName() {
+ protected String getInterfaceName(String apnType) {
if (mActiveDataConnection != null) {
return mActiveDataConnection.getInterface();
}
return null;
}
- protected String getIpAddress() {
+ protected String getIpAddress(String apnType) {
if (mActiveDataConnection != null) {
return mActiveDataConnection.getIpAddress();
}
return null;
}
- String getGateway() {
+ protected String getGateway(String apnType) {
if (mActiveDataConnection != null) {
return mActiveDataConnection.getGatewayAddress();
}
return null;
}
- protected String[] getDnsServers() {
+ protected String[] getDnsServers(String apnType) {
if (mActiveDataConnection != null) {
return mActiveDataConnection.getDnsServers();
}
@@ -957,6 +924,10 @@
onDataStateChanged((AsyncResult) msg.obj);
break;
+ case EVENT_CDMA_OTA_PROVISION:
+ onCdmaOtaProvision((AsyncResult) msg.obj);
+ break;
+
default:
// handle the message in the super class DataConnectionTracker
super.handleMessage(msg);
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index b42cffd..b4de09b 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -131,6 +131,8 @@
private boolean isEriTextLoaded = false;
private boolean isSubscriptionFromRuim = false;
+ private boolean mPendingRadioPowerOffAfterDataOff = false;
+
// Registration Denied Reason, General/Authentication Failure, used only for debugging purposes
private String mRegistrationDeniedReason;
@@ -520,6 +522,16 @@
}
break;
+ case EVENT_SET_RADIO_POWER_OFF:
+ synchronized(this) {
+ if (mPendingRadioPowerOffAfterDataOff) {
+ if (DBG) log("EVENT_SET_RADIO_OFF, turn radio off now.");
+ cm.setRadioPower(false, null);
+ mPendingRadioPowerOffAfterDataOff = false;
+ }
+ }
+ break;
+
default:
Log.e(LOG_TAG, "Unhandled message with number: " + msg.what);
break;
@@ -548,20 +560,23 @@
msg.obj = CDMAPhone.REASON_RADIO_TURNED_OFF;
dcTracker.sendMessage(msg);
- // Poll data state up to 50 times, with a 100ms delay
- // totaling 5 sec.
- // TODO: change the 5 seconds wait from blocking to non-blocking.
- for (int i = 0; i < 50; i++) {
- DataConnectionTracker.State currentState = dcTracker.getState();
- if (currentState != DataConnectionTracker.State.CONNECTED
- && currentState != DataConnectionTracker.State.DISCONNECTING) {
- if (DBG) log("Data shutdown complete.");
- break;
+ synchronized(this) {
+ if (!mPendingRadioPowerOffAfterDataOff) {
+ DataConnectionTracker.State currentState = dcTracker.getState();
+ if (currentState != DataConnectionTracker.State.CONNECTED
+ && currentState != DataConnectionTracker.State.DISCONNECTING) {
+ if (DBG) log("Data disconnected, turn off radio right away.");
+ cm.setRadioPower(false, null);
+ }
+ else if (sendEmptyMessageDelayed(EVENT_SET_RADIO_POWER_OFF, 5000)) {
+ if (DBG) log("Wait 5 sec for data to be disconnected, then turn off radio.");
+ mPendingRadioPowerOffAfterDataOff = true;
+ } else {
+ Log.w(LOG_TAG, "Cannot send delayed Msg, turn off radio right away.");
+ cm.setRadioPower(false, null);
+ }
}
- SystemClock.sleep(DATA_STATE_POLL_SLEEP_MS);
}
- // If it's on and available and we want it off..
- cm.setRadioPower(false, null);
} // Otherwise, we're in the desired state
}
@@ -1582,4 +1597,22 @@
public boolean isMinInfoReady() {
return mIsMinInfoReady;
}
+
+ /**
+ * process the pending request to turn radio off after data is disconnected
+ *
+ * return true if there is pending request to process; false otherwise.
+ */
+ public boolean processPendingRadioPowerOffAfterDataOff() {
+ synchronized(this) {
+ if (mPendingRadioPowerOffAfterDataOff) {
+ if (DBG) log("Process pending request to turn radio off.");
+ removeMessages(EVENT_SET_RADIO_POWER_OFF);
+ cm.setRadioPower(false, null);
+ mPendingRadioPowerOffAfterDataOff = false;
+ return true;
+ }
+ return false;
+ }
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
index 94d4344..bb04a43 100755
--- a/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -102,7 +102,6 @@
GsmCallTracker mCT;
GsmServiceStateTracker mSST;
GsmSMSDispatcher mSMS;
- GsmDataConnectionTracker mDataConnection;
SIMRecords mSIMRecords;
SimCard mSimCard;
StkService mStkService;
@@ -280,14 +279,6 @@
return "GSM";
}
- public String[] getActiveApnTypes() {
- return mDataConnection.getActiveApnTypes();
- }
-
- public String getActiveApn() {
- return mDataConnection.getActiveApnString();
- }
-
public SignalStrength getSignalStrength() {
return mSST.mSignalStrength;
}
@@ -1145,38 +1136,10 @@
return mDataConnection.setDataEnabled(true);
}
- public int enableApnType(String type) {
- return mDataConnection.enableApnType(type);
- }
-
- public int disableApnType(String type) {
- return mDataConnection.disableApnType(type);
- }
-
public boolean disableDataConnectivity() {
return mDataConnection.setDataEnabled(false);
}
- public String getInterfaceName(String apnType) {
- return mDataConnection.getInterfaceName(apnType);
- }
-
- public String getIpAddress(String apnType) {
- return mDataConnection.getIpAddress(apnType);
- }
-
- public String getGateway(String apnType) {
- return mDataConnection.getGateway(apnType);
- }
-
- public String[] getDnsServers(String apnType) {
- return mDataConnection.getDnsServers(apnType);
- }
-
- public boolean isDataConnectivityEnabled() {
- return mDataConnection.getDataEnabled();
- }
-
/**
* The only circumstances under which we report that data connectivity is not
* possible are
@@ -1543,36 +1506,6 @@
}
}
}
- /**
- * simulateDataConnection
- *
- * simulates various data connection states. This messes with
- * DataConnectionTracker's internal states, but doesn't actually change
- * the underlying radio connection states.
- *
- * @param state Phone.DataState enum.
- */
- public void simulateDataConnection(Phone.DataState state) {
- DataConnectionTracker.State dcState;
-
- switch (state) {
- case CONNECTED:
- dcState = DataConnectionTracker.State.CONNECTED;
- break;
- case SUSPENDED:
- dcState = DataConnectionTracker.State.CONNECTED;
- break;
- case DISCONNECTED:
- dcState = DataConnectionTracker.State.FAILED;
- break;
- default:
- dcState = DataConnectionTracker.State.CONNECTING;
- break;
- }
-
- mDataConnection.setState(dcState);
- notifyDataConnection(null);
- }
/**
* Retrieves the PhoneSubInfo of the GSMPhone
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index bf60bfe..b9688f3 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -63,8 +63,7 @@
* {@hide}
*/
public final class GsmDataConnectionTracker extends DataConnectionTracker {
- private static final String LOG_TAG = "GSM";
- private static final boolean DBG = true;
+ protected final String LOG_TAG = "GSM";
private GSMPhone mGsmPhone;
/**
@@ -96,8 +95,6 @@
private int mPdpResetCount = 0;
private boolean mIsScreenOn = true;
- private final RetryManager mRetryMgr = new RetryManager();
-
/** Delay between APN attempts */
protected static final int APN_DELAY_MILLIS = 5000;
@@ -121,31 +118,17 @@
private ApnSetting preferredApn = null;
+ /* Currently active APN */
+ protected ApnSetting mActiveApn;
+
/**
* pdpList holds all the PDP connection, i.e. IP Link in GPRS
*/
private ArrayList<DataConnection> pdpList;
- /** Currently requested APN type */
- private String mRequestedApnType = Phone.APN_TYPE_DEFAULT;
-
- /** Currently active APN */
- private ApnSetting mActiveApn;
-
/** Currently active PdpConnection */
private PdpConnection mActivePdp;
- private static int APN_INVALID_ID = -1;
- private static int APN_DEFAULT_ID = 0;
- private static int APN_MMS_ID = 1;
- private static int APN_SUPL_ID = 2;
- private static int APN_DUN_ID = 3;
- private static int APN_HIPRI_ID = 4;
- private static int APN_NUM_TYPES = 5;
-
- private boolean[] dataEnabled = new boolean[APN_NUM_TYPES];
- private int enabledCount = 0;
-
/** Is packet service restricted by network */
private boolean mIsPsRestricted = false;
@@ -295,7 +278,7 @@
if(DBG) Log.d(LOG_TAG, "GsmDataConnectionTracker finalized");
}
- void setState(State s) {
+ protected void setState(State s) {
if (DBG) log ("setState: " + s);
if (state != s) {
if (s == State.INITING) { // request PDP context
@@ -319,7 +302,7 @@
}
}
- String[] getActiveApnTypes() {
+ public String[] getActiveApnTypes() {
String[] result;
if (mActiveApn != null) {
result = mActiveApn.types;
@@ -338,87 +321,6 @@
return result;
}
- protected int apnTypeToId(String type) {
- if (TextUtils.equals(type, Phone.APN_TYPE_DEFAULT)) {
- return APN_DEFAULT_ID;
- } else if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
- return APN_MMS_ID;
- } else if (TextUtils.equals(type, Phone.APN_TYPE_SUPL)) {
- return APN_SUPL_ID;
- } else if (TextUtils.equals(type, Phone.APN_TYPE_DUN)) {
- return APN_DUN_ID;
- } else if (TextUtils.equals(type, Phone.APN_TYPE_HIPRI)) {
- return APN_HIPRI_ID;
- } else {
- return APN_INVALID_ID;
- }
- }
-
- /**
- * Ensure that we are connected to an APN of the specified type.
- * @param type the APN type (currently the only valid values
- * are {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL})
- * @return the result of the operation. Success is indicated by
- * a return value of either {@code Phone.APN_ALREADY_ACTIVE} or
- * {@code Phone.APN_REQUEST_STARTED}. In the latter case, a broadcast
- * will be sent by the ConnectivityManager when a connection to
- * the APN has been established.
- */
- protected int enableApnType(String type) {
- int id = apnTypeToId(type);
- if (id == APN_INVALID_ID) {
- return Phone.APN_REQUEST_FAILED;
- }
-
- // If already active, return
- if(DBG) Log.d(LOG_TAG, "enableApnType("+type+"), isApnTypeActive = "
- + isApnTypeActive(type) + " and state = " + state);
- if (isApnTypeActive(type)) {
- if (state == State.INITING) return Phone.APN_REQUEST_STARTED;
- else if (state == State.CONNECTED) return Phone.APN_ALREADY_ACTIVE;
- }
-
- if (!isApnTypeAvailable(type)) {
- return Phone.APN_TYPE_NOT_AVAILABLE;
- }
-
- setEnabled(id, true);
- mRequestedApnType = type;
- sendMessage(obtainMessage(EVENT_ENABLE_NEW_APN));
- return Phone.APN_REQUEST_STARTED;
- }
-
- /**
- * The APN of the specified type is no longer needed. Ensure that if
- * use of the default APN has not been explicitly disabled, we are connected
- * to the default APN.
- * @param type the APN type. The only valid values are currently
- * {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}.
- * @return
- */
- protected int disableApnType(String type) {
- if (DBG) Log.d(LOG_TAG, "disableApnType("+type+")");
- int id = apnTypeToId(type);
- if (id == APN_INVALID_ID) {
- return Phone.APN_REQUEST_FAILED;
- }
- if (isEnabled(id)) {
- setEnabled(id, false);
- if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
- mRequestedApnType = Phone.APN_TYPE_DEFAULT;
- if (dataEnabled[APN_DEFAULT_ID]) {
- return Phone.APN_ALREADY_ACTIVE;
- } else {
- return Phone.APN_REQUEST_STARTED;
- }
- } else {
- return Phone.APN_REQUEST_STARTED;
- }
- } else {
- return Phone.APN_REQUEST_FAILED;
- }
- }
-
/**
* The data connection is expected to be setup while device
* 1. has sim card
@@ -429,7 +331,7 @@
* @return false while no data connection if all above requirements are met.
*/
public boolean isDataConnectionAsDesired() {
- boolean roaming = phone.getServiceState().getRoaming();
+ boolean roaming = getDataRoaming();
if (mGsmPhone.mSIMRecords.getRecordsLoaded() &&
mGsmPhone.mSST.getCurrentGprsState() == ServiceState.STATE_IN_SERVICE &&
@@ -441,12 +343,18 @@
return true;
}
- private boolean isApnTypeActive(String type) {
- // TODO: to support simultaneous, mActiveApn can be a List instead.
+ private boolean getDataRoaming() {
+ return mGsmPhone.mSST.getDataRoaming();
+ }
+
+ @Override
+ protected boolean isApnTypeActive(String type) {
+ // TODO: support simultaneous with List instead
return mActiveApn != null && mActiveApn.canHandleType(type);
}
- private boolean isApnTypeAvailable(String type) {
+ @Override
+ protected boolean isApnTypeAvailable(String type) {
if (allApns != null) {
for (ApnSetting apn : allApns) {
if (apn.canHandleType(type)) {
@@ -457,80 +365,6 @@
return false;
}
- private boolean isEnabled(int id) {
- if (id != APN_INVALID_ID) {
- return dataEnabled[id];
- }
- return false;
- }
-
- private void setEnabled(int id, boolean enable) {
- if (DBG) Log.d(LOG_TAG, "setEnabled(" + id + ", " + enable + ')');
- if (dataEnabled[id] != enable) {
- dataEnabled[id] = enable;
-
- if (enable) {
- enabledCount++;
- } else {
- enabledCount--;
- }
-
- if (enabledCount == 0) {
- setPrivateDataEnabled(false);
- } else if (enabledCount == 1) {
- setPrivateDataEnabled(true);
- }
- }
- }
-
- /**
- * Prevent mobile data connections from being established,
- * or once again allow mobile data connections. If the state
- * toggles, then either tear down or set up data, as
- * appropriate to match the new state.
- * <p>This operation only affects the default APN, and if the same APN is
- * currently being used for MMS traffic, the teardown will not happen
- * even when {@code enable} is {@code false}.</p>
- * @param enable indicates whether to enable ({@code true}) or disable ({@code false}) data
- * @return {@code true} if the operation succeeded
- */
- public boolean setDataEnabled(boolean enable) {
- if (DBG) Log.d(LOG_TAG, "setDataEnabled("+enable+")");
- setEnabled(APN_DEFAULT_ID, enable);
- return true;
- }
-
- private void setPrivateDataEnabled(boolean enable) {
- if (DBG) Log.d(LOG_TAG, "setPrivateDataEnabled("+enable+")");
- if (enable) {
- sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
- } else {
- Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
- msg.arg1 = 1; // tearDown is true
- msg.obj = Phone.REASON_DATA_DISABLED;
- sendMessage(msg);
- }
- }
-
- /**
- * Report the current state of data connectivity (enabled or disabled) for
- * the default APN.
- * @return {@code false} if data connectivity has been explicitly disabled,
- * {@code true} otherwise.
- */
- public boolean getDataEnabled() {
- return dataEnabled[APN_DEFAULT_ID];
- }
-
- /**
- * Report on whether data connectivity is enabled for any APN.
- * @return {@code false} if data connectivity has been explicitly disabled,
- * {@code true} otherwise.
- */
- public boolean getAnyDataEnabled() {
- return (enabledCount != 0);
- }
-
/**
* Formerly this method was ArrayList<PdpConnection> getAllPdps()
*/
@@ -540,7 +374,7 @@
}
private boolean isDataAllowed() {
- boolean roaming = phone.getServiceState().getRoaming();
+ boolean roaming = getDataRoaming();
return getAnyDataEnabled() && (!roaming || getDataOnRoamingEnabled());
}
@@ -587,7 +421,7 @@
}
int gprsState = mGsmPhone.mSST.getCurrentGprsState();
- boolean roaming = phone.getServiceState().getRoaming();
+ boolean roaming = getDataRoaming();
boolean desiredPowerState = mGsmPhone.mSST.getDesiredPowerState();
if ((state == State.IDLE || state == State.SCANNING)
@@ -746,7 +580,7 @@
return true;
}
- String getInterfaceName(String apnType) {
+ protected String getInterfaceName(String apnType) {
if (mActivePdp != null
&& (apnType == null || mActiveApn.canHandleType(apnType))) {
return mActivePdp.getInterface();
@@ -762,7 +596,7 @@
return null;
}
- String getGateway(String apnType) {
+ public String getGateway(String apnType) {
if (mActivePdp != null
&& (apnType == null || mActiveApn.canHandleType(apnType))) {
return mActivePdp.getGatewayAddress();
@@ -1244,16 +1078,38 @@
trySetupData(reason);
}
+ /**
+ * Check the data roaming consistency since this can be triggered by
+ * voice roaming flag of ServiceState in setDataOnRoamingEnabled()
+ *
+ * TODO make this triggered by data roaming state only
+ */
+ @Override
protected void onRoamingOff() {
- trySetupData(Phone.REASON_ROAMING_OFF);
+ if (!getDataRoaming()) { //data roaming is off
+ trySetupData(Phone.REASON_ROAMING_OFF);
+ } else { // Inconsistent! data roaming is on
+ sendMessage(obtainMessage(EVENT_ROAMING_ON));
+ }
}
+ /**
+ * Check the data roaming consistency since this can be triggered by
+ * voice roaming flag of ServiceState in setDataOnRoamingEnabled()
+ *
+ * TODO make this triggered by data roaming state only
+ */
+ @Override
protected void onRoamingOn() {
- if (getDataOnRoamingEnabled()) {
- trySetupData(Phone.REASON_ROAMING_ON);
- } else {
- if (DBG) log("Tear down data connection on roaming.");
- cleanUpConnection(true, Phone.REASON_ROAMING_ON);
+ if (getDataRoaming()) { // data roaming is on
+ if (getDataOnRoamingEnabled()) {
+ trySetupData(Phone.REASON_ROAMING_ON);
+ } else {
+ if (DBG) log("Tear down data connection on roaming.");
+ cleanUpConnection(true, Phone.REASON_ROAMING_ON);
+ }
+ } else { // Inconsistent! data roaming is off
+ sendMessage(obtainMessage(EVENT_ROAMING_OFF));
}
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index 4178115..0c040e6 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -88,6 +88,9 @@
private int newNetworkType = 0;
/* gsm roaming status solely based on TS 27.007 7.2 CREG */
private boolean mGsmRoaming = false;
+ /* data roaming status solely based on TS 27.007 10.1.19 CGREG */
+ private boolean mDataRoaming = false;
+ private boolean newDataRoaming = false;
private RegistrantList gprsAttachedRegistrants = new RegistrantList();
private RegistrantList gprsDetachedRegistrants = new RegistrantList();
@@ -311,6 +314,10 @@
psRestrictDisabledRegistrants.remove(h);
}
+ /*protected*/ boolean getDataRoaming() {
+ return mDataRoaming;
+ }
+
//***** Called from GSMPhone
public void
getLacAndCid(Message onComplete) {
@@ -668,6 +675,7 @@
}
}
newGPRSState = regCodeToServiceState(regState);
+ newDataRoaming = regCodeIsRoaming(regState);
newNetworkType = type;
break;
@@ -695,6 +703,11 @@
if (pollingContext[0] == 0) {
newSS.setRoaming(isRoamingBetweenOperators(mGsmRoaming, newSS));
+ // when both roaming indicators are true but not roaming between
+ // operators, roaming should set to false.
+ if (newDataRoaming && mGsmRoaming && !newSS.getRoaming()) {
+ newDataRoaming = false;
+ }
pollStateDone();
}
@@ -724,6 +737,7 @@
newCellLoc.setStateInvalid();
setSignalStrengthDefaultValues();
mGotCountryCode = false;
+ newDataRoaming = false;
pollStateDone();
break;
@@ -733,6 +747,7 @@
newCellLoc.setStateInvalid();
setSignalStrengthDefaultValues();
mGotCountryCode = false;
+ newDataRoaming = false;
pollStateDone();
break;
@@ -747,6 +762,8 @@
newCellLoc.setStateInvalid();
setSignalStrengthDefaultValues();
mGotCountryCode = false;
+ newDataRoaming = false;
+ mDataRoaming = false;
//NOTE: pollStateDone() is not needed in this case
break;
@@ -831,9 +848,9 @@
boolean hasChanged = !newSS.equals(ss);
- boolean hasRoamingOn = !ss.getRoaming() && newSS.getRoaming();
+ boolean hasRoamingOn = !mDataRoaming && newDataRoaming;
- boolean hasRoamingOff = ss.getRoaming() && !newSS.getRoaming();
+ boolean hasRoamingOff = mDataRoaming && !newDataRoaming;
boolean hasLocationChanged = !newCellLoc.equals(cellLoc);
@@ -850,6 +867,7 @@
gprsState = newGPRSState;
networkType = newNetworkType;
+ mDataRoaming = newDataRoaming;
newSS.setStateOutOfService(); // clean slate for next time
diff --git a/tests/AndroidTests/src/com/android/unit_tests/accounts/AccountManagerServiceTest.java b/tests/AndroidTests/src/com/android/unit_tests/accounts/AccountManagerServiceTest.java
index 6b8e1f0..1e4f161 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/accounts/AccountManagerServiceTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/accounts/AccountManagerServiceTest.java
@@ -28,7 +28,6 @@
import java.util.Arrays;
import java.util.Comparator;
-import java.util.Map;
public class AccountManagerServiceTest extends AndroidTestCase {
@Override
@@ -48,9 +47,9 @@
if (object1 == object2) return 0;
if (object1 == null) return 1;
if (object2 == null) return -1;
- int result = object1.mType.compareTo(object2.mType);
+ int result = object1.type.compareTo(object2.type);
if (result != 0) return result;
- return object1.mName.compareTo(object2.mName);
+ return object1.name.compareTo(object2.name);
}
}
@@ -62,16 +61,14 @@
Account a12 = new Account("account1", "type2");
Account a22 = new Account("account2", "type2");
Account a32 = new Account("account3", "type2");
- assertTrue(ams.addAccount(a11, "p11", null));
- assertTrue(ams.addAccount(a12, "p12", null));
- assertTrue(ams.addAccount(a21, "p21", null));
- assertTrue(ams.addAccount(a22, "p22", null));
- assertTrue(ams.addAccount(a31, "p31", null));
- assertTrue(ams.addAccount(a32, "p32", null));
+ ams.addAccount(a11, "p11", null);
+ ams.addAccount(a12, "p12", null);
+ ams.addAccount(a21, "p21", null);
+ ams.addAccount(a22, "p22", null);
+ ams.addAccount(a31, "p31", null);
+ ams.addAccount(a32, "p32", null);
- assertFalse("duplicate account insertion should fail", ams.addAccount(a32, "p", null));
-
- Account[] accounts = ams.getAccounts();
+ Account[] accounts = ams.getAccounts(null);
Arrays.sort(accounts, new AccountSorter());
assertEquals(6, accounts.length);
assertEquals(a11, accounts[0]);
@@ -88,7 +85,7 @@
assertEquals(a21, accounts[1]);
assertEquals(a31, accounts[2]);
- ams.removeAccount(a21);
+ ams.removeAccount(null, a21);
accounts = ams.getAccountsByType("type1" );
Arrays.sort(accounts, new AccountSorter());
@@ -101,8 +98,8 @@
AccountManagerService ams = new AccountManagerService(getContext());
Account a11 = new Account("account1", "type1");
Account a12 = new Account("account1", "type2");
- assertTrue(ams.addAccount(a11, "p11", null));
- assertTrue(ams.addAccount(a12, "p12", null));
+ ams.addAccount(a11, "p11", null);
+ ams.addAccount(a12, "p12", null);
assertEquals("p11", ams.getPassword(a11));
assertEquals("p12", ams.getPassword(a12));
@@ -125,8 +122,8 @@
u12.putString("a", "a_a12");
u12.putString("b", "b_a12");
u12.putString("c", "c_a12");
- assertTrue(ams.addAccount(a11, "p11", u11));
- assertTrue(ams.addAccount(a12, "p12", u12));
+ ams.addAccount(a11, "p11", u11);
+ ams.addAccount(a12, "p12", u12);
assertEquals("a_a11", ams.getUserData(a11, "a"));
assertEquals("b_a11", ams.getUserData(a11, "b"));
@@ -149,8 +146,8 @@
AccountManagerService ams = new AccountManagerService(getContext());
Account a11 = new Account("account1", "type1");
Account a12 = new Account("account1", "type2");
- assertTrue(ams.addAccount(a11, "p11", null));
- assertTrue(ams.addAccount(a12, "p12", null));
+ ams.addAccount(a11, "p11", null);
+ ams.addAccount(a12, "p12", null);
ams.setAuthToken(a11, "att1", "a11_att1");
ams.setAuthToken(a11, "att2", "a11_att2");
@@ -167,7 +164,7 @@
assertEquals("a12_att3", ams.peekAuthToken(a12, "att3"));
ams.setAuthToken(a11, "att3", "a11_att3b");
- ams.invalidateAuthToken(a12.mType, "a12_att2");
+ ams.invalidateAuthToken(a12.type, "a12_att2");
assertEquals("a11_att1", ams.peekAuthToken(a11, "att1"));
assertEquals("a11_att2", ams.peekAuthToken(a11, "att2"));
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
index 97a8b25..b61b307 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
@@ -18,6 +18,7 @@
import android.os.Handler;
import android.os.Message;
+import android.webkit.MockGeolocation;
import android.webkit.WebStorage;
import java.util.HashMap;
@@ -325,7 +326,7 @@
}
public void setWindowIsKey(boolean b) {
- obtainMessage(LAYOUT_SET_WINDOW_KEY,b ? 1 : 0, 0).sendToTarget();
+ obtainMessage(LAYOUT_SET_WINDOW_KEY, b ? 1 : 0, 0).sendToTarget();
}
public void testRepaint() {
@@ -352,4 +353,15 @@
obtainMessage(LAYOUT_SET_CAN_OPEN_WINDOWS).sendToTarget();
}
+ public void setMockGeolocationPosition(double latitude,
+ double longitude,
+ double accuracy) {
+ MockGeolocation.getInstance().setPosition(latitude,
+ longitude,
+ accuracy);
+ }
+
+ public void setMockGeolocationError(int code, String message) {
+ MockGeolocation.getInstance().setError(code, message);
+ }
}
diff --git a/tests/FrameworkTest/tests/src/android/content/AbstractTableMergerTest.java b/tests/FrameworkTest/tests/src/android/content/AbstractTableMergerTest.java
index 42c1e78..a8af7f8 100644
--- a/tests/FrameworkTest/tests/src/android/content/AbstractTableMergerTest.java
+++ b/tests/FrameworkTest/tests/src/android/content/AbstractTableMergerTest.java
@@ -74,8 +74,8 @@
if (syncVersion != null) values.put("_sync_version", syncVersion);
if (syncId != null) values.put("_sync_id", syncId);
if (syncAccount != null) {
- values.put("_sync_account", syncAccount.mName);
- values.put("_sync_account_type", syncAccount.mType);
+ values.put("_sync_account", syncAccount.name);
+ values.put("_sync_account_type", syncAccount.type);
}
values.put("_sync_local_id", syncLocalId);
values.put("_sync_dirty", 0);
@@ -88,8 +88,8 @@
if (syncVersion != null) values.put("_sync_version", syncVersion);
if (syncId != null) values.put("_sync_id", syncId);
if (syncAccount != null) {
- values.put("_sync_account", syncAccount.mName);
- values.put("_sync_account_type", syncAccount.mType);
+ values.put("_sync_account", syncAccount.name);
+ values.put("_sync_account_type", syncAccount.type);
}
if (syncLocalId != null) values.put("_sync_local_id", syncLocalId);
return values;
diff --git a/tests/backup/backup_stress_test.sh b/tests/backup/backup_stress_test.sh
new file mode 100755
index 0000000..8155507
--- /dev/null
+++ b/tests/backup/backup_stress_test.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+
+# 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.
+
+iterations=150
+failures=0
+i=0
+LOGDIR="$HOME/backup_tests"
+LOGFILE="$LOGDIR/backup_stress.`date +%s`.log"
+export BUGREPORT_DIR="$LOGDIR/bugreports"
+
+# make sure that we have a place to put logs and bugreports
+mkdir -p $LOGDIR $BUGREPORT_DIR
+
+echo "logfile is $LOGFILE"
+
+(while (sleep 10); do
+ failed=0
+
+ echo
+ echo "Iteration $i at `date`"
+ echo
+
+ ./test_backup.sh "$@" 2>&1
+
+ sleep 10
+ echo "Restore at `date`"
+ echo
+
+ ./test_restore.sh "$@" 2>&1 || failed=1
+
+ if [ "$failed" -ne 0 ]; then
+ failures=$(($failures+1))
+ # Long and verbose so it sticks out
+ echo "FAILED iteration $i of $iterations; $failures failures so far"
+ echo "FAILED iteration $i of $iterations; $failures failures so far" > /dev/stderr
+ else
+ printf "Iteration %d:\tPASS; remaining: %d\n" $i $(($iterations - $i - 1))
+ printf "Iteration %d:\tPASS; remaining: %d\n" $i $(($iterations - $i - 1)) > /dev/stderr
+ fi
+
+ echo "End $i at `date`"
+
+ i=$(($i+1))
+ if [ $i -eq $iterations ]; then
+ echo "DONE: $iterations iterations with $failures failures."
+ echo "DONE: $iterations iterations with $failures failures." > /dev/stderr
+ [ "$failures" -eq 0 ] && exit 0
+ exit 1
+ fi
+done) > "$LOGFILE"
+
diff --git a/tests/backup/test_restore.sh b/tests/backup/test_restore.sh
index 4506c16..46b46e4 100755
--- a/tests/backup/test_restore.sh
+++ b/tests/backup/test_restore.sh
@@ -18,7 +18,7 @@
#export DRY_RUN="echo"
source test_backup_common.sh
-BUGREPORT_DIR="$HOME/backup/bugreports"
+[ -z "$BUGREPORT_DIR" ] && BUGREPORT_DIR="$HOME/backup/bugreports"
function check_file
{
@@ -107,3 +107,5 @@
echo "Last 3 timestamps in 3.txt:"
a shell cat /data/data/com.android.backuptest/files/3.txt | tail -n 3
+exit $need_bug
+
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 5724349..32efa4e 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -482,6 +482,8 @@
const sp<AaptFile>& file,
const String8& resType);
+ void addGroupEntry(const AaptGroupEntry& entry) { mGroupEntries.add(entry); }
+
ssize_t slurpFromArgs(Bundle* bundle);
virtual ssize_t slurpFullTree(Bundle* bundle,
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 9d2ed10..9a5127d 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -272,15 +272,16 @@
ResourceDirIterator it(set, String8("drawable"));
Vector<sp<AaptFile> > newNameFiles;
Vector<String8> newNamePaths;
+ bool hasErrors = false;
ssize_t res;
while ((res=it.next()) == NO_ERROR) {
res = preProcessImage(bundle, assets, it.getFile(), NULL);
- if (res != NO_ERROR) {
- return res;
+ if (res < NO_ERROR) {
+ hasErrors = true;
}
}
- return NO_ERROR;
+ return (hasErrors || (res < NO_ERROR)) ? UNKNOWN_ERROR : NO_ERROR;
}
status_t postProcessImages(const sp<AaptAssets>& assets,
@@ -288,15 +289,16 @@
const sp<ResourceTypeSet>& set)
{
ResourceDirIterator it(set, String8("drawable"));
+ bool hasErrors = false;
ssize_t res;
while ((res=it.next()) == NO_ERROR) {
res = postProcessImage(assets, table, it.getFile());
- if (res != NO_ERROR) {
- return res;
+ if (res < NO_ERROR) {
+ hasErrors = true;
}
}
- return res < NO_ERROR ? res : (status_t)NO_ERROR;
+ return (hasErrors || (res < NO_ERROR)) ? UNKNOWN_ERROR : NO_ERROR;
}
static void collect_files(const sp<AaptDir>& dir,
@@ -472,11 +474,22 @@
// didn't find a match fall through and add it..
}
baseGroup->addFile(overlayFiles.valueAt(overlayGroupIndex));
+ assets->addGroupEntry(overlayFiles.keyAt(overlayGroupIndex));
}
} else {
// this group doesn't exist (a file that's only in the overlay)
baseSet->add(overlaySet->keyAt(overlayIndex),
overlaySet->valueAt(overlayIndex));
+ // make sure all flavors are defined in the resources.
+ sp<AaptGroup> overlayGroup = overlaySet->valueAt(overlayIndex);
+ DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> > overlayFiles =
+ overlayGroup->getFiles();
+ size_t overlayGroupSize = overlayFiles.size();
+ for (size_t overlayGroupIndex = 0;
+ overlayGroupIndex<overlayGroupSize;
+ overlayGroupIndex++) {
+ assets->addGroupEntry(overlayFiles.keyAt(overlayGroupIndex));
+ }
}
}
// this overlay didn't have resources for this type
diff --git a/tools/layoutlib/bridge/src/android/os/ServiceManager.java b/tools/layoutlib/bridge/src/android/os/ServiceManager.java
new file mode 100644
index 0000000..6a68ee2
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/os/ServiceManager.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import java.util.Map;
+
+public final class ServiceManager {
+
+ /**
+ * Returns a reference to a service with the given name.
+ *
+ * @param name the name of the service to get
+ * @return a reference to the service, or <code>null</code> if the service doesn't exist
+ */
+ public static IBinder getService(String name) {
+ return null;
+ }
+
+ /**
+ * Place a new @a service called @a name into the service
+ * manager.
+ *
+ * @param name the name of the new service
+ * @param service the service object
+ */
+ public static void addService(String name, IBinder service) {
+ // pass
+ }
+
+ /**
+ * Retrieve an existing service called @a name from the
+ * service manager. Non-blocking.
+ */
+ public static IBinder checkService(String name) {
+ return null;
+ }
+
+ /**
+ * Return a list of all currently running services.
+ */
+ public static String[] listServices() throws RemoteException {
+ // actual implementation returns null sometimes, so it's ok
+ // to return null instead of an empty list.
+ return null;
+ }
+
+ /**
+ * This is only intended to be called when the process is first being brought
+ * up and bound by the activity manager. There is only one thread in the process
+ * at that time, so no locking is done.
+ *
+ * @param cache the cache of service references
+ * @hide
+ */
+ public static void initServiceCache(Map<String, IBinder> cache) {
+ // pass
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java b/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java
new file mode 100644
index 0000000..251c053
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/accessibility/AccessibilityManager.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.accessibility;
+
+import android.content.Context;
+import android.content.pm.ServiceInfo;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * System level service that serves as an event dispatch for {@link AccessibilityEvent}s.
+ * Such events are generated when something notable happens in the user interface,
+ * for example an {@link android.app.Activity} starts, the focus or selection of a
+ * {@link android.view.View} changes etc. Parties interested in handling accessibility
+ * events implement and register an accessibility service which extends
+ * {@link android.accessibilityservice.AccessibilityService}.
+ *
+ * @see AccessibilityEvent
+ * @see android.accessibilityservice.AccessibilityService
+ * @see android.content.Context#getSystemService
+ */
+public final class AccessibilityManager {
+ private static AccessibilityManager sInstance = new AccessibilityManager();
+
+ /**
+ * Get an AccessibilityManager instance (create one if necessary).
+ *
+ * @hide
+ */
+ public static AccessibilityManager getInstance(Context context) {
+ return sInstance;
+ }
+
+ /**
+ * Create an instance.
+ *
+ * @param context A {@link Context}.
+ */
+ private AccessibilityManager() {
+ }
+
+ /**
+ * Returns if the {@link AccessibilityManager} is enabled.
+ *
+ * @return True if this {@link AccessibilityManager} is enabled, false otherwise.
+ */
+ public boolean isEnabled() {
+ return false;
+ }
+
+ /**
+ * Sends an {@link AccessibilityEvent}. If this {@link AccessibilityManager} is not
+ * enabled the call is a NOOP.
+ *
+ * @param event The {@link AccessibilityEvent}.
+ *
+ * @throws IllegalStateException if a client tries to send an {@link AccessibilityEvent}
+ * while accessibility is not enabled.
+ */
+ public void sendAccessibilityEvent(AccessibilityEvent event) {
+ }
+
+ /**
+ * Requests interruption of the accessibility feedback from all accessibility services.
+ */
+ public void interrupt() {
+ }
+
+ /**
+ * Returns the {@link ServiceInfo}s of the installed accessibility services.
+ *
+ * @return An unmodifiable list with {@link ServiceInfo}s.
+ */
+ public List<ServiceInfo> getAccessibilityServiceList() {
+ // normal implementation does this in some case, so let's do the same
+ // (unmodifiableList wrapped around null).
+ List<ServiceInfo> services = null;
+ return Collections.unmodifiableList(services);
+ }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 8d44ac08..c598126 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -358,7 +358,7 @@
windowBackground = context.findItemInStyle(currentTheme, "windowBackground");
windowBackground = context.resolveResValue(windowBackground);
- screenOffset = getScreenOffset(currentTheme, context);
+ screenOffset = getScreenOffset(frameworkResources, currentTheme, context);
}
// we need to make sure the Looper has been initialized for this thread.
@@ -673,9 +673,13 @@
/**
* Returns the top screen offset. This depends on whether the current theme defines the user
* of the title and status bars.
+ * @param frameworkResources The framework resources
+ * @param currentTheme The current theme
+ * @param context The context
* @return the pixel height offset
*/
- private int getScreenOffset(IStyleResourceValue currentTheme, BridgeContext context) {
+ private int getScreenOffset(Map<String, Map<String, IResourceValue>> frameworkResources,
+ IStyleResourceValue currentTheme, BridgeContext context) {
int offset = 0;
// get the title bar flag from the current theme.
@@ -687,22 +691,25 @@
// if there's a value and it's true (default is false)
if (value == null || value.getValue() == null ||
XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
+ // default size of the window title bar
+ int defaultOffset = DEFAULT_TITLE_BAR_HEIGHT;
+
// get value from the theme.
value = context.findItemInStyle(currentTheme, "windowTitleSize");
// resolve it
value = context.resolveResValue(value);
- // default value
- offset = DEFAULT_TITLE_BAR_HEIGHT;
-
- // get the real value;
if (value != null) {
+ // get the numerical value, if available
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
if (typedValue != null) {
- offset = (int)typedValue.getDimension(context.getResources().mMetrics);
+ // compute the pixel value based on the display metrics
+ defaultOffset = (int)typedValue.getDimension(context.getResources().mMetrics);
}
}
+
+ offset += defaultOffset;
}
// get the fullscreen flag from the current theme.
@@ -713,8 +720,25 @@
if (value == null || value.getValue() == null ||
XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
- // FIXME: Right now this is hard-coded in the platform, but once there's a constant, we'll need to use it.
- offset += DEFAULT_STATUS_BAR_HEIGHT;
+
+ // default value
+ int defaultOffset = DEFAULT_STATUS_BAR_HEIGHT;
+
+ // get the real value, first the list of Dimensions from the framework map
+ Map<String, IResourceValue> dimens = frameworkResources.get(BridgeConstants.RES_DIMEN);
+
+ // now get the value
+ value = dimens.get("status_bar_height");
+ if (value != null) {
+ TypedValue typedValue = ResourceHelper.getValue(value.getValue());
+ if (typedValue != null) {
+ // compute the pixel value based on the display metrics
+ defaultOffset = (int)typedValue.getDimension(context.getResources().mMetrics);
+ }
+ }
+
+ // add the computed offset.
+ offset += defaultOffset;
}
return offset;
@@ -1021,12 +1045,12 @@
}
@SuppressWarnings("unused")
- public void dispatchPointer(MotionEvent arg0, long arg1) throws RemoteException {
+ public void dispatchPointer(MotionEvent arg0, long arg1, boolean arg2) throws RemoteException {
// pass for now.
}
@SuppressWarnings("unused")
- public void dispatchTrackball(MotionEvent arg0, long arg1) throws RemoteException {
+ public void dispatchTrackball(MotionEvent arg0, long arg1, boolean arg2) throws RemoteException {
// pass for now.
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
index b426247..b5b7ceb 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
@@ -45,11 +45,12 @@
public final static String PREFIX_RESOURCE_REF = "@";
public final static String PREFIX_ANDROID_THEME_REF = "?android:";
public final static String PREFIX_THEME_REF = "?";
-
+
public final static String PREFIX_ANDROID = "android:";
-
+
public final static String RES_STYLE = "style";
public final static String RES_ATTR = "attr";
+ public final static String RES_DIMEN = "dimen";
public final static String RES_DRAWABLE = "drawable";
public final static String RES_COLOR = "color";
public final static String RES_LAYOUT = "layout";
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
index 69f3d9c..f48c8db 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java
@@ -64,7 +64,7 @@
* Custom implementation of Context to handle non compiled resources.
*/
public final class BridgeContext extends Context {
-
+
private Resources mResources;
private Theme mTheme;
private HashMap<View, Object> mViewKeyMap = new HashMap<View, Object>();
@@ -73,12 +73,12 @@
private Map<String, Map<String, IResourceValue>> mProjectResources;
private Map<String, Map<String, IResourceValue>> mFrameworkResources;
private Map<IStyleResourceValue, IStyleResourceValue> mStyleInheritanceMap;
-
+
// maps for dynamically generated id representing style objects (IStyleResourceValue)
private Map<Integer, IStyleResourceValue> mDynamicIdToStyleMap;
private Map<IStyleResourceValue, Integer> mStyleToDynamicIdMap;
private int mDynamicIdGenerator = 0x01030000; // Base id for framework R.style
-
+
// cache for TypedArray generated from IStyleResourceValue object
private Map<int[], Map<Integer, TypedArray>> mTypedArrayCache;
private BridgeInflater mInflater;
@@ -112,7 +112,7 @@
mProjectCallback = customViewLoader;
mLogger = logger;
Configuration config = new Configuration();
-
+
AssetManager assetManager = BridgeAssetManager.initSystem();
mResources = BridgeResources.initSystem(
this,
@@ -120,19 +120,19 @@
metrics,
config,
customViewLoader);
-
+
mTheme = mResources.newTheme();
-
+
mThemeValues = currentTheme;
mProjectResources = projectResources;
mFrameworkResources = frameworkResources;
mStyleInheritanceMap = styleInheritanceMap;
}
-
+
public void setBridgeInflater(BridgeInflater inflater) {
mInflater = inflater;
}
-
+
public void addViewKey(View view, Object viewKey) {
mViewKeyMap.put(view, viewKey);
}
@@ -140,19 +140,19 @@
public Object getViewKey(View view) {
return mViewKeyMap.get(view);
}
-
+
public Object getProjectKey() {
return mProjectKey;
}
-
+
public IProjectCallback getProjectCallback() {
return mProjectCallback;
}
-
+
public ILayoutLog getLogger() {
return mLogger;
}
-
+
// ------------ Context methods
@Override
@@ -169,14 +169,14 @@
public ClassLoader getClassLoader() {
return this.getClass().getClassLoader();
}
-
+
@Override
public Object getSystemService(String service) {
if (LAYOUT_INFLATER_SERVICE.equals(service)) {
return mInflater;
}
-
- // AutoCompleteTextView and MultiAutoCompleteTextView want a window
+
+ // AutoCompleteTextView and MultiAutoCompleteTextView want a window
// service. We don't have any but it's not worth an exception.
if (WINDOW_SERVICE.equals(service)) {
return null;
@@ -196,38 +196,38 @@
throws Resources.NotFoundException {
// get the IStyleResourceValue based on the resId;
IStyleResourceValue style = getStyleByDynamicId(resid);
-
+
if (style == null) {
throw new Resources.NotFoundException();
}
if (mTypedArrayCache == null) {
mTypedArrayCache = new HashMap<int[], Map<Integer,TypedArray>>();
-
+
Map<Integer, TypedArray> map = new HashMap<Integer, TypedArray>();
mTypedArrayCache.put(attrs, map);
BridgeTypedArray ta = createStyleBasedTypedArray(style, attrs);
map.put(resid, ta);
-
+
return ta;
}
-
+
// get the 2nd map
Map<Integer, TypedArray> map = mTypedArrayCache.get(attrs);
if (map == null) {
map = new HashMap<Integer, TypedArray>();
mTypedArrayCache.put(attrs, map);
}
-
+
// get the array from the 2nd map
TypedArray ta = map.get(resid);
-
+
if (ta == null) {
ta = createStyleBasedTypedArray(style, attrs);
map.put(resid, ta);
}
-
+
return ta;
}
@@ -235,11 +235,11 @@
public final TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs) {
return obtainStyledAttributes(set, attrs, 0, 0);
}
-
+
@Override
public TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs,
int defStyleAttr, int defStyleRes) {
-
+
// Hint: for XmlPullParser, attach source //DEVICE_SRC/dalvik/libcore/xml/src/java
BridgeXmlBlockParser parser = null;
if (set instanceof BridgeXmlBlockParser) {
@@ -252,10 +252,10 @@
boolean[] frameworkAttributes = new boolean[1];
TreeMap<Integer, String> styleNameMap = searchAttrs(attrs, frameworkAttributes);
-
+
BridgeTypedArray ta = ((BridgeResources) mResources).newTypeArray(attrs.length,
parser.isPlatformFile());
-
+
// resolve the defStyleAttr value into a IStyleResourceValue
IStyleResourceValue defStyleValues = null;
if (defStyleAttr != 0) {
@@ -265,7 +265,7 @@
// look for the style in the current theme, and its parent:
if (mThemeValues != null) {
IResourceValue item = findItemInStyle(mThemeValues, defStyleName);
-
+
if (item != null) {
// item is a reference to a style entry. Search for it.
item = findResValue(item.getValue());
@@ -279,12 +279,12 @@
}
}
}
-
+
if (defStyleRes != 0) {
// FIXME: See what we need to do with this.
throw new UnsupportedOperationException();
}
-
+
String namespace = BridgeConstants.NS_RESOURCES;
if (frameworkAttributes[0] == false) {
// need to use the application namespace
@@ -294,32 +294,32 @@
if (styleNameMap != null) {
for (Entry<Integer, String> styleAttribute : styleNameMap.entrySet()) {
int index = styleAttribute.getKey().intValue();
-
+
String name = styleAttribute.getValue();
String value = parser.getAttributeValue(namespace, name);
-
+
// if there's no direct value for this attribute in the XML, we look for default
// values in the widget defStyle, and then in the theme.
if (value == null) {
IResourceValue resValue = null;
-
+
// look for the value in the defStyle first (and its parent if needed)
if (defStyleValues != null) {
resValue = findItemInStyle(defStyleValues, name);
}
-
+
// if the item is not present in the defStyle, we look in the main theme (and
// its parent themes)
if (resValue == null && mThemeValues != null) {
resValue = findItemInStyle(mThemeValues, name);
}
-
+
// if we found a value, we make sure this doesn't reference another value.
// So we resolve it.
if (resValue != null) {
resValue = resolveResValue(resValue);
}
-
+
ta.bridgeSetValue(index, name, resValue);
} else {
// there is a value in the XML, but we need to resolve it in case it's
@@ -328,15 +328,20 @@
}
}
}
-
+
ta.sealArray();
-
+
return ta;
}
-
-
+
+ @Override
+ public Looper getMainLooper() {
+ return Looper.myLooper();
+ }
+
+
// ------------- private new methods
-
+
/**
* Creates a {@link BridgeTypedArray} by filling the values defined by the int[] with the
* values found in the given style.
@@ -345,30 +350,30 @@
private BridgeTypedArray createStyleBasedTypedArray(IStyleResourceValue style, int[] attrs)
throws Resources.NotFoundException {
TreeMap<Integer, String> styleNameMap = searchAttrs(attrs, null);
-
+
BridgeTypedArray ta = ((BridgeResources) mResources).newTypeArray(attrs.length,
false /* platformResourceFlag */);
-
+
// loop through all the values in the style map, and init the TypedArray with
// the style we got from the dynamic id
for (Entry<Integer, String> styleAttribute : styleNameMap.entrySet()) {
int index = styleAttribute.getKey().intValue();
String name = styleAttribute.getValue();
-
+
// get the value from the style, or its parent styles.
IResourceValue resValue = findItemInStyle(style, name);
-
+
// resolve it to make sure there are no references left.
ta.bridgeSetValue(index, name, resolveResValue(resValue));
}
-
+
ta.sealArray();
return ta;
}
-
+
/**
* Resolves the value of a resource, if the value references a theme or resource value.
* <p/>
@@ -391,13 +396,13 @@
// get the IResourceValue referenced by this value
IResourceValue resValue = findResValue(value);
-
+
// if resValue is null, but value is not null, this means it was not a reference.
// we return the name/value wrapper in a IResourceValue
if (resValue == null) {
return new ResourceValue(type, name, value);
}
-
+
// we resolved a first reference, but we need to make sure this isn't a reference also.
return resolveResValue(resValue);
}
@@ -411,7 +416,7 @@
* <p/>
* If a value that does not need to be resolved is given, the method will return the input
* value.
- *
+ *
* @param value the value containing the reference to resolve.
* @return a {@link IResourceValue} object or <code>null</code>
*/
@@ -419,7 +424,7 @@
if (value == null) {
return null;
}
-
+
// if the resource value is a style, we simply return it.
if (value instanceof IStyleResourceValue) {
return value;
@@ -436,7 +441,7 @@
// otherwise, we attempt to resolve this new value as well
return resolveResValue(resolvedValue);
}
-
+
/**
* Searches for, and returns a {@link IResourceValue} by its reference.
* <p/>
@@ -451,7 +456,7 @@
* <p/>
* The actual format of a reference is <pre>@[namespace:]resType/resName</pre> but this method
* only support the android namespace.
- *
+ *
* @param reference the resource reference to search for.
* @return a {@link IResourceValue} or <code>null</code>.
*/
@@ -481,7 +486,7 @@
// we look for the referenced item name.
String referenceName = null;
-
+
if (segments.length == 2) {
// there was a resType in the reference. If it's attr, we ignore it
// else, we assert for now.
@@ -495,7 +500,7 @@
// it's just an item name.
referenceName = segments[0];
}
-
+
// now we look for android: in the referenceName in order to support format
// such as: ?attr/android:name
if (referenceName.startsWith(BridgeConstants.PREFIX_ANDROID)) {
@@ -512,9 +517,9 @@
return findItemInStyle(mThemeValues, referenceName);
} else if (reference.startsWith(BridgeConstants.PREFIX_RESOURCE_REF)) {
boolean frameworkOnly = false;
-
+
// check for the specific null reference value.
- if (BridgeConstants.REFERENCE_NULL.equals(reference)) {
+ if (BridgeConstants.REFERENCE_NULL.equals(reference)) {
return null;
}
@@ -526,20 +531,20 @@
} else {
reference = reference.substring(BridgeConstants.PREFIX_RESOURCE_REF.length());
}
-
+
// at this point, value contains type/[android:]name (drawable/foo for instance)
String[] segments = reference.split("\\/");
-
+
// now we look for android: in the resource name in order to support format
// such as: @drawable/android:name
if (segments[1].startsWith(BridgeConstants.PREFIX_ANDROID)) {
frameworkOnly = true;
segments[1] = segments[1].substring(BridgeConstants.PREFIX_ANDROID.length());
}
-
+
return findResValue(segments[0], segments[1], frameworkOnly);
}
-
+
// Looks like the value didn't reference anything. Return null.
return null;
}
@@ -565,7 +570,7 @@
}
}
}
-
+
// now search in the framework resources.
typeMap = mFrameworkResources.get(resType);
if (typeMap != null) {
@@ -574,11 +579,11 @@
return item;
}
}
-
+
// didn't find the resource anywhere.
return null;
}
-
+
/**
* Returns a framework resource by type and name. The returned resource is resolved.
* @param resourceType the type of the resource
@@ -587,7 +592,7 @@
public IResourceValue getFrameworkResource(String resourceType, String resourceName) {
return getResource(resourceType, resourceName, mFrameworkResources);
}
-
+
/**
* Returns a project resource by type and name. The returned resource is resolved.
* @param resourceType the type of the resource
@@ -596,7 +601,7 @@
public IResourceValue getProjectResource(String resourceType, String resourceName) {
return getResource(resourceType, resourceName, mProjectResources);
}
-
+
IResourceValue getResource(String resourceType, String resourceName,
Map<String, Map<String, IResourceValue>> resourceRepository) {
Map<String, IResourceValue> typeMap = resourceRepository.get(resourceType);
@@ -607,12 +612,12 @@
return item;
}
}
-
+
// didn't find the resource anywhere.
return null;
-
+
}
-
+
/**
* Returns the {@link IResourceValue} matching a given name in a given style. If the
* item is not directly available in the style, the method looks in its parent style.
@@ -622,7 +627,7 @@
*/
IResourceValue findItemInStyle(IStyleResourceValue style, String itemName) {
IResourceValue item = style.findItem(itemName);
-
+
// if we didn't find it, we look in the parent style (if applicable)
if (item == null && mStyleInheritanceMap != null) {
IStyleResourceValue parentStyle = mStyleInheritanceMap.get(style);
@@ -630,7 +635,7 @@
return findItemInStyle(parentStyle, itemName);
}
}
-
+
return item;
}
@@ -642,7 +647,7 @@
* attrs == com.android.internal.R.styleable.View, this returns the list of the "xyz" where
* there's a field com.android.internal.R.styleable.View_xyz and the field value is the index
* that is used to reference the attribute later in the TypedArray.
- *
+ *
* @param attrs An attribute array reference given to obtainStyledAttributes.
* @return A sorted map Attribute-Value to Attribute-Name for all attributes declared by the
* attribute array. Returns null if nothing is found.
@@ -662,14 +667,14 @@
attributes.put(i, null);
}
}
-
+
if (outFrameworkFlag != null) {
outFrameworkFlag[0] = true;
}
-
+
return attributes;
}
-
+
// if the name was not found in the framework resources, look in the project
// resources
arrayName = mProjectCallback.resolveResourceValue(attrs);
@@ -697,7 +702,7 @@
/**
* Searches for the attribute referenced by its internal id.
- *
+ *
* @param attr An attribute reference given to obtainStyledAttributes such as defStyle.
* @return The unique name of the attribute, if found, e.g. "buttonStyle". Returns null
* if nothing is found.
@@ -707,12 +712,12 @@
if (info != null) {
return info[0];
}
-
+
info = mProjectCallback.resolveResourceValue(attr);
if (info != null) {
return info[0];
}
-
+
return null;
}
@@ -722,27 +727,27 @@
mDynamicIdToStyleMap = new HashMap<Integer, IStyleResourceValue>();
mStyleToDynamicIdMap = new HashMap<IStyleResourceValue, Integer>();
}
-
+
// look for an existing id
Integer id = mStyleToDynamicIdMap.get(resValue);
-
+
if (id == null) {
// generate a new id
id = Integer.valueOf(++mDynamicIdGenerator);
-
+
// and add it to the maps.
mDynamicIdToStyleMap.put(id, resValue);
mStyleToDynamicIdMap.put(resValue, id);
}
-
+
return id;
}
-
+
private IStyleResourceValue getStyleByDynamicId(int i) {
if (mDynamicIdToStyleMap != null) {
return mDynamicIdToStyleMap.get(i);
}
-
+
return null;
}
@@ -751,10 +756,10 @@
if (value != null) {
return value.intValue();
}
-
+
return defValue;
}
-
+
int getProjectIdValue(String idName, int defValue) {
if (mProjectCallback != null) {
Integer value = mProjectCallback.getResourceValue(BridgeConstants.RES_ID, idName);
@@ -762,7 +767,7 @@
return value.intValue();
}
}
-
+
return defValue;
}
@@ -820,7 +825,7 @@
@Override
public void clearWallpaper() {
// TODO Auto-generated method stub
-
+
}
@Override
@@ -850,46 +855,46 @@
@Override
public void enforceCallingOrSelfPermission(String arg0, String arg1) {
// TODO Auto-generated method stub
-
+
}
@Override
public void enforceCallingOrSelfUriPermission(Uri arg0, int arg1,
String arg2) {
// TODO Auto-generated method stub
-
+
}
@Override
public void enforceCallingPermission(String arg0, String arg1) {
// TODO Auto-generated method stub
-
+
}
@Override
public void enforceCallingUriPermission(Uri arg0, int arg1, String arg2) {
// TODO Auto-generated method stub
-
+
}
@Override
public void enforcePermission(String arg0, int arg1, int arg2, String arg3) {
// TODO Auto-generated method stub
-
+
}
@Override
public void enforceUriPermission(Uri arg0, int arg1, int arg2, int arg3,
String arg4) {
// TODO Auto-generated method stub
-
+
}
@Override
public void enforceUriPermission(Uri arg0, String arg1, String arg2,
int arg3, int arg4, int arg5, String arg6) {
// TODO Auto-generated method stub
-
+
}
@Override
@@ -965,7 +970,7 @@
// TODO Auto-generated method stub
return null;
}
-
+
@Override
public String getPackageResourcePath() {
// TODO Auto-generated method stub
@@ -1003,7 +1008,7 @@
@Override
public void grantUriPermission(String arg0, Uri arg1, int arg2) {
// TODO Auto-generated method stub
-
+
}
@SuppressWarnings("unused")
@@ -1051,31 +1056,31 @@
@Override
public void removeStickyBroadcast(Intent arg0) {
// TODO Auto-generated method stub
-
+
}
@Override
public void revokeUriPermission(Uri arg0, int arg1) {
// TODO Auto-generated method stub
-
+
}
@Override
public void sendBroadcast(Intent arg0) {
// TODO Auto-generated method stub
-
+
}
@Override
public void sendBroadcast(Intent arg0, String arg1) {
// TODO Auto-generated method stub
-
+
}
@Override
public void sendOrderedBroadcast(Intent arg0, String arg1) {
// TODO Auto-generated method stub
-
+
}
@Override
@@ -1083,39 +1088,39 @@
BroadcastReceiver arg2, Handler arg3, int arg4, String arg5,
Bundle arg6) {
// TODO Auto-generated method stub
-
+
}
@Override
public void sendStickyBroadcast(Intent arg0) {
// TODO Auto-generated method stub
-
+
}
@Override
public void setTheme(int arg0) {
// TODO Auto-generated method stub
-
+
}
@SuppressWarnings("unused")
@Override
public void setWallpaper(Bitmap arg0) throws IOException {
// TODO Auto-generated method stub
-
+
}
@SuppressWarnings("unused")
@Override
public void setWallpaper(InputStream arg0) throws IOException {
// TODO Auto-generated method stub
-
+
}
@Override
public void startActivity(Intent arg0) {
// TODO Auto-generated method stub
-
+
}
@Override
@@ -1140,21 +1145,16 @@
@Override
public void unbindService(ServiceConnection arg0) {
// TODO Auto-generated method stub
-
+
}
@Override
public void unregisterReceiver(BroadcastReceiver arg0) {
// TODO Auto-generated method stub
-
+
}
@Override
- public Looper getMainLooper() {
- throw new UnsupportedOperationException();
- }
-
- @Override
public Context getApplicationContext() {
throw new UnsupportedOperationException();
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeResources.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeResources.java
index 0bcc7fd..8a040e41 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeResources.java
@@ -43,14 +43,14 @@
import java.io.InputStream;
/**
- *
+ *
*/
public final class BridgeResources extends Resources {
private BridgeContext mContext;
private IProjectCallback mProjectCallback;
private boolean[] mPlatformResourceFlag = new boolean[1];
-
+
/**
* This initializes the static field {@link Resources#mSystem} which is used
* by methods who get global resources using {@link Resources#getSystem()}.
@@ -59,7 +59,7 @@
* <p/>
* {@link Bridge} calls this method after setting up a new bridge.
*/
- /*package*/ static Resources initSystem(BridgeContext context,
+ /*package*/ static Resources initSystem(BridgeContext context,
AssetManager assets,
DisplayMetrics metrics,
Configuration config,
@@ -73,7 +73,7 @@
}
return Resources.mSystem;
}
-
+
/**
* Clears the static {@link Resources#mSystem} to make sure we don't leave objects
* around that would prevent us from unloading the library.
@@ -92,15 +92,15 @@
mContext = context;
mProjectCallback = projectCallback;
}
-
+
public BridgeTypedArray newTypeArray(int numEntries, boolean platformFile) {
return new BridgeTypedArray(this, mContext, numEntries, platformFile);
}
-
+
private IResourceValue getResourceValue(int id, boolean[] platformResFlag_out) {
// first get the String related to this id in the framework
String[] resourceInfo = Bridge.resolveResourceValue(id);
-
+
if (resourceInfo != null) {
platformResFlag_out[0] = true;
return mContext.getFrameworkResource(resourceInfo[1], resourceInfo[0]);
@@ -109,7 +109,7 @@
// didn't find a match in the framework? look in the project.
if (mProjectCallback != null) {
resourceInfo = mProjectCallback.resolveResourceValue(id);
-
+
if (resourceInfo != null) {
platformResFlag_out[0] = false;
return mContext.getProjectResource(resourceInfo[1], resourceInfo[0]);
@@ -118,26 +118,26 @@
return null;
}
-
+
@Override
public Drawable getDrawable(int id) throws NotFoundException {
IResourceValue value = getResourceValue(id, mPlatformResourceFlag);
-
+
if (value != null) {
return ResourceHelper.getDrawable(value.getValue(), mContext, value.isFramework());
}
-
+
// id was not found or not resolved. Throw a NotFoundException.
throwException(id);
-
+
// this is not used since the method above always throws
return null;
}
-
+
@Override
public int getColor(int id) throws NotFoundException {
IResourceValue value = getResourceValue(id, mPlatformResourceFlag);
-
+
if (value != null) {
try {
return ResourceHelper.getColor(value.getValue());
@@ -145,18 +145,18 @@
return 0;
}
}
-
+
// id was not found or not resolved. Throw a NotFoundException.
throwException(id);
-
+
// this is not used since the method above always throws
return 0;
}
-
+
@Override
public ColorStateList getColorStateList(int id) throws NotFoundException {
IResourceValue value = getResourceValue(id, mPlatformResourceFlag);
-
+
if (value != null) {
try {
int color = ResourceHelper.getColor(value.getValue());
@@ -165,33 +165,33 @@
return null;
}
}
-
+
// id was not found or not resolved. Throw a NotFoundException.
throwException(id);
-
+
// this is not used since the method above always throws
return null;
}
-
+
@Override
public CharSequence getText(int id) throws NotFoundException {
IResourceValue value = getResourceValue(id, mPlatformResourceFlag);
-
+
if (value != null) {
return value.getValue();
}
-
+
// id was not found or not resolved. Throw a NotFoundException.
throwException(id);
-
+
// this is not used since the method above always throws
return null;
}
-
+
@Override
public XmlResourceParser getLayout(int id) throws NotFoundException {
IResourceValue value = getResourceValue(id, mPlatformResourceFlag);
-
+
if (value != null) {
File xml = new File(value.getValue());
if (xml.isFile()) {
@@ -201,7 +201,7 @@
KXmlParser parser = new KXmlParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(new FileReader(xml));
-
+
return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
} catch (XmlPullParserException e) {
mContext.getLogger().error(e);
@@ -215,22 +215,22 @@
// id was not found or not resolved. Throw a NotFoundException.
throwException(id);
-
+
// this is not used since the method above always throws
return null;
}
-
+
@Override
public TypedArray obtainAttributes(AttributeSet set, int[] attrs) {
return mContext.obtainStyledAttributes(set, attrs);
}
-
+
@Override
public TypedArray obtainTypedArray(int id) throws NotFoundException {
throw new UnsupportedOperationException();
}
-
-
+
+
@Override
public float getDimension(int id) throws NotFoundException {
IResourceValue value = getResourceValue(id, mPlatformResourceFlag);
@@ -244,7 +244,7 @@
} else if (v.equals(BridgeConstants.WRAP_CONTENT)) {
return LayoutParams.WRAP_CONTENT;
}
-
+
if (ResourceHelper.stringToFloat(v, mTmpValue) &&
mTmpValue.type == TypedValue.TYPE_DIMENSION) {
return mTmpValue.getDimension(mMetrics);
@@ -254,7 +254,7 @@
// id was not found or not resolved. Throw a NotFoundException.
throwException(id);
-
+
// this is not used since the method above always throws
return 0;
}
@@ -276,7 +276,7 @@
// id was not found or not resolved. Throw a NotFoundException.
throwException(id);
-
+
// this is not used since the method above always throws
return 0;
}
@@ -298,7 +298,7 @@
// id was not found or not resolved. Throw a NotFoundException.
throwException(id);
-
+
// this is not used since the method above always throws
return 0;
}
@@ -306,7 +306,7 @@
@Override
public int getInteger(int id) throws NotFoundException {
IResourceValue value = getResourceValue(id, mPlatformResourceFlag);
-
+
if (value != null && value.getValue() != null) {
String v = value.getValue();
int radix = 10;
@@ -320,10 +320,10 @@
// return exception below
}
}
-
+
// id was not found or not resolved. Throw a NotFoundException.
throwException(id);
-
+
// this is not used since the method above always throws
return 0;
}
@@ -348,12 +348,12 @@
String s = getString(id);
if (s != null) {
return String.format(s, formatArgs);
-
+
}
// id was not found or not resolved. Throw a NotFoundException.
throwException(id);
-
+
// this is not used since the method above always throws
return null;
}
@@ -361,14 +361,14 @@
@Override
public String getString(int id) throws NotFoundException {
IResourceValue value = getResourceValue(id, mPlatformResourceFlag);
-
+
if (value != null && value.getValue() != null) {
return value.getValue();
}
// id was not found or not resolved. Throw a NotFoundException.
throwException(id);
-
+
// this is not used since the method above always throws
return null;
}
@@ -385,6 +385,11 @@
if (ResourceHelper.stringToFloat(v, outValue)) {
return;
}
+
+ // else it's a string
+ outValue.type = TypedValue.TYPE_STRING;
+ outValue.string = v;
+ return;
}
}
@@ -413,7 +418,7 @@
KXmlParser parser = new KXmlParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(new FileReader(f));
-
+
return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
} catch (XmlPullParserException e) {
NotFoundException newE = new NotFoundException();
@@ -436,6 +441,33 @@
}
@Override
+ public XmlResourceParser loadXmlResourceParser(String file, int id,
+ int assetCookie, String type) throws NotFoundException {
+ // even though we know the XML file to load directly, we still need to resolve the
+ // id so that we can know if it's a platform or project resource.
+ // (mPlatformResouceFlag will get the result and will be used later).
+ getResourceValue(id, mPlatformResourceFlag);
+
+ File f = new File(file);
+ try {
+ KXmlParser parser = new KXmlParser();
+ parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
+ parser.setInput(new FileReader(f));
+
+ return new BridgeXmlBlockParser(parser, mContext, mPlatformResourceFlag[0]);
+ } catch (XmlPullParserException e) {
+ NotFoundException newE = new NotFoundException();
+ newE.initCause(e);
+ throw newE;
+ } catch (FileNotFoundException e) {
+ NotFoundException newE = new NotFoundException();
+ newE.initCause(e);
+ throw newE;
+ }
+ }
+
+
+ @Override
public InputStream openRawResource(int id) throws NotFoundException {
IResourceValue value = getResourceValue(id, mPlatformResourceFlag);
@@ -482,7 +514,7 @@
if (resourceInfo == null && mProjectCallback != null) {
resourceInfo = mProjectCallback.resolveResourceValue(id);
}
-
+
String message = null;
if (resourceInfo != null) {
message = String.format(
@@ -492,7 +524,7 @@
message = String.format(
"Could not resolve resource value: 0x%1$X.", id);
}
-
+
throw new NotFoundException(message);
}
}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
index 76bd8d4..c07baff 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
@@ -40,7 +40,7 @@
for (String path : osJarPath) {
log.info("Input : %1$s", path);
}
-
+
try {
AsmGenerator agen = new AsmGenerator(log, osDestJar[0],
new Class<?>[] { // classes to inject in the final JAR
@@ -66,8 +66,10 @@
"android.graphics.ComposeShader", "android.graphics._Original_ComposeShader",
"android.graphics.RadialGradient", "android.graphics._Original_RadialGradient",
"android.graphics.SweepGradient", "android.graphics._Original_SweepGradient",
+ "android.os.ServiceManager", "android.os._Original_ServiceManager",
"android.util.FloatMath", "android.util._Original_FloatMath",
"android.view.SurfaceView", "android.view._Original_SurfaceView",
+ "android.view.accessibility.AccessibilityManager", "android.view.accessibility._Original_AccessibilityManager",
},
new String[] { // methods deleted from their return type.
"android.graphics.Paint", // class to delete method from
@@ -101,7 +103,7 @@
});
aa.analyze();
agen.generate();
-
+
// Throw an error if any class failed to get renamed by the generator
//
// IMPORTANT: if you're building the platform and you get this error message,
@@ -123,7 +125,7 @@
}
System.exit(1);
}
-
+
System.exit(0);
} catch (IOException e) {
log.exception(e, "Failed to load jar");
@@ -158,7 +160,7 @@
return false;
}
}
-
+
if (osJarPath.isEmpty()) {
log.error("Missing parameter: path to input jar");
return false;
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 083cda3..fa24a98 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -39,6 +39,7 @@
import android.util.Config;
import android.app.Notification;
import android.app.PendingIntent;
+import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothA2dp;
import android.content.ContentResolver;
@@ -49,6 +50,7 @@
import java.util.List;
import java.util.ArrayList;
+import java.util.Set;
import java.net.UnknownHostException;
/**
@@ -645,10 +647,10 @@
private void checkIsBluetoothPlaying() {
boolean isBluetoothPlaying = false;
- List<String> connected = mBluetoothA2dp.listConnectedSinks();
+ Set<BluetoothDevice> connected = mBluetoothA2dp.getConnectedSinks();
- for (String address : connected) {
- if (mBluetoothA2dp.getSinkState(address) == BluetoothA2dp.STATE_PLAYING) {
+ for (BluetoothDevice device : connected) {
+ if (mBluetoothA2dp.getSinkState(device) == BluetoothA2dp.STATE_PLAYING) {
isBluetoothPlaying = true;
break;
}