Merge change 23908 into eclair
* changes:
Add another testcase for moto to reproduce bug #2099685 to the stagefright commandline app.
diff --git a/api/current.xml b/api/current.xml
index b052a61..7bb99e4 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -17373,6 +17373,21 @@
visibility="public"
>
</method>
+<method name="getRunningServiceControlPanel"
+ return="android.app.PendingIntent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="service" type="android.content.ComponentName">
+</parameter>
+<exception name="SecurityException" type="java.lang.SecurityException">
+</exception>
+</method>
<method name="getRunningServices"
return="java.util.List<android.app.ActivityManager.RunningServiceInfo>"
abstract="false"
@@ -17942,6 +17957,39 @@
visibility="public"
>
</field>
+<field name="REASON_PROVIDER_IN_USE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="REASON_SERVICE_IN_USE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="REASON_UNKNOWN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="importance"
type="int"
transient="false"
@@ -17952,6 +18000,36 @@
visibility="public"
>
</field>
+<field name="importanceReasonCode"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="importanceReasonComponent"
+ type="android.content.ComponentName"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="importanceReasonPid"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="lru"
type="int"
transient="false"
@@ -18125,6 +18203,26 @@
visibility="public"
>
</field>
+<field name="clientLabel"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="clientPackage"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="crashCount"
type="int"
transient="false"
@@ -112103,6 +112201,17 @@
visibility="public"
>
</constructor>
+<field name="ACTION_ACCESSIBILITY_SETTINGS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.settings.ACCESSIBILITY_SETTINGS""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="ACTION_AIRPLANE_MODE_SETTINGS"
type="java.lang.String"
transient="false"
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index ad06fa9..af73112 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -366,6 +366,19 @@
*/
public int flags;
+ /**
+ * For special services that are bound to by system code, this is
+ * the package that holds the binding.
+ */
+ public String clientPackage;
+
+ /**
+ * For special services that are bound to by system code, this is
+ * a string resource providing a user-visible label for who the
+ * client is.
+ */
+ public int clientLabel;
+
public RunningServiceInfo() {
}
@@ -386,6 +399,8 @@
dest.writeLong(lastActivityTime);
dest.writeLong(restarting);
dest.writeInt(this.flags);
+ dest.writeString(clientPackage);
+ dest.writeInt(clientLabel);
}
public void readFromParcel(Parcel source) {
@@ -401,6 +416,8 @@
lastActivityTime = source.readLong();
restarting = source.readLong();
flags = source.readInt();
+ clientPackage = source.readString();
+ clientLabel = source.readInt();
}
public static final Creator<RunningServiceInfo> CREATOR = new Creator<RunningServiceInfo>() {
@@ -439,6 +456,22 @@
}
/**
+ * Returns a PendingIntent you can start to show a control panel for the
+ * given running service. If the service does not have a control panel,
+ * null is returned.
+ */
+ public PendingIntent getRunningServiceControlPanel(ComponentName service)
+ throws SecurityException {
+ try {
+ return ActivityManagerNative.getDefault()
+ .getRunningServiceControlPanel(service);
+ } catch (RemoteException e) {
+ // System dead, we will be dead too soon!
+ return null;
+ }
+ }
+
+ /**
* Information you can retrieve about the available memory through
* {@link ActivityManager#getMemoryInfo}.
*/
@@ -704,8 +737,51 @@
*/
public int lru;
+ /**
+ * Constant for {@link #importanceReasonCode}: nothing special has
+ * been specified for the reason for this level.
+ */
+ public static final int REASON_UNKNOWN = 0;
+
+ /**
+ * Constant for {@link #importanceReasonCode}: one of the application's
+ * content providers is being used by another process. The pid of
+ * the client process is in {@link #importanceReasonPid} and the
+ * target provider in this process is in
+ * {@link #importanceReasonComponent}.
+ */
+ public static final int REASON_PROVIDER_IN_USE = 1;
+
+ /**
+ * Constant for {@link #importanceReasonCode}: one of the application's
+ * content providers is being used by another process. The pid of
+ * the client process is in {@link #importanceReasonPid} and the
+ * target provider in this process is in
+ * {@link #importanceReasonComponent}.
+ */
+ public static final int REASON_SERVICE_IN_USE = 2;
+
+ /**
+ * The reason for {@link #importance}, if any.
+ */
+ public int importanceReasonCode;
+
+ /**
+ * For the specified values of {@link #importanceReasonCode}, this
+ * is the process ID of the other process that is a client of this
+ * process. This will be 0 if no other process is using this one.
+ */
+ public int importanceReasonPid;
+
+ /**
+ * For the specified values of {@link #importanceReasonCode}, this
+ * is the name of the component that is being used in this process.
+ */
+ public ComponentName importanceReasonComponent;
+
public RunningAppProcessInfo() {
importance = IMPORTANCE_FOREGROUND;
+ importanceReasonCode = REASON_UNKNOWN;
}
public RunningAppProcessInfo(String pProcessName, int pPid, String pArr[]) {
@@ -724,6 +800,9 @@
dest.writeStringArray(pkgList);
dest.writeInt(importance);
dest.writeInt(lru);
+ dest.writeInt(importanceReasonCode);
+ dest.writeInt(importanceReasonPid);
+ ComponentName.writeToParcel(importanceReasonComponent, dest);
}
public void readFromParcel(Parcel source) {
@@ -732,6 +811,9 @@
pkgList = source.readStringArray();
importance = source.readInt();
lru = source.readInt();
+ importanceReasonCode = source.readInt();
+ importanceReasonPid = source.readInt();
+ importanceReasonComponent = ComponentName.readFromParcel(source);
}
public static final Creator<RunningAppProcessInfo> CREATOR =
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 213f26e..4ed152e 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -510,6 +510,15 @@
return true;
}
+ case GET_RUNNING_SERVICE_CONTROL_PANEL_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ ComponentName comp = ComponentName.CREATOR.createFromParcel(data);
+ PendingIntent pi = getRunningServiceControlPanel(comp);
+ reply.writeNoException();
+ PendingIntent.writePendingIntentOrNullToParcel(pi, reply);
+ return true;
+ }
+
case START_SERVICE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
@@ -1634,6 +1643,21 @@
reply.recycle();
}
+ public PendingIntent getRunningServiceControlPanel(ComponentName service)
+ throws RemoteException
+ {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ service.writeToParcel(data, 0);
+ mRemote.transact(GET_RUNNING_SERVICE_CONTROL_PANEL_TRANSACTION, data, reply, 0);
+ reply.readException();
+ PendingIntent res = PendingIntent.readPendingIntentOrNullFromParcel(reply);
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
+
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType) throws RemoteException
{
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index a7bef54..a937c11 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -126,13 +126,15 @@
public void finishOtherInstances(IBinder token, ComponentName className) throws RemoteException;
/* oneway */
public void reportThumbnail(IBinder token,
- Bitmap thumbnail, CharSequence description) throws RemoteException;
+ Bitmap thumbnail, CharSequence description) throws RemoteException;
public ContentProviderHolder getContentProvider(IApplicationThread caller,
- String name) throws RemoteException;
+ String name) throws RemoteException;
public void removeContentProvider(IApplicationThread caller,
- String name) throws RemoteException;
+ String name) throws RemoteException;
public void publishContentProviders(IApplicationThread caller,
- List<ContentProviderHolder> providers) throws RemoteException;
+ List<ContentProviderHolder> providers) throws RemoteException;
+ public PendingIntent getRunningServiceControlPanel(ComponentName service)
+ throws RemoteException;
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType) throws RemoteException;
public int stopService(IApplicationThread caller, Intent service,
@@ -367,7 +369,7 @@
int PUBLISH_CONTENT_PROVIDERS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+29;
int SET_PERSISTENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+30;
int FINISH_SUB_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+31;
-
+ int GET_RUNNING_SERVICE_CONTROL_PANEL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+32;
int START_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+33;
int STOP_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+34;
int BIND_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+35;
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 87a8f39..1d1161e 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2044,6 +2044,24 @@
public static final String EXTRA_CHANGED_COMPONENT_NAME =
"android.intent.extra.changed_component_name";
+ /**
+ * @hide
+ * Magic extra system code can use when binding, to give a label for
+ * who it is that has bound to a service. This is an integer giving
+ * a framework string resource that can be displayed to the user.
+ */
+ public static final String EXTRA_CLIENT_LABEL =
+ "android.intent.extra.client_label";
+
+ /**
+ * @hide
+ * Magic extra system code can use when binding, to give a PendingIntent object
+ * that can be launched for the user to disable the system's use of this
+ * service.
+ */
+ public static final String EXTRA_CLIENT_INTENT =
+ "android.intent.extra.client_intent";
+
// ---------------------------------------------------------------------
// ---------------------------------------------------------------------
// Intent flags (see mFlags variable).
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 5ffe962..6d27bc7 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -1064,6 +1064,10 @@
Intent intent = new Intent();
intent.setAction("android.content.SyncAdapter");
intent.setComponent(info.componentName);
+ intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
+ com.android.internal.R.string.sync_binding_label);
+ intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
+ mContext, 0, new Intent(Settings.ACTION_SYNC_SETTINGS), 0));
return mContext.bindService(intent, this, Context.BIND_AUTO_CREATE);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 125ed0b..64e47eb 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -119,6 +119,20 @@
"android.settings.AIRPLANE_MODE_SETTINGS";
/**
+ * Activity Action: Show settings for accessibility modules.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_ACCESSIBILITY_SETTINGS =
+ "android.settings.ACCESSIBILITY_SETTINGS";
+
+ /**
* Activity Action: Show settings to allow configuration of security and
* location privacy.
* <p>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 70c9385..3333915 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1943,25 +1943,34 @@
<string-array translatable="false" name="carrier_properties">
</string-array>
- <!-- Title for the selected state of a CompoundButton. -->
- <string name="accessibility_compound_button_selected">checked</string>
+ <!-- Title for the selected state of a CompoundButton. -->
+ <string name="accessibility_compound_button_selected">checked</string>
- <!-- Title for the unselected state of a CompoundButton. -->
- <string name="accessibility_compound_button_unselected">not checked</string>
+ <!-- Title for the unselected state of a CompoundButton. -->
+ <string name="accessibility_compound_button_unselected">not checked</string>
- <string name="grant_credentials_permission_message_desc">The
- listed applications are requesting permission to access the login credentials for account <xliff:g id="account" example="foo@gmail.com">%1$s</xliff:g> from
- <xliff:g id="application" example="Google Apps">%2$s</xliff:g>. Do you wish to grant this permission? If so, your answer will be remembered and you will not be prompted
- again.</string>
+ <string name="grant_credentials_permission_message_desc">The
+ listed applications are requesting permission to access the login credentials for account <xliff:g id="account" example="foo@gmail.com">%1$s</xliff:g> from
+ <xliff:g id="application" example="Google Apps">%2$s</xliff:g>. Do you wish to grant this permission? If so, your answer will be remembered and you will not be prompted
+ again.</string>
- <string name="grant_credentials_permission_message_with_authtokenlabel_desc">The
- listed applications are requesting permission to access the <xliff:g id="type" example="Contacts">%1$s</xliff:g> login credentials for account <xliff:g id="account" example="foo@gmail.com">%2$s</xliff:g> from
- <xliff:g id="application" example="Google Apps">%3$s</xliff:g>. Do you wish to grant this permission? If so, your answer will be remembered and you will not be prompted
- again.</string>
+ <string name="grant_credentials_permission_message_with_authtokenlabel_desc">The
+ listed applications are requesting permission to access the <xliff:g id="type" example="Contacts">%1$s</xliff:g> login credentials for account <xliff:g id="account" example="foo@gmail.com">%2$s</xliff:g> from
+ <xliff:g id="application" example="Google Apps">%3$s</xliff:g>. Do you wish to grant this permission? If so, your answer will be remembered and you will not be prompted
+ again.</string>
- <string name="allow">Allow</string>
- <string name="deny">Deny</string>
- <string name="permission_request_notification_title">Permission Requested</string>
- <string name="permission_request_notification_subtitle">for account <xliff:g id="account" example="foo@gmail.com">%s</xliff:g></string>
+ <string name="allow">Allow</string>
+ <string name="deny">Deny</string>
+ <string name="permission_request_notification_title">Permission Requested</string>
+ <string name="permission_request_notification_subtitle">for account <xliff:g id="account" example="foo@gmail.com">%s</xliff:g></string>
+ <!-- Label to show for a service that is running because it is an input method. -->
+ <string name="input_method_binding_label">Input method</string>
+ <!-- Label to show for a service that is running because it is a sync adapter. -->
+ <string name="sync_binding_label">Sync</string>
+ <!-- Label to show for a service that is running because it is an accessibility module. -->
+ <string name="accessibility_binding_label">Accessibility</string>
+ <!-- Label to show for a service that is running because it is a wallpaper. -->
+ <string name="wallpaper_binding_label">Wallpaper</string>
+
</resources>
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 536f71c..e6cb395 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -110,9 +110,12 @@
}
public void data(Object o) {
- mRS.nAllocationDataFromObject(mID, mType, o);
+ mRS.nAllocationSubDataFromObject(mID, mType, 0, o);
}
+ public void subData(int offset, Object o) {
+ mRS.nAllocationSubDataFromObject(mID, mType, offset, o);
+ }
public class Adapter1D extends BaseObj {
Adapter1D(int id, RenderScript rs) {
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index 0ca112c..0b7e667 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -244,8 +244,8 @@
}
public Builder addFloatXY(String prefix) {
- add(DataType.FLOAT, DataKind.X, false, 32, prefix + "X");
- add(DataType.FLOAT, DataKind.Y, false, 32, prefix + "Y");
+ add(DataType.FLOAT, DataKind.X, false, 32, prefix + "x");
+ add(DataType.FLOAT, DataKind.Y, false, 32, prefix + "y");
return this;
}
@@ -257,9 +257,9 @@
}
public Builder addFloatXYZ(String prefix) {
- add(DataType.FLOAT, DataKind.X, false, 32, prefix + "X");
- add(DataType.FLOAT, DataKind.Y, false, 32, prefix + "Y");
- add(DataType.FLOAT, DataKind.Z, false, 32, prefix + "Z");
+ add(DataType.FLOAT, DataKind.X, false, 32, prefix + "x");
+ add(DataType.FLOAT, DataKind.Y, false, 32, prefix + "y");
+ add(DataType.FLOAT, DataKind.Z, false, 32, prefix + "z");
return this;
}
@@ -270,8 +270,8 @@
}
public Builder addFloatST(String prefix) {
- add(DataType.FLOAT, DataKind.S, false, 32, prefix + "S");
- add(DataType.FLOAT, DataKind.T, false, 32, prefix + "T");
+ add(DataType.FLOAT, DataKind.S, false, 32, prefix + "s");
+ add(DataType.FLOAT, DataKind.T, false, 32, prefix + "t");
return this;
}
@@ -283,9 +283,9 @@
}
public Builder addFloatNorm(String prefix) {
- add(DataType.FLOAT, DataKind.NX, false, 32, prefix + "NX");
- add(DataType.FLOAT, DataKind.NY, false, 32, prefix + "NY");
- add(DataType.FLOAT, DataKind.NZ, false, 32, prefix + "NZ");
+ add(DataType.FLOAT, DataKind.NX, false, 32, prefix + "nx");
+ add(DataType.FLOAT, DataKind.NY, false, 32, prefix + "ny");
+ add(DataType.FLOAT, DataKind.NZ, false, 32, prefix + "nz");
return this;
}
@@ -294,8 +294,8 @@
return this;
}
- public Builder addFloatPointSize(String name) {
- add(DataType.FLOAT, DataKind.POINT_SIZE, false, 32, name);
+ public Builder addFloatPointSize(String prefix) {
+ add(DataType.FLOAT, DataKind.POINT_SIZE, false, 32, prefix + "pointSize");
return this;
}
@@ -307,9 +307,9 @@
}
public Builder addFloatRGB(String prefix) {
- add(DataType.FLOAT, DataKind.RED, false, 32, prefix + "R");
- add(DataType.FLOAT, DataKind.GREEN, false, 32, prefix + "G");
- add(DataType.FLOAT, DataKind.BLUE, false, 32, prefix + "B");
+ add(DataType.FLOAT, DataKind.RED, false, 32, prefix + "r");
+ add(DataType.FLOAT, DataKind.GREEN, false, 32, prefix + "g");
+ add(DataType.FLOAT, DataKind.BLUE, false, 32, prefix + "b");
return this;
}
@@ -322,10 +322,10 @@
}
public Builder addFloatRGBA(String prefix) {
- add(DataType.FLOAT, DataKind.RED, false, 32, prefix + "R");
- add(DataType.FLOAT, DataKind.GREEN, false, 32, prefix + "G");
- add(DataType.FLOAT, DataKind.BLUE, false, 32, prefix + "B");
- add(DataType.FLOAT, DataKind.ALPHA, false, 32, prefix + "A");
+ add(DataType.FLOAT, DataKind.RED, false, 32, prefix + "r");
+ add(DataType.FLOAT, DataKind.GREEN, false, 32, prefix + "g");
+ add(DataType.FLOAT, DataKind.BLUE, false, 32, prefix + "b");
+ add(DataType.FLOAT, DataKind.ALPHA, false, 32, prefix + "a");
return this;
}
@@ -338,10 +338,10 @@
}
public Builder addUNorm8RGBA(String prefix) {
- add(DataType.UNSIGNED, DataKind.RED, true, 8, prefix + "R");
- add(DataType.UNSIGNED, DataKind.GREEN, true, 8, prefix + "G");
- add(DataType.UNSIGNED, DataKind.BLUE, true, 8, prefix + "B");
- add(DataType.UNSIGNED, DataKind.ALPHA, true, 8, prefix + "A");
+ add(DataType.UNSIGNED, DataKind.RED, true, 8, prefix + "r");
+ add(DataType.UNSIGNED, DataKind.GREEN, true, 8, prefix + "g");
+ add(DataType.UNSIGNED, DataKind.BLUE, true, 8, prefix + "b");
+ add(DataType.UNSIGNED, DataKind.ALPHA, true, 8, prefix + "a");
return this;
}
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 0f188f6..bd345e5 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -106,7 +106,7 @@
native void nAllocationSubData2D(int id, int xoff, int yoff, int w, int h, float[] d, int sizeBytes);
native void nAllocationRead(int id, int[] d);
native void nAllocationRead(int id, float[] d);
- native void nAllocationDataFromObject(int id, Type t, Object o);
+ native void nAllocationSubDataFromObject(int id, Type t, int offset, Object o);
native void nTriangleMeshBegin(int vertex, int index);
native void nTriangleMeshAddVertex_XY (float x, float y);
diff --git a/graphics/java/android/renderscript/SimpleMesh.java b/graphics/java/android/renderscript/SimpleMesh.java
index e66fb8a..5d87654 100644
--- a/graphics/java/android/renderscript/SimpleMesh.java
+++ b/graphics/java/android/renderscript/SimpleMesh.java
@@ -50,6 +50,13 @@
return Allocation.createTyped(mRS, mIndexType);
}
+ public Type getVertexType(int slot) {
+ return mVertexTypes[slot];
+ }
+
+ public Type getIndexType() {
+ return mIndexType;
+ }
public static class Builder {
RenderScript mRS;
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 558146d..62c3914 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -543,7 +543,7 @@
//{"nAllocationDataFromObject", "(ILandroid/renderscript/Type;Ljava/lang/Object;)V", (void*)nAllocationDataFromObject },
static void
-nAllocationDataFromObject(JNIEnv *_env, jobject _this, jint alloc, jobject _type, jobject _o)
+nAllocationSubDataFromObject(JNIEnv *_env, jobject _this, jint alloc, jobject _type, jint offset, jobject _o)
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
LOG_API("nAllocationDataFromObject con(%p), alloc(%p)", con, (RsAllocation)alloc);
@@ -556,7 +556,7 @@
const TypeFieldCache *tfc = &tc->fields[ct];
buf = tfc->ptr(_env, _o, tfc->field, buf);
}
- rsAllocationData(con, (RsAllocation)alloc, bufAlloc, tc->size);
+ rsAllocation1DSubData(con, (RsAllocation)alloc, offset, 1, bufAlloc, tc->size);
const uint32_t * tmp = (const uint32_t *)bufAlloc;
free(bufAlloc);
}
@@ -1282,7 +1282,7 @@
{"nAllocationSubData2D", "(IIIII[FI)V", (void*)nAllocationSubData2D_f },
{"nAllocationRead", "(I[I)V", (void*)nAllocationRead_i },
{"nAllocationRead", "(I[F)V", (void*)nAllocationRead_f },
-{"nAllocationDataFromObject", "(ILandroid/renderscript/Type;Ljava/lang/Object;)V", (void*)nAllocationDataFromObject },
+{"nAllocationSubDataFromObject", "(ILandroid/renderscript/Type;ILjava/lang/Object;)V", (void*)nAllocationSubDataFromObject },
{"nTriangleMeshBegin", "(II)V", (void*)nTriangleMeshBegin },
{"nTriangleMeshAddVertex_XY", "(FF)V", (void*)nTriangleMeshAddVertex_XY },
diff --git a/libs/rs/java/Fall/res/raw/fall.c b/libs/rs/java/Fall/res/raw/fall.c
index f348a62..c09f43c 100644
--- a/libs/rs/java/Fall/res/raw/fall.c
+++ b/libs/rs/java/Fall/res/raw/fall.c
@@ -52,8 +52,8 @@
}
void dropWithStrength(int x, int y, int r, int s) {
- int width = State_meshWidth;
- int height = State_meshHeight;
+ int width = State->meshWidth;
+ int height = State->meshHeight;
if (x < r) x = r;
if (y < r) y = r;
@@ -62,8 +62,8 @@
x = width - x;
- int rippleMapSize = State_rippleMapSize;
- int index = State_rippleIndex;
+ int rippleMapSize = State->rippleMapSize;
+ int index = State->rippleIndex;
int origin = offset(0, 0, width);
int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
@@ -94,10 +94,10 @@
}
void updateRipples() {
- int rippleMapSize = State_rippleMapSize;
- int width = State_meshWidth;
- int height = State_meshHeight;
- int index = State_rippleIndex;
+ int rippleMapSize = State->rippleMapSize;
+ int width = State->meshWidth;
+ int height = State->meshHeight;
+ int index = State->rippleIndex;
int origin = offset(0, 0, width);
int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
@@ -139,9 +139,9 @@
void generateRipples() {
int rippleMapSize = loadI32(RSID_STATE, OFFSETOF_WorldState_rippleMapSize);
- int width = State_meshWidth;
- int height = State_meshHeight;
- int index = State_rippleIndex;
+ int width = State->meshWidth;
+ int height = State->meshHeight;
+ int index = State->rippleIndex;
int origin = offset(0, 0, width);
int b = width + 2;
@@ -180,7 +180,7 @@
// Update Z coordinate of the vertex
vertices[index + 7] = dy * fy;
-
+
w -= 1;
current += 1;
wave = nextWave;
@@ -210,7 +210,7 @@
float v2x = vertices[o1 + 5];
float v2y = vertices[o1 + 6];
float v2z = vertices[o1 + 7];
-
+
// V3
float v3x = vertices[ow + 5];
float v3y = vertices[ow + 6];
@@ -236,7 +236,7 @@
n3x *= len;
n3y *= len;
n3z *= len;
-
+
// V2
v2x = vertices[ow1 + 5];
v2y = vertices[ow1 + 6];
@@ -266,7 +266,7 @@
vertices[o + 0] = n3x;
vertices[o + 1] = n3y;
vertices[o + 2] = -n3z;
-
+
// reset Z
//vertices[(yOffset + x) << 3 + 7] = 0.0f;
}
@@ -322,7 +322,7 @@
float z2 = 0.0f;
float z3 = 0.0f;
float z4 = 0.0f;
-
+
float a = leafStruct[LEAF_STRUCT_ALTITUDE];
float s = leafStruct[LEAF_STRUCT_SCALE];
float r = leafStruct[LEAF_STRUCT_ANGLE];
@@ -384,7 +384,7 @@
LEAF_SIZE * s + y < -glHeight / 2.0f) {
int sprite = randf(LEAVES_TEXTURES_COUNT);
- leafStruct[LEAF_STRUCT_X] = randf2(-1.0f, 1.0f);
+ leafStruct[LEAF_STRUCT_X] = randf2(-1.0f, 1.0f);
leafStruct[LEAF_STRUCT_Y] = glHeight / 2.0f + LEAF_SIZE * 2 * randf(1.0f);
leafStruct[LEAF_STRUCT_SCALE] = randf2(0.4f, 0.5f);
leafStruct[LEAF_STRUCT_SPIN] = degf(randf2(-0.02f, 0.02f)) / 4.0f;
@@ -401,20 +401,20 @@
bindProgramVertex(NAMED_PVSky);
bindTexture(NAMED_PFBackground, 0, NAMED_TLeaves);
- int leavesCount = State_leavesCount;
+ int leavesCount = State->leavesCount;
int count = leavesCount * LEAF_STRUCT_FIELDS_COUNT;
- int width = State_meshWidth;
- int height = State_meshHeight;
- float glWidth = State_glWidth;
- float glHeight = State_glHeight;
+ int width = State->meshWidth;
+ int height = State->meshHeight;
+ float glWidth = State->glWidth;
+ float glHeight = State->glHeight;
- float *vertices = loadTriangleMeshVerticesF(NAMED_WaterMesh);
+ float *vertices = loadTriangleMeshVerticesF(NAMED_WaterMesh);
int i = 0;
for ( ; i < count; i += LEAF_STRUCT_FIELDS_COUNT) {
drawLeaf(i, vertices, width, height, glWidth, glHeight);
}
-
+
float matrix[16];
matrixLoadIdentity(matrix);
vpLoadModelMatrix(matrix);
@@ -433,8 +433,8 @@
bindProgramFragmentStore(NAMED_PFSLeaf);
bindTexture(NAMED_PFSky, 0, NAMED_TSky);
- float x = State_skyOffsetX + State_skySpeedX;
- float y = State_skyOffsetY + State_skySpeedY;
+ float x = State->skyOffsetX + State->skySpeedX;
+ float y = State->skyOffsetY + State->skySpeedY;
if (x > 1.0f) x = 0.0f;
if (x < -1.0f) x = 0.0f;
@@ -467,8 +467,8 @@
}
void drawNormals() {
- int width = State_meshWidth;
- int height = State_meshHeight;
+ int width = State->meshWidth;
+ int height = State->meshHeight;
float *vertices = loadTriangleMeshVerticesF(NAMED_WaterMesh);
@@ -496,12 +496,10 @@
}
int main(int index) {
- int dropX = Drop_dropX;
- if (dropX != -1) {
- int dropY = Drop_dropY;
- drop(dropX, dropY, DROP_RADIUS);
- storeI32(RSID_DROP, OFFSETOF_DropState_dropX, -1);
- storeI32(RSID_DROP, OFFSETOF_DropState_dropY, -1);
+ if (Drop->dropX != -1) {
+ drop(Drop->dropX, Drop->dropY, DROP_RADIUS);
+ Drop->dropX = -1;
+ Drop->dropY = -1;
}
updateRipples();
diff --git a/libs/rs/java/Film/res/raw/filmstrip.c b/libs/rs/java/Film/res/raw/filmstrip.c
index 8f3d930..8fbfee1 100644
--- a/libs/rs/java/Film/res/raw/filmstrip.c
+++ b/libs/rs/java/Film/res/raw/filmstrip.c
@@ -5,10 +5,6 @@
#pragma stateFragment(PFBackground)
#pragma stateFragmentStore(PSBackground)
-#define POS_TRANSLATE 0
-#define POS_ROTATE 1
-#define POS_FOCUS 2
-
#define STATE_TRIANGLE_OFFSET_COUNT 0
#define STATE_LAST_FOCUS 1
@@ -18,12 +14,14 @@
// bank1: (r) The position information
// bank2: (rw) The temporary texture state
+int lastFocus;
+
int main(int index)
{
float mat1[16];
- float trans = Pos_translate;
- float rot = Pos_rotate;
+ float trans = Pos->translate;
+ float rot = Pos->rotate;
matrixLoadScale(mat1, 2.f, 2.f, 2.f);
matrixTranslate(mat1, 0.f, 0.f, trans);
@@ -39,7 +37,7 @@
bindProgramFragment(NAMED_PFImages);
bindProgramVertex(NAMED_PVImages);
- float focusPos = Pos_focus;
+ float focusPos = Pos->focus;
int focusID = 0;
int lastFocusID = loadI32(2, STATE_LAST_FOCUS);
int imgCount = 13;
@@ -63,9 +61,9 @@
}
}
*/
- storeI32(2, STATE_LAST_FOCUS, focusID);
+ lastFocus = focusID;
- int triangleOffsetsCount = Pos_triangleOffsetCount;
+ int triangleOffsetsCount = Pos->triangleOffsetCount;
int imgId = 0;
for (imgId=1; imgId <= imgCount; imgId++) {
diff --git a/libs/rs/java/Fountain/res/raw/fountain.c b/libs/rs/java/Fountain/res/raw/fountain.c
index 99f4048..36516c2 100644
--- a/libs/rs/java/Fountain/res/raw/fountain.c
+++ b/libs/rs/java/Fountain/res/raw/fountain.c
@@ -4,27 +4,32 @@
#pragma stateFragment(default)
#pragma stateFragmentStore(default)
-struct PartStruct {float dx; float dy; float x; float y; int c;};
int newPart = 0;
int main(int launchID) {
int ct;
- int count = Control_count - 1;
- int rate = Control_rate;
+ int count = Control->count;
+ int rate = Control->rate;
float height = getHeight();
- struct PartStruct * p = (struct PartStruct *)loadArrayF(1, 0);
+ struct point_s * p = (struct point_s *)point;
if (rate) {
float rMax = ((float)rate) * 0.005f;
- int x = Control_x;
- int y = Control_y;
- int c = colorFloatRGBAtoUNorm8(Control_r, Control_g, Control_b, 0.99f);
+ int x = Control->x;
+ int y = Control->y;
+ char r = Control->r * 255.f;
+ char g = Control->g * 255.f;
+ char b = Control->b * 255.f;
+ char a = 0xf0;
while (rate--) {
vec2Rand((float *)(p + newPart), rMax);
p[newPart].x = x;
p[newPart].y = y;
- p[newPart].c = c;
+ p[newPart].r = r;
+ p[newPart].g = g;
+ p[newPart].b = b;
+ p[newPart].a = a;
newPart++;
if (newPart >= count) {
newPart = 0;
@@ -45,6 +50,6 @@
}
uploadToBufferObject(NAMED_PartBuffer);
- drawSimpleMeshRange(NAMED_PartMesh, 0, count);
+ drawSimpleMesh(NAMED_PartMesh);
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 6d400c5..f4f9b0c 100644
--- a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
+++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
@@ -79,10 +79,10 @@
mIntAlloc.data(mSD);
Element.Builder eb = new Element.Builder(mRS);
- eb.addFloat(Element.DataKind.USER); //dx
- eb.addFloat(Element.DataKind.USER); //dy
- eb.addFloatXY();
- eb.addUNorm8RGBA();
+ eb.addFloat(Element.DataKind.USER, "dx");
+ eb.addFloat(Element.DataKind.USER, "dy");
+ eb.addFloatXY("");
+ eb.addUNorm8RGBA("");
Element primElement = eb.create();
@@ -102,6 +102,7 @@
sb.setScript(mRes, R.raw.fountain);
sb.setRoot(true);
sb.setType(mSDType, "Control", 0);
+ sb.setType(mSM.getVertexType(0), "point", 1);
Script script = sb.create();
script.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index c28bd02..c132915 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -116,6 +116,7 @@
//glEnable(GL_LIGHT0);
glViewport(0, 0, mEGL.mWidth, mEGL.mHeight);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ glEnable(GL_POINT_SMOOTH);
glClearColor(mRootScript->mEnviroment.mClearColor[0],
mRootScript->mEnviroment.mClearColor[1],
@@ -153,10 +154,18 @@
void Context::timerInit()
{
mTimeLast = getTime();
+ mTimeFrame = mTimeLast;
+ mTimeLastFrame = mTimeLast;
mTimerActive = RS_TIMER_INTERNAL;
timerReset();
}
+void Context::timerFrame()
+{
+ mTimeLastFrame = mTimeFrame;
+ mTimeFrame = getTime();
+}
+
void Context::timerSet(Timers tm)
{
uint64_t last = mTimeLast;
@@ -171,8 +180,10 @@
for (int ct = 0; ct < _RS_TIMER_TOTAL; ct++) {
total += mTimers[ct];
}
+ uint64_t frame = mTimeFrame - mTimeLastFrame;
- LOGV("RS Time Data: Idle %2.1f (%lli), Internal %2.1f (%lli), Script %2.1f (%lli), Clear & Swap %2.1f (%lli)",
+ LOGV("RS: Frame (%lli), Script %2.1f (%lli), Clear & Swap %2.1f (%lli), Idle %2.1f (%lli), Internal %2.1f (%lli)",
+ frame / 1000000,
100.0 * mTimers[RS_TIMER_IDLE] / total, mTimers[RS_TIMER_IDLE] / 1000000,
100.0 * mTimers[RS_TIMER_INTERNAL] / total, mTimers[RS_TIMER_INTERNAL] / 1000000,
100.0 * mTimers[RS_TIMER_SCRIPT] / total, mTimers[RS_TIMER_SCRIPT] / 1000000,
@@ -232,6 +243,7 @@
#endif
eglSwapBuffers(rsc->mEGL.mDisplay, rsc->mEGL.mSurface);
#if RS_LOG_TIMES
+ rsc->timerFrame();
rsc->timerSet(RS_TIMER_INTERNAL);
rsc->timerPrint();
rsc->timerReset();
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index c58a88c..634416b 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -131,6 +131,7 @@
void timerReset();
void timerSet(Timers);
void timerPrint();
+ void timerFrame();
bool checkVersion1_1() const {return (mGL.mMajorVersion > 1) || (mGL.mMinorVersion >= 1); }
bool checkVersion2_0() const {return mGL.mMajorVersion >= 2; }
@@ -202,6 +203,8 @@
uint64_t mTimers[_RS_TIMER_TOTAL];
Timers mTimerActive;
uint64_t mTimeLast;
+ uint64_t mTimeFrame;
+ uint64_t mTimeLastFrame;
};
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 0c7ac18..9d9eb1b 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -67,6 +67,12 @@
= nanoseconds_to_milliseconds(systemTime(SYSTEM_TIME_MONOTONIC));
}
+ for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
+ if (mProgram.mSlotPointers[ct]) {
+ *mProgram.mSlotPointers[ct] = mSlots[ct]->getPtr();
+ }
+ }
+
bool ret = false;
tls->mScript = this;
ret = mProgram.mScript(launchIndex) != 0;
@@ -139,6 +145,7 @@
accRegisterSymbolCallback(mAccScript, symbolLookup, NULL);
accCompileScript(mAccScript);
accGetScriptLabel(mAccScript, "main", (ACCvoid**) &mProgram.mScript);
+ accGetScriptLabel(mAccScript, "init", (ACCvoid**) &mProgram.mInit);
rsAssert(mProgram.mScript);
if (!mProgram.mScript) {
@@ -148,6 +155,19 @@
LOGE(buf);
}
+ if (mProgram.mInit) {
+ mProgram.mInit();
+ }
+
+ for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
+ if (mSlotNames[ct].length() > 0) {
+ accGetScriptLabel(mAccScript,
+ mSlotNames[ct].string(),
+ (ACCvoid**) &mProgram.mSlotPointers[ct]);
+ LOGE("var %s %p", mSlotNames[ct].string(), mProgram.mSlotPointers[ct]);
+ }
+ }
+
mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
mEnviroment.mFragmentStore.set(rsc->getDefaultProgramFragmentStore());
@@ -224,6 +244,19 @@
}
}
+static void appendElementBody(String8 *s, const Element *e)
+{
+ s->append(" {\n");
+ for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) {
+ const Component *c = e->getComponent(ct2);
+ s->append(" ");
+ s->append(c->getCType());
+ s->append(" ");
+ s->append(c->getComponentName());
+ s->append(";\n");
+ }
+ s->append("}");
+}
void ScriptCState::appendVarDefines(String8 *str)
{
@@ -246,6 +279,8 @@
}
}
+
+
void ScriptCState::appendTypes(String8 *str)
{
char buf[256];
@@ -257,6 +292,19 @@
continue;
}
const Element *e = t->getElement();
+ if (e->getName() && (e->getComponentCount() > 1)) {
+ String8 s("struct struct_");
+ s.append(e->getName());
+ appendElementBody(&s, e);
+ s.append(";\n");
+ s.append("#define ");
+ s.append(e->getName());
+ s.append("_t struct struct_");
+ s.append(e->getName());
+ s.append("\n\n");
+ LOGD(s);
+ str->append(s);
+ }
if (t->getName()) {
for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) {
@@ -267,12 +315,39 @@
tmp.append(c->getComponentName());
sprintf(buf, " %i\n", ct2);
tmp.append(buf);
- //LOGD(tmp);
+ LOGD(tmp);
str->append(tmp);
}
}
if (mSlotNames[ct].length() > 0) {
+ String8 s;
+ if (e->getComponentCount() > 1) {
+ if (e->getName()) {
+ // Use the named struct
+ s.setTo(e->getName());
+ s.append("_t *");
+ } else {
+ // create an struct named from the slot.
+ s.setTo("struct ");
+ s.append(mSlotNames[ct]);
+ s.append("_s");
+ appendElementBody(&s, e);
+ s.append(";\n");
+ s.append("struct ");
+ s.append(mSlotNames[ct]);
+ s.append("_s * ");
+ }
+ } else {
+ // Just make an array
+ s.setTo(e->getComponent(0)->getCType());
+ s.append("_t *");
+ }
+ s.append(mSlotNames[ct]);
+ s.append(";\n");
+ LOGD(s);
+ str->append(s);
+#if 0
for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) {
const Component *c = e->getComponent(ct2);
tmp.setTo("#define ");
@@ -295,12 +370,12 @@
sprintf(buf, "%i, %i)\n", ct, ct2);
tmp.append(buf);
- //LOGD(tmp);
+ LOGD(tmp);
str->append(tmp);
}
+#endif
}
}
-
}
diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h
index 302515e..8aa99ef 100644
--- a/libs/rs/rsScriptC.h
+++ b/libs/rs/rsScriptC.h
@@ -35,6 +35,7 @@
{
public:
typedef int (*RunScript_t)(uint32_t launchIndex);
+ typedef void (*VoidFunc_t)();
ScriptC();
virtual ~ScriptC();
@@ -48,6 +49,9 @@
int mVersionMinor;
RunScript_t mScript;
+ VoidFunc_t mInit;
+
+ void ** mSlotPointers[MAX_SCRIPT_BANKS];
};
Program_t mProgram;
diff --git a/services/java/com/android/server/AccessibilityManagerService.java b/services/java/com/android/server/AccessibilityManagerService.java
index 55007ba..f67a7ae 100644
--- a/services/java/com/android/server/AccessibilityManagerService.java
+++ b/services/java/com/android/server/AccessibilityManagerService.java
@@ -25,6 +25,7 @@
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.IAccessibilityServiceConnection;
import android.accessibilityservice.IEventListener;
+import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -615,6 +616,10 @@
mId = sIdCounter++;
mComponentName = componentName;
mIntent = new Intent().setComponent(mComponentName);
+ mIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
+ com.android.internal.R.string.accessibility_binding_label);
+ mIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
+ mContext, 0, new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS), 0));
}
/**
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 558a024..1da2b47 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -32,6 +32,7 @@
import android.app.ActivityManagerNative;
import android.app.AlertDialog;
+import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -765,6 +766,10 @@
mCurIntent = new Intent(InputMethod.SERVICE_INTERFACE);
mCurIntent.setComponent(info.getComponent());
+ mCurIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
+ com.android.internal.R.string.input_method_binding_label);
+ mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
+ mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
if (mContext.bindService(mCurIntent, this, Context.BIND_AUTO_CREATE)) {
mLastBindTime = SystemClock.uptimeMillis();
mHaveConnection = true;
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index c101463..cc977b0 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -21,6 +21,7 @@
import android.app.IWallpaperManager;
import android.app.IWallpaperManagerCallback;
+import android.app.PendingIntent;
import android.backup.BackupManager;
import android.content.ComponentName;
import android.content.Context;
@@ -40,6 +41,7 @@
import android.os.RemoteCallbackList;
import android.os.ServiceManager;
import android.os.SystemClock;
+import android.provider.Settings;
import android.service.wallpaper.IWallpaperConnection;
import android.service.wallpaper.IWallpaperEngine;
import android.service.wallpaper.IWallpaperService;
@@ -376,6 +378,10 @@
// Bind the service!
WallpaperConnection newConn = new WallpaperConnection();
intent.setComponent(realName);
+ intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
+ com.android.internal.R.string.wallpaper_binding_label);
+ intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
+ mContext, 0, new Intent(Intent.ACTION_SET_WALLPAPER), 0));
if (!mContext.bindService(intent, newConn,
Context.BIND_AUTO_CREATE)) {
throw new IllegalArgumentException("Unable to bind service: "
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 03ebf0c..9554a22 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -8866,6 +8866,16 @@
} else {
currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
}
+ currApp.importanceReasonCode = app.adjTypeCode;
+ if (app.adjSource instanceof ProcessRecord) {
+ currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid;
+ } else if (app.adjSource instanceof HistoryRecord) {
+ HistoryRecord r = (HistoryRecord)app.adjSource;
+ if (r.app != null) currApp.importanceReasonPid = r.app.pid;
+ }
+ if (app.adjTarget instanceof ComponentName) {
+ currApp.importanceReasonComponent = (ComponentName)app.adjTarget;
+ }
//Log.v(TAG, "Proc " + app.processName + ": imp=" + currApp.importance
// + " lru=" + currApp.lru);
if (runList == null) {
@@ -9888,6 +9898,13 @@
if (r.app != null && r.app.persistent) {
info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
}
+ for (ConnectionRecord conn : r.connections.values()) {
+ if (conn.clientLabel != 0) {
+ info.clientPackage = conn.binding.client.info.packageName;
+ info.clientLabel = conn.clientLabel;
+ break;
+ }
+ }
return info;
}
@@ -9916,6 +9933,20 @@
}
}
+ public PendingIntent getRunningServiceControlPanel(ComponentName name) {
+ synchronized (this) {
+ ServiceRecord r = mServices.get(name);
+ if (r != null) {
+ for (ConnectionRecord conn : r.connections.values()) {
+ if (conn.clientIntent != null) {
+ return conn.clientIntent;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
private final ServiceRecord findServiceLocked(ComponentName name,
IBinder token) {
ServiceRecord r = mServices.get(name);
@@ -10783,6 +10814,29 @@
activity = (HistoryRecord)mHistory.get(aindex);
}
+ int clientLabel = 0;
+ PendingIntent clientIntent = null;
+
+ if (callerApp.info.uid == Process.SYSTEM_UID) {
+ // Hacky kind of thing -- allow system stuff to tell us
+ // what they are, so we can report this elsewhere for
+ // others to know why certain services are running.
+ try {
+ clientIntent = (PendingIntent)service.getParcelableExtra(
+ Intent.EXTRA_CLIENT_INTENT);
+ } catch (RuntimeException e) {
+ }
+ if (clientIntent != null) {
+ clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
+ if (clientLabel != 0) {
+ // There are no useful extras in the intent, trash them.
+ // System code calling with this stuff just needs to know
+ // this will happen.
+ service = service.cloneFilter();
+ }
+ }
+ }
+
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType,
Binder.getCallingPid(), Binder.getCallingUid());
@@ -10803,7 +10857,7 @@
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity,
- connection, flags);
+ connection, flags, clientLabel, clientIntent);
IBinder binder = connection.asBinder();
s.connections.put(binder, c);
@@ -12776,6 +12830,7 @@
return (app.curAdj=app.maxAdj);
}
+ app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
app.adjSource = null;
app.adjTarget = null;
@@ -12909,6 +12964,8 @@
adj = clientAdj > VISIBLE_APP_ADJ
? clientAdj : VISIBLE_APP_ADJ;
app.adjType = "service";
+ app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+ .REASON_SERVICE_IN_USE;
app.adjSource = cr.binding.client;
app.adjTarget = s.serviceInfo.name;
}
@@ -12922,6 +12979,8 @@
|| a.state == ActivityState.PAUSING)) {
adj = FOREGROUND_APP_ADJ;
app.adjType = "service";
+ app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+ .REASON_SERVICE_IN_USE;
app.adjSource = a;
app.adjTarget = s.serviceInfo.name;
}
@@ -12964,6 +13023,8 @@
adj = clientAdj > FOREGROUND_APP_ADJ
? clientAdj : FOREGROUND_APP_ADJ;
app.adjType = "provider";
+ app.adjTypeCode = ActivityManager.RunningAppProcessInfo
+ .REASON_PROVIDER_IN_USE;
app.adjSource = client;
app.adjTarget = cpr.info.name;
}
diff --git a/services/java/com/android/server/am/ConnectionRecord.java b/services/java/com/android/server/am/ConnectionRecord.java
index b3343dd..f613b00 100644
--- a/services/java/com/android/server/am/ConnectionRecord.java
+++ b/services/java/com/android/server/am/ConnectionRecord.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import android.app.IServiceConnection;
+import android.app.PendingIntent;
import java.io.PrintWriter;
@@ -28,6 +29,8 @@
final HistoryRecord activity; // If non-null, the owning activity.
final IServiceConnection conn; // The client connection.
final int flags; // Binding options.
+ final int clientLabel; // String resource labeling this client.
+ final PendingIntent clientIntent; // How to launch the client.
String stringName; // Caching of toString.
void dump(PrintWriter pw, String prefix) {
@@ -40,11 +43,14 @@
}
ConnectionRecord(AppBindRecord _binding, HistoryRecord _activity,
- IServiceConnection _conn, int _flags) {
+ IServiceConnection _conn, int _flags,
+ int _clientLabel, PendingIntent _clientIntent) {
binding = _binding;
activity = _activity;
conn = _conn;
flags = _flags;
+ clientLabel = _clientLabel;
+ clientIntent = _clientIntent;
}
public String toString() {
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 76fdf09..d05b44b 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -75,6 +75,7 @@
boolean reportLowMemory; // Set to true when waiting to report low mem
int lastPss; // Last pss size reported by app.
String adjType; // Debugging: primary thing impacting oom_adj.
+ int adjTypeCode; // Debugging: adj code to report to app.
Object adjSource; // Debugging: option dependent object.
Object adjTarget; // Debugging: target component impacting oom_adj.
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a690e3c..a744486 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -484,7 +484,12 @@
* @return true if a ICC card is present
*/
public boolean hasIccCard() {
- return PhoneFactory.getDefaultPhone().getIccCard().hasIccCard();
+ try {
+ return getITelephony().hasIccCard();
+ } catch (RemoteException ex) {
+ // Assume no ICC card if remote exception which shouldn't happen
+ return false;
+ }
}
/**
diff --git a/telephony/java/com/android/internal/telephony/AdnRecord.java b/telephony/java/com/android/internal/telephony/AdnRecord.java
index 5f40579..0896ba6 100644
--- a/telephony/java/com/android/internal/telephony/AdnRecord.java
+++ b/telephony/java/com/android/internal/telephony/AdnRecord.java
@@ -23,6 +23,8 @@
import com.android.internal.telephony.GsmAlphabet;
+import java.util.Arrays;
+
/**
*
@@ -38,6 +40,7 @@
String alphaTag = "";
String number = "";
+ String[] emails;
int extRecord = 0xff;
int efid; // or 0 if none
int recordNumber; // or 0 if none
@@ -74,13 +77,15 @@
int recordNumber;
String alphaTag;
String number;
+ String[] emails;
efid = source.readInt();
recordNumber = source.readInt();
alphaTag = source.readString();
number = source.readString();
+ emails = source.readStringArray();
- return new AdnRecord(efid, recordNumber, alphaTag, number);
+ return new AdnRecord(efid, recordNumber, alphaTag, number, emails);
}
public AdnRecord[] newArray(int size) {
@@ -90,29 +95,38 @@
//***** Constructor
- public
- AdnRecord (byte[] record) {
+ public AdnRecord (byte[] record) {
this(0, 0, record);
}
- public
- AdnRecord (int efid, int recordNumber, byte[] record) {
+ public AdnRecord (int efid, int recordNumber, byte[] record) {
this.efid = efid;
this.recordNumber = recordNumber;
parseRecord(record);
}
- public
- AdnRecord (String alphaTag, String number) {
+ public AdnRecord (String alphaTag, String number) {
this(0, 0, alphaTag, number);
}
- public
- AdnRecord (int efid, int recordNumber, String alphaTag, String number) {
+ public AdnRecord (String alphaTag, String number, String[] emails) {
+ this(0, 0, alphaTag, number, emails);
+ }
+
+ public AdnRecord (int efid, int recordNumber, String alphaTag, String number, String[] emails) {
this.efid = efid;
this.recordNumber = recordNumber;
this.alphaTag = alphaTag;
this.number = number;
+ this.emails = emails;
+ }
+
+ public AdnRecord(int efid, int recordNumber, String alphaTag, String number) {
+ this.efid = efid;
+ this.recordNumber = recordNumber;
+ this.alphaTag = alphaTag;
+ this.number = number;
+ this.emails = null;
}
//***** Instance Methods
@@ -125,12 +139,20 @@
return number;
}
+ public String[] getEmails() {
+ return emails;
+ }
+
+ public void setEmails(String[] emails) {
+ this.emails = emails;
+ }
+
public String toString() {
- return "ADN Record '" + alphaTag + "' '" + number + "'";
+ return "ADN Record '" + alphaTag + "' '" + number + " " + emails + "'";
}
public boolean isEmpty() {
- return alphaTag.equals("") && number.equals("");
+ return alphaTag.equals("") && number.equals("") && emails == null;
}
public boolean hasExtendedRecord() {
@@ -139,7 +161,8 @@
public boolean isEqual(AdnRecord adn) {
return ( alphaTag.equals(adn.getAlphaTag()) &&
- number.equals(adn.getNumber()) );
+ number.equals(adn.getNumber()) &&
+ Arrays.equals(emails, adn.getEmails()));
}
//***** Parcelable Implementation
@@ -152,6 +175,7 @@
dest.writeInt(recordNumber);
dest.writeString(alphaTag);
dest.writeString(number);
+ dest.writeStringArray(emails);
}
/**
@@ -274,10 +298,13 @@
extRecord = 0xff & record[record.length - 1];
+ emails = null;
+
} catch (RuntimeException ex) {
Log.w(LOG_TAG, "Error parsing AdnRecord", ex);
number = "";
alphaTag = "";
+ emails = null;
}
}
}
diff --git a/telephony/java/com/android/internal/telephony/AdnRecordCache.java b/telephony/java/com/android/internal/telephony/AdnRecordCache.java
index c270ae5..c8c0658 100644
--- a/telephony/java/com/android/internal/telephony/AdnRecordCache.java
+++ b/telephony/java/com/android/internal/telephony/AdnRecordCache.java
@@ -16,14 +16,16 @@
package com.android.internal.telephony;
-import android.util.SparseArray;
-import android.util.Log;
-import android.os.Message;
-import android.os.Handler;
import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.telephony.gsm.UsimPhoneBookManager;
+
import java.util.ArrayList;
import java.util.Iterator;
-import com.android.internal.telephony.IccConstants;
/**
* {@hide}
@@ -32,6 +34,7 @@
//***** Instance Variables
PhoneBase phone;
+ private UsimPhoneBookManager mUsimPhoneBookManager;
// Indexed by EF ID
SparseArray<ArrayList<AdnRecord>> adnLikeFiles
@@ -55,6 +58,7 @@
public AdnRecordCache(PhoneBase phone) {
this.phone = phone;
+ mUsimPhoneBookManager = new UsimPhoneBookManager(phone, this);
}
//***** Called from SIMRecords
@@ -64,6 +68,7 @@
*/
public void reset() {
adnLikeFiles.clear();
+ mUsimPhoneBookManager.reset();
clearWaiters();
clearUserWriters();
@@ -103,14 +108,14 @@
*
* See 3GPP TS 51.011 for this mapping
*/
- private int
- extensionEfForEf(int efid) {
+ int extensionEfForEf(int efid) {
switch (efid) {
case EF_MBDN: return EF_EXT6;
case EF_ADN: return EF_EXT1;
case EF_SDN: return EF_EXT3;
case EF_FDN: return EF_EXT2;
case EF_MSISDN: return EF_EXT1;
+ case EF_PBR: return 0; // The EF PBR doesn't have an extension record
default: return -1;
}
}
@@ -223,11 +228,15 @@
* record
*/
public void
- requestLoadAllAdnLike (int efid, Message response) {
+ requestLoadAllAdnLike (int efid, int extensionEf, Message response) {
ArrayList<Message> waiters;
ArrayList<AdnRecord> result;
- result = getRecordsIfLoaded(efid);
+ if (efid == EF_PBR) {
+ result = mUsimPhoneBookManager.loadEfFilesFromUsim();
+ } else {
+ result = getRecordsIfLoaded(efid);
+ }
// Have we already loaded this efid?
if (result != null) {
@@ -258,9 +267,8 @@
adnLikeWaiters.put(efid, waiters);
- int extensionEF = extensionEfForEf(efid);
- if (extensionEF < 0) {
+ if (extensionEf < 0) {
// respond with error if not known ADN-like record
if (response != null) {
@@ -272,7 +280,7 @@
return;
}
- new AdnRecordLoader(phone).loadAllFromEF(efid, extensionEF,
+ new AdnRecordLoader(phone).loadAllFromEF(efid, extensionEf,
obtainMessage(EVENT_LOAD_ALL_ADN_LIKE_DONE, efid, 0));
}
@@ -311,7 +319,7 @@
adnLikeWaiters.delete(efid);
if (ar.exception == null) {
- adnLikeFiles.put(efid, (ArrayList<AdnRecord>) (ar.result));
+ adnLikeFiles.put(efid, (ArrayList<AdnRecord>) ar.result);
}
notifyWaiters(waiters, ar);
break;
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 63c23ae..2328717 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -252,5 +252,10 @@
* Returns the network type
*/
int getNetworkType();
+
+ /**
+ * Return true if an ICC card is present
+ */
+ boolean hasIccCard();
}
diff --git a/telephony/java/com/android/internal/telephony/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java
index 200340e..0f76633 100644
--- a/telephony/java/com/android/internal/telephony/IccCard.java
+++ b/telephony/java/com/android/internal/telephony/IccCard.java
@@ -655,7 +655,7 @@
}
- public boolean hasApplicationType(IccCardApplication.AppType type) {
+ public boolean isApplicationOnIcc(IccCardApplication.AppType type) {
if (mIccCardStatus == null) return false;
for (int i = 0 ; i < mIccCardStatus.getNumApplications(); i++) {
diff --git a/telephony/java/com/android/internal/telephony/IccConstants.java b/telephony/java/com/android/internal/telephony/IccConstants.java
index 7eafafd..acc9197 100644
--- a/telephony/java/com/android/internal/telephony/IccConstants.java
+++ b/telephony/java/com/android/internal/telephony/IccConstants.java
@@ -42,6 +42,9 @@
static final int EF_CFIS = 0x6FCB;
static final int EF_IMG = 0x4f20;
+ // USIM SIM file ids from TS 31.102
+ public static final int EF_PBR = 0x4F30;
+
// GSM SIM file ids from CPHS (phase 2, version 4.2) CPHS4_2.WW6
static final int EF_MAILBOX_CPHS = 0x6F17;
static final int EF_VOICE_MAIL_INDICATOR_CPHS = 0x6F11;
@@ -59,6 +62,7 @@
static final String MF_SIM = "3F00";
static final String DF_TELECOM = "7F10";
+ static final String DF_PHONEBOOK = "5F3A";
static final String DF_GRAPHICS = "5F50";
static final String DF_GSM = "7F20";
static final String DF_CDMA = "7F25";
diff --git a/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java b/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
index 0bcaaa6..31cf6a7 100644
--- a/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
+++ b/telephony/java/com/android/internal/telephony/IccPhoneBookInterfaceManager.java
@@ -115,7 +115,8 @@
* Replace oldAdn with newAdn in ADN-like record in EF
*
* getAdnRecordsInEf must be called at least once before this function,
- * otherwise an error will be returned
+ * otherwise an error will be returned. Currently the email field
+ * if set in the ADN record is ignored.
* throws SecurityException if no WRITE_CONTACTS permission
*
* @param efid must be one among EF_ADN, EF_FDN, and EF_SDN
@@ -167,7 +168,8 @@
* Update an ADN-like EF record by record index
*
* This is useful for iteration the whole ADN file, such as write the whole
- * phone book or erase/format the whole phonebook
+ * phone book or erase/format the whole phonebook. Currently the email field
+ * if set in the ADN record is ignored.
* throws SecurityException if no WRITE_CONTACTS permission
*
* @param efid must be one among EF_ADN, EF_FDN, and EF_SDN
@@ -237,12 +239,13 @@
"Requires android.permission.READ_CONTACTS permission");
}
+ efid = updateEfForIccType(efid);
if (DBG) logd("getAdnRecordsInEF: efid=" + efid);
synchronized(mLock) {
checkThread();
Message response = mBaseHandler.obtainMessage(EVENT_LOAD_DONE);
- adnCache.requestLoadAllAdnLike(efid, response);
+ adnCache.requestLoadAllAdnLike(efid, adnCache.extensionEfForEf(efid), response);
try {
mLock.wait();
} catch (InterruptedException e) {
@@ -262,5 +265,15 @@
}
}
}
+
+ private int updateEfForIccType(int efid) {
+ // Check if we are trying to read ADN records
+ if (efid == IccConstants.EF_ADN) {
+ if (phone.getIccCard().isApplicationOnIcc(IccCardApplication.AppType.APPTYPE_USIM)) {
+ return IccConstants.EF_PBR;
+ }
+ }
+ return efid;
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/IccProvider.java b/telephony/java/com/android/internal/telephony/IccProvider.java
index 4cbd779..ffcfe6f 100644
--- a/telephony/java/com/android/internal/telephony/IccProvider.java
+++ b/telephony/java/com/android/internal/telephony/IccProvider.java
@@ -46,7 +46,8 @@
private static final String[] ADDRESS_BOOK_COLUMN_NAMES = new String[] {
"name",
- "number"
+ "number",
+ "emails"
};
private static final int ADN = 1;
@@ -55,6 +56,7 @@
private static final String STR_TAG = "tag";
private static final String STR_NUMBER = "number";
+ private static final String STR_EMAILS = "emails";
private static final String STR_PIN2 = "pin2";
private static final UriMatcher URL_MATCHER =
@@ -172,7 +174,8 @@
String tag = initialValues.getAsString("tag");
String number = initialValues.getAsString("number");
- boolean success = addIccRecordToEf(efType, tag, number, pin2);
+ // TODO(): Read email instead of sending null.
+ boolean success = addIccRecordToEf(efType, tag, number, null, pin2);
if (!success) {
return null;
@@ -238,6 +241,7 @@
// parse where clause
String tag = null;
String number = null;
+ String[] emails = null;
String pin2 = null;
String[] tokens = where.split("AND");
@@ -261,6 +265,9 @@
tag = normalizeValue(val);
} else if (STR_NUMBER.equals(key)) {
number = normalizeValue(val);
+ } else if (STR_EMAILS.equals(key)) {
+ //TODO(): Email is null.
+ emails = null;
} else if (STR_PIN2.equals(key)) {
pin2 = normalizeValue(val);
}
@@ -274,7 +281,7 @@
return 0;
}
- boolean success = deleteIccRecordFromEf(efType, tag, number, pin2);
+ boolean success = deleteIccRecordFromEf(efType, tag, number, emails, pin2);
if (!success) {
return 0;
}
@@ -307,9 +314,11 @@
String tag = values.getAsString("tag");
String number = values.getAsString("number");
+ String[] emails = null;
String newTag = values.getAsString("newTag");
String newNumber = values.getAsString("newNumber");
-
+ String[] newEmails = null;
+ // TODO(): Update for email.
boolean success = updateIccRecordInEf(efType, tag, number,
newTag, newNumber, pin2);
@@ -355,9 +364,9 @@
}
private boolean
- addIccRecordToEf(int efType, String name, String number, String pin2) {
+ addIccRecordToEf(int efType, String name, String number, String[] emails, String pin2) {
if (DBG) log("addIccRecordToEf: efType=" + efType + ", name=" + name +
- ", number=" + number);
+ ", number=" + number + ", emails=" + emails);
boolean success = false;
@@ -384,7 +393,7 @@
private boolean
updateIccRecordInEf(int efType, String oldName, String oldNumber,
- String newName, String newNumber,String pin2) {
+ String newName, String newNumber, String pin2) {
if (DBG) log("updateIccRecordInEf: efType=" + efType +
", oldname=" + oldName + ", oldnumber=" + oldNumber +
", newname=" + newName + ", newnumber=" + newNumber);
@@ -407,9 +416,10 @@
}
- private boolean deleteIccRecordFromEf(int efType, String name, String number, String pin2) {
+ private boolean deleteIccRecordFromEf(int efType, String name, String number, String[] emails,
+ String pin2) {
if (DBG) log("deleteIccRecordFromEf: efType=" + efType +
- ", name=" + name + ", number=" + number + ", pin2=" + pin2);
+ ", name=" + name + ", number=" + number + ", emails=" + emails + ", pin2=" + pin2);
boolean success = false;
@@ -438,13 +448,26 @@
private void loadRecord(AdnRecord record,
ArrayList<ArrayList> results) {
if (!record.isEmpty()) {
- ArrayList<String> contact = new ArrayList<String>(2);
+ ArrayList<String> contact = new ArrayList<String>();
String alphaTag = record.getAlphaTag();
String number = record.getNumber();
+ String[] emails = record.getEmails();
- if (DBG) log("loadRecord: " + alphaTag + ", " + number);
+ if (DBG) log("loadRecord: " + alphaTag + ", " + number + ",");
contact.add(alphaTag);
contact.add(number);
+ StringBuilder emailString = new StringBuilder();
+
+ if (emails != null) {
+ for (String email: emails) {
+ if (DBG) log("Adding email:" + email);
+ emailString.append(email);
+ emailString.append(",");
+ }
+ contact.add(emailString.toString());
+ } else {
+ contact.add(null);
+ }
results.add(contact);
}
}
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java b/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java
index a08cdde..206e62f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java
@@ -19,15 +19,18 @@
import android.os.Message;
import android.util.Log;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.IccCardApplication;
import com.android.internal.telephony.IccConstants;
import com.android.internal.telephony.IccFileHandler;
+import com.android.internal.telephony.Phone;
/**
* {@hide}
*/
public final class SIMFileHandler extends IccFileHandler implements IccConstants {
static final String LOG_TAG = "GSM";
-
+ private Phone mPhone;
//***** Instance Variables
@@ -35,6 +38,7 @@
SIMFileHandler(GSMPhone phone) {
super(phone);
+ mPhone = phone;
}
public void dispose() {
@@ -53,7 +57,6 @@
}
protected String getEFPath(int efid) {
- // TODO(): Make changes when USIM is supported
// TODO(): DF_GSM can be 7F20 or 7F21 to handle backward compatibility.
// Implement this after discussion with OEMs.
switch(efid) {
@@ -79,8 +82,23 @@
case EF_SPN_SHORT_CPHS:
case EF_INFO_CPHS:
return MF_SIM + DF_GSM;
+
+ case EF_PBR:
+ // we only support global phonebook.
+ return MF_SIM + DF_TELECOM + DF_PHONEBOOK;
}
- return getCommonIccEFPath(efid);
+ String path = getCommonIccEFPath(efid);
+ if (path == null) {
+ // The EFids in USIM phone book entries are decided by the card manufacturer.
+ // So if we don't match any of the cases above and if its a USIM return
+ // the phone book path.
+ IccCard card = phone.getIccCard();
+ if (card != null && card.isApplicationOnIcc(IccCardApplication.AppType.APPTYPE_USIM)) {
+ return MF_SIM + DF_TELECOM + DF_PHONEBOOK;
+ }
+ Log.e(LOG_TAG, "Error: EF Path being returned in null");
+ }
+ return path;
}
protected void logd(String msg) {
diff --git a/telephony/java/com/android/internal/telephony/gsm/SimTlv.java b/telephony/java/com/android/internal/telephony/gsm/SimTlv.java
index 30543c7..497cf5f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SimTlv.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SimTlv.java
@@ -47,7 +47,6 @@
public boolean nextObject() {
if (!hasValidTlvObject) return false;
-
curOffset = curDataOffset + curDataLength;
hasValidTlvObject = parseCurrentTlvObject();
return hasValidTlvObject;
@@ -88,11 +87,12 @@
private boolean parseCurrentTlvObject() {
// 0x00 and 0xff are invalid tag values
- if (record[curOffset] == 0 || (record[curOffset] & 0xff) == 0xff) {
- return false;
- }
try {
+ if (record[curOffset] == 0 || (record[curOffset] & 0xff) == 0xff) {
+ return false;
+ }
+
if ((record[curOffset + 1] & 0xff) < 0x80) {
// one byte length 0 - 0x7f
curDataLength = record[curOffset + 1] & 0xff;
diff --git a/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java b/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
new file mode 100644
index 0000000..d27f240
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/gsm/UsimPhoneBookManager.java
@@ -0,0 +1,424 @@
+/*
+ * 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.internal.telephony.gsm;
+
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+import com.android.internal.telephony.AdnRecord;
+import com.android.internal.telephony.AdnRecordCache;
+import com.android.internal.telephony.IccConstants;
+import com.android.internal.telephony.IccUtils;
+import com.android.internal.telephony.PhoneBase;
+
+import org.apache.harmony.luni.lang.reflect.ListOfTypes;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * This class implements reading and parsing USIM records.
+ * Refer to Spec 3GPP TS 31.102 for more details.
+ *
+ * {@hide}
+ */
+public class UsimPhoneBookManager extends Handler implements IccConstants {
+ private static final String LOG_TAG = "GSM";
+ private static final boolean DBG = true;
+ private PbrFile mPbrFile;
+ private Boolean mIsPbrPresent;
+ private PhoneBase mPhone;
+ private AdnRecordCache mAdnCache;
+ private Object mLock = new Object();
+ private ArrayList<AdnRecord> mPhoneBookRecords;
+ private boolean mEmailPresentInIap = false;
+ private int mEmailTagNumberInIap = 0;
+ private ArrayList<byte[]> mIapFileRecord;
+ private ArrayList<byte[]> mEmailFileRecord;
+ private Map<Integer, ArrayList<String>> mEmailsForAdnRec;
+
+ private static final int EVENT_PBR_LOAD_DONE = 1;
+ private static final int EVENT_USIM_ADN_LOAD_DONE = 2;
+ private static final int EVENT_IAP_LOAD_DONE = 3;
+ private static final int EVENT_EMAIL_LOAD_DONE = 4;
+
+ private static final int USIM_TYPE1_TAG = 0xA8;
+ private static final int USIM_TYPE2_TAG = 0xA9;
+ private static final int USIM_TYPE3_TAG = 0xAA;
+ private static final int USIM_EFADN_TAG = 0xC0;
+ private static final int USIM_EFIAP_TAG = 0xC1;
+ private static final int USIM_EFEXT1_TAG = 0xC2;
+ private static final int USIM_EFSNE_TAG = 0xC3;
+ private static final int USIM_EFANR_TAG = 0xC4;
+ private static final int USIM_EFPBC_TAG = 0xC5;
+ private static final int USIM_EFGRP_TAG = 0xC6;
+ private static final int USIM_EFAAS_TAG = 0xC7;
+ private static final int USIM_EFGSD_TAG = 0xC8;
+ private static final int USIM_EFUID_TAG = 0xC9;
+ private static final int USIM_EFEMAIL_TAG = 0xCA;
+ private static final int USIM_EFCCP1_TAG = 0xCB;
+
+ public UsimPhoneBookManager(PhoneBase phone, AdnRecordCache cache) {
+ mPhone = phone;
+ mPhoneBookRecords = new ArrayList<AdnRecord>();
+ mPbrFile = null;
+ // We assume its present, after the first read this is updated.
+ // So we don't have to read from UICC if its not present on subsequent reads.
+ mIsPbrPresent = true;
+ mAdnCache = cache;
+ }
+
+ public void reset() {
+ mPhoneBookRecords.clear();
+ mIapFileRecord = null;
+ mEmailFileRecord = null;
+ mPbrFile = null;
+ mIsPbrPresent = true;
+ }
+
+ public ArrayList<AdnRecord> loadEfFilesFromUsim() {
+ synchronized (mLock) {
+ if (!mPhoneBookRecords.isEmpty()) return mPhoneBookRecords;
+ if (!mIsPbrPresent) return null;
+
+ // Check if the PBR file is present in the cache, if not read it
+ // from the USIM.
+ if (mPbrFile == null) {
+ readPbrFileAndWait();
+ }
+
+ if (mPbrFile == null) return null;
+
+ int numRecs = mPbrFile.mFileIds.size();
+ for (int i = 0; i < numRecs; i++) {
+ readAdnFileAndWait(i);
+ readEmailFileAndWait(i);
+ }
+ // All EF files are loaded, post the response.
+ }
+ return mPhoneBookRecords;
+ }
+
+ private void readPbrFileAndWait() {
+ mPhone.getIccFileHandler().loadEFLinearFixedAll(EF_PBR, obtainMessage(EVENT_PBR_LOAD_DONE));
+ try {
+ mLock.wait();
+ } catch (InterruptedException e) {
+ Log.e(LOG_TAG, "Interrupted Exception in readAdnFileAndWait");
+ }
+ }
+
+ private void readEmailFileAndWait(int recNum) {
+ Map <Integer,Integer> fileIds;
+ fileIds = mPbrFile.mFileIds.get(recNum);
+ if (fileIds == null) return;
+
+ if (fileIds.containsKey(USIM_EFEMAIL_TAG)) {
+ int efid = fileIds.get(USIM_EFEMAIL_TAG);
+ // Check if the EFEmail is a Type 1 file or a type 2 file.
+ // If mEmailPresentInIap is true, its a type 2 file.
+ // So we read the IAP file and then read the email records.
+ // instead of reading directly.
+ if (mEmailPresentInIap) {
+ readIapFileAndWait(fileIds.get(USIM_EFIAP_TAG));
+ if (mIapFileRecord == null) {
+ Log.e(LOG_TAG, "Error: IAP file is empty");
+ return;
+ }
+ }
+ // Read the EFEmail file.
+ mPhone.getIccFileHandler().loadEFLinearFixedAll(fileIds.get(USIM_EFEMAIL_TAG),
+ obtainMessage(EVENT_EMAIL_LOAD_DONE));
+ try {
+ mLock.wait();
+ } catch (InterruptedException e) {
+ Log.e(LOG_TAG, "Interrupted Exception in readEmailFileAndWait");
+ }
+
+ if (mEmailFileRecord == null) {
+ Log.e(LOG_TAG, "Error: Email file is empty");
+ return;
+ }
+ updatePhoneAdnRecord();
+ }
+
+ }
+
+ private void readIapFileAndWait(int efid) {
+ mPhone.getIccFileHandler().loadEFLinearFixedAll(efid, obtainMessage(EVENT_IAP_LOAD_DONE));
+ try {
+ mLock.wait();
+ } catch (InterruptedException e) {
+ Log.e(LOG_TAG, "Interrupted Exception in readIapFileAndWait");
+ }
+ }
+
+ private void updatePhoneAdnRecord() {
+ if (mEmailFileRecord == null) return;
+ int numAdnRecs = mPhoneBookRecords.size();
+ if (mIapFileRecord != null) {
+ // The number of records in the IAP file is same as the number of records in ADN file.
+ // The order of the pointers in an EFIAP shall be the same as the order of file IDs
+ // that appear in the TLV object indicated by Tag 'A9' in the reference file record.
+ // i.e value of mEmailTagNumberInIap
+
+ for (int i = 0; i < numAdnRecs; i++) {
+ byte[] record = null;
+ try {
+ record = mIapFileRecord.get(i);
+ } catch (IndexOutOfBoundsException e) {
+ Log.e(LOG_TAG, "Error: Improper ICC card: No IAP record for ADN, continuing");
+ break;
+ }
+ int recNum = record[mEmailTagNumberInIap];
+
+ if (recNum != -1) {
+ String[] emails = new String[1];
+ // SIM record numbers are 1 based
+ emails[0] = readEmailRecord(recNum - 1);
+ AdnRecord rec = mPhoneBookRecords.get(i);
+ if (rec != null) {
+ rec.setEmails(emails);
+ } else {
+ // might be a record with only email
+ rec = new AdnRecord("", "", emails);
+ }
+ mPhoneBookRecords.set(i, rec);
+ }
+ }
+ }
+
+ // ICC cards can be made such that they have an IAP file but all
+ // records are empty. So we read both type 1 and type 2 file
+ // email records, just to be sure.
+
+ int len = mPhoneBookRecords.size();
+ // Type 1 file, the number of records is the same as the number of
+ // records in the ADN file.
+ if (mEmailsForAdnRec == null) {
+ parseType1EmailFile(len);
+ }
+ for (int i = 0; i < numAdnRecs; i++) {
+ ArrayList<String> emailList = null;
+ try {
+ emailList = mEmailsForAdnRec.get(i);
+ } catch (IndexOutOfBoundsException e) {
+ break;
+ }
+ if (emailList == null) continue;
+
+ AdnRecord rec = mPhoneBookRecords.get(i);
+
+ String[] emails = new String[emailList.size()];
+ System.arraycopy(emailList.toArray(), 0, emails, 0, emailList.size());
+ rec.setEmails(emails);
+ mPhoneBookRecords.set(i, rec);
+ }
+ }
+
+ void parseType1EmailFile(int numRecs) {
+ mEmailsForAdnRec = new HashMap<Integer, ArrayList<String>>();
+ byte[] emailRec = null;
+ for (int i = 0; i < numRecs; i++) {
+ try {
+ emailRec = mEmailFileRecord.get(i);
+ } catch (IndexOutOfBoundsException e) {
+ Log.e(LOG_TAG, "Error: Improper ICC card: No email record for ADN, continuing");
+ break;
+ }
+ int adnRecNum = emailRec[emailRec.length - 1];
+
+ if (adnRecNum == -1) {
+ continue;
+ }
+
+ String email = readEmailRecord(i);
+
+ if (email == null || email.equals("")) {
+ continue;
+ }
+
+ // SIM record numbers are 1 based.
+ ArrayList<String> val = mEmailsForAdnRec.get(adnRecNum - 1);
+ if (val == null) {
+ val = new ArrayList<String>();
+ }
+ val.add(email);
+ // SIM record numbers are 1 based.
+ mEmailsForAdnRec.put(adnRecNum - 1, val);
+ }
+ }
+
+ private String readEmailRecord(int recNum) {
+ byte[] emailRec = null;
+ try {
+ emailRec = mEmailFileRecord.get(recNum);
+ } catch (IndexOutOfBoundsException e) {
+ return null;
+ }
+
+ // The length of the record is X+2 byte, where X bytes is the email address
+ String email = IccUtils.adnStringFieldToString(emailRec, 0, emailRec.length - 2);
+ return email;
+ }
+
+ private void readAdnFileAndWait(int recNum) {
+ Map <Integer,Integer> fileIds;
+ fileIds = mPbrFile.mFileIds.get(recNum);
+ if (fileIds == null) return;
+
+ mAdnCache.requestLoadAllAdnLike(fileIds.get(USIM_EFADN_TAG),
+ fileIds.get(USIM_EFEXT1_TAG), obtainMessage(EVENT_USIM_ADN_LOAD_DONE));
+ try {
+ mLock.wait();
+ } catch (InterruptedException e) {
+ Log.e(LOG_TAG, "Interrupted Exception in readAdnFileAndWait");
+ }
+ }
+
+ private void createPbrFile(ArrayList<byte[]> records) {
+ if (records == null) {
+ mPbrFile = null;
+ mIsPbrPresent = false;
+ return;
+ }
+ mPbrFile = new PbrFile(records);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ AsyncResult ar;
+
+ switch(msg.what) {
+ case EVENT_PBR_LOAD_DONE:
+ ar = (AsyncResult) msg.obj;
+ if (ar.exception == null) {
+ createPbrFile((ArrayList<byte[]>)ar.result);
+ }
+ synchronized (mLock) {
+ mLock.notify();
+ }
+ break;
+ case EVENT_USIM_ADN_LOAD_DONE:
+ log("Loading USIM ADN records done");
+ ar = (AsyncResult) msg.obj;
+ if (ar.exception == null) {
+ mPhoneBookRecords.addAll((ArrayList<AdnRecord>)ar.result);
+ }
+ synchronized (mLock) {
+ mLock.notify();
+ }
+ break;
+ case EVENT_IAP_LOAD_DONE:
+ log("Loading USIM IAP records done");
+ ar = (AsyncResult) msg.obj;
+ if (ar.exception == null) {
+ mIapFileRecord = ((ArrayList<byte[]>)ar.result);
+ }
+ synchronized (mLock) {
+ mLock.notify();
+ }
+ break;
+ case EVENT_EMAIL_LOAD_DONE:
+ log("Loading USIM Email records done");
+ ar = (AsyncResult) msg.obj;
+ if (ar.exception == null) {
+ mEmailFileRecord = ((ArrayList<byte[]>)ar.result);
+ }
+
+ synchronized (mLock) {
+ mLock.notify();
+ }
+ break;
+ }
+ }
+
+ private class PbrFile {
+ // RecNum <EF Tag, efid>
+ HashMap<Integer,Map<Integer,Integer>> mFileIds;
+
+ PbrFile(ArrayList<byte[]> records) {
+ mFileIds = new HashMap<Integer, Map<Integer, Integer>>();
+ SimTlv recTlv;
+ int recNum = 0;
+ for (byte[] record: records) {
+ recTlv = new SimTlv(record, 0, record.length);
+ parseTag(recTlv, recNum);
+ recNum ++;
+ }
+ }
+
+ void parseTag(SimTlv tlv, int recNum) {
+ SimTlv tlvEf;
+ int tag;
+ byte[] data;
+ Map<Integer, Integer> val = new HashMap<Integer, Integer>();
+ do {
+ tag = tlv.getTag();
+ switch(tag) {
+ case USIM_TYPE1_TAG: // A8
+ case USIM_TYPE3_TAG: // AA
+ case USIM_TYPE2_TAG: // A9
+ data = tlv.getData();
+ tlvEf = new SimTlv(data, 0, data.length);
+ parseEf(tlvEf, val, tag);
+ break;
+ }
+ } while (tlv.nextObject());
+ mFileIds.put(recNum, val);
+ }
+
+ void parseEf(SimTlv tlv, Map<Integer, Integer> val, int parentTag) {
+ int tag;
+ byte[] data;
+ int tagNumberWithinParentTag = 0;
+ do {
+ tag = tlv.getTag();
+ if (parentTag == USIM_TYPE2_TAG && tag == USIM_EFEMAIL_TAG) {
+ mEmailPresentInIap = true;
+ mEmailTagNumberInIap = tagNumberWithinParentTag;
+ }
+ switch(tag) {
+ case USIM_EFEMAIL_TAG:
+ case USIM_EFADN_TAG:
+ case USIM_EFEXT1_TAG:
+ case USIM_EFANR_TAG:
+ case USIM_EFPBC_TAG:
+ case USIM_EFGRP_TAG:
+ case USIM_EFAAS_TAG:
+ case USIM_EFGSD_TAG:
+ case USIM_EFUID_TAG:
+ case USIM_EFCCP1_TAG:
+ case USIM_EFIAP_TAG:
+ case USIM_EFSNE_TAG:
+ data = tlv.getData();
+ int efid = data[0] << 8 | data[1];
+ val.put(tag, efid);
+ break;
+ }
+ tagNumberWithinParentTag ++;
+ } while(tlv.nextObject());
+ }
+ }
+
+ private void log(String msg) {
+ if(DBG) Log.d(LOG_TAG, msg);
+ }
+}