Merge change 25362 into eclair
* changes:
Handle BACK key with focus in search ACTV correctly
diff --git a/api/current.xml b/api/current.xml
index 6174bff..448da7c 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -27401,6 +27401,87 @@
>
</method>
</class>
+<class name="ParcelUuid"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<constructor name="ParcelUuid"
+ type="android.bluetooth.ParcelUuid"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uuid" type="java.util.UUID">
+</parameter>
+</constructor>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="fromString"
+ return="android.bluetooth.ParcelUuid"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uuid" type="java.lang.String">
+</parameter>
+</method>
+<method name="getUuid"
+ return="java.util.UUID"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
</package>
<package name="android.content"
>
@@ -35178,6 +35259,17 @@
visibility="public"
>
</field>
+<field name="ACTION_DOCK_EVENT"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.intent.action.DOCK_EVENT""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="ACTION_EDIT"
type="java.lang.String"
transient="false"
@@ -35893,6 +35985,17 @@
visibility="public"
>
</field>
+<field name="CATEGORY_CAR_DOCK"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.intent.category.CAR_DOCK""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="CATEGORY_DEFAULT"
type="java.lang.String"
transient="false"
@@ -35904,6 +36007,17 @@
visibility="public"
>
</field>
+<field name="CATEGORY_DESK_DOCK"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.intent.category.DESK_DOCK""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="CATEGORY_DEVELOPMENT_PREFERENCE"
type="java.lang.String"
transient="false"
@@ -36123,6 +36237,50 @@
visibility="public"
>
</field>
+<field name="EXTRA_DOCK_STATE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.intent.extra.DOCK_STATE""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_DOCK_STATE_CAR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_DOCK_STATE_DESK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_DOCK_STATE_UNDOCKED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="EXTRA_DONT_KILL_APP"
type="java.lang.String"
transient="false"
@@ -43786,6 +43944,39 @@
visibility="public"
>
</field>
+<field name="NAVIGATIONHIDDEN_NO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NAVIGATIONHIDDEN_UNDEFINED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="NAVIGATIONHIDDEN_YES"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="NAVIGATION_DPAD"
type="int"
transient="false"
@@ -44108,6 +44299,16 @@
visibility="public"
>
</field>
+<field name="navigationHidden"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="orientation"
type="int"
transient="false"
@@ -66956,6 +67157,17 @@
<parameter name="cb" type="android.hardware.Camera.AutoFocusCallback">
</parameter>
</method>
+<method name="cancelAutoFocus"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getParameters"
return="android.hardware.Camera.Parameters"
abstract="false"
@@ -77314,6 +77526,387 @@
</parameter>
</method>
</interface>
+<class name="ExifInterface"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="ExifInterface"
+ type="android.media.ExifInterface"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="filename" type="java.lang.String">
+</parameter>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</constructor>
+<method name="getAttribute"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="java.lang.String">
+</parameter>
+</method>
+<method name="getDateTime"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getLatLong"
+ return="float[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getOrientationString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getThumbnail"
+ return="byte[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getWhiteBalanceString"
+ return="java.lang.String"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="hasThumbnail"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="saveAttributes"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
+<method name="setAttribute"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="java.lang.String">
+</parameter>
+<parameter name="value" type="java.lang.String">
+</parameter>
+</method>
+<field name="ORIENTATION_FLIP_HORIZONTAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_FLIP_VERTICAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_NORMAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_ROTATE_180"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_ROTATE_270"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_ROTATE_90"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_TRANSPOSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_TRANSVERSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_UNDEFINED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_DATETIME"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""DateTime""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_FLASH"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""Flash""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_GPS_LATITUDE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""GPSLatitude""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_GPS_LATITUDE_REF"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""GPSLatitudeRef""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_GPS_LONGITUDE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""GPSLongitude""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_GPS_LONGITUDE_REF"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""GPSLongitudeRef""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_IMAGE_LENGTH"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""ImageLength""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_IMAGE_WIDTH"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""ImageWidth""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_MAKE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""Make""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_MODEL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""Model""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_ORIENTATION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""Orientation""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TAG_WHITE_BALANCE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""WhiteBalance""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="WHITEBALANCE_AUTO"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="WHITEBALANCE_MANUAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
<class name="FaceDetector"
extends="java.lang.Object"
abstract="false"
@@ -128851,6 +129444,17 @@
visibility="public"
>
</field>
+<field name="TYPE_TEXT_FLAG_NO_SUGGESTIONS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="524288"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="TYPE_TEXT_VARIATION_EMAIL_ADDRESS"
type="int"
transient="false"
@@ -159360,6 +159964,17 @@
visibility="public"
>
</field>
+<field name="FLAG_TURN_SCREEN_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2097152"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="FLAG_WATCH_OUTSIDE_TOUCH"
type="int"
transient="false"
diff --git a/cmds/keystore/netkeystore.c b/cmds/keystore/netkeystore.c
index 83c7871..87fdc80 100644
--- a/cmds/keystore/netkeystore.c
+++ b/cmds/keystore/netkeystore.c
@@ -116,10 +116,13 @@
static int is_alnum_string(char *s)
{
+ char *s0 = s;
while (*s != 0) {
- if (!isalnum(*s++)) return 0;
+ if (!isalnum(*s++)) {
+ LOGE("The string '%s' is not an alphanumeric string\n", s0);
+ return 0;
+ }
}
- LOGE("The string %s is not an alphanumeric string\n", s);
return 1;
}
@@ -159,7 +162,9 @@
// no argument
static void do_get_state(LPC_MARSHAL *cmd, LPC_MARSHAL *reply)
{
- reply->retcode = get_state();
+ int s = get_state();
+ if (DBG) LOGD("keystore state = %d\n", s);
+ reply->retcode = s;
}
// args of listkeys():
@@ -413,12 +418,10 @@
// read the command, execute and send the result back.
if(read_marshal(s, &cmd)) goto err;
- if (DBG) LOGD("new connection\n");
execute(&cmd, &reply);
write_marshal(s, &reply);
err:
memset(&reply, 0, sizeof(LPC_MARSHAL));
- if (DBG) LOGD("closing connection\n");
close(s);
}
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index c13893a..4217957 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -46,7 +46,6 @@
import android.app.PendingIntent;
import android.app.NotificationManager;
import android.app.Notification;
-import android.app.Activity;
import android.Manifest;
import java.io.FileDescriptor;
@@ -471,6 +470,7 @@
}
private boolean saveAuthTokenToDatabase(Account account, String type, String authToken) {
+ cancelNotification(getSigninRequiredNotificationId(account));
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
db.beginTransaction();
try {
@@ -523,7 +523,7 @@
checkAuthenticateAccountsPermission(account);
long identityToken = clearCallingIdentity();
try {
- cacheAuthToken(account, authTokenType, authToken);
+ saveAuthTokenToDatabase(account, authTokenType, authToken);
} finally {
restoreCallingIdentity(identityToken);
}
@@ -686,7 +686,8 @@
"the type and name should not be empty");
return;
}
- cacheAuthToken(new Account(name, type), authTokenType, authToken);
+ saveAuthTokenToDatabase(new Account(name, type),
+ authTokenType, authToken);
}
Intent intent = result.getParcelable(Constants.INTENT_KEY);
@@ -714,11 +715,14 @@
Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
0 /* when */);
- final CharSequence subtitleFormatString =
- mContext.getText(R.string.permission_request_notification_subtitle);
+ final String titleAndSubtitle =
+ mContext.getString(R.string.permission_request_notification_with_subtitle,
+ account.name);
+ final int index = titleAndSubtitle.indexOf('\n');
+ final String title = titleAndSubtitle.substring(0, index);
+ final String subtitle = titleAndSubtitle.substring(index + 1);
n.setLatestEventInfo(mContext,
- mContext.getText(R.string.permission_request_notification_title),
- String.format(subtitleFormatString.toString(), account.name),
+ title, subtitle,
PendingIntent.getActivity(mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT));
((NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE))
.notify(getCredentialPermissionNotificationId(account, authTokenType, uid), n);
@@ -1001,10 +1005,6 @@
}
}
- private boolean cacheAuthToken(Account account, String authTokenType, String authToken) {
- return saveAuthTokenToDatabase(account, authTokenType, authToken);
- }
-
private long getAccountId(SQLiteDatabase db, Account account) {
Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_ID},
"name=? AND type=?", new String[]{account.name, account.type}, null, null, null);
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 8f7e8ca..4f9531e 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -20,14 +20,15 @@
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.ContentResolver.OpenResourceIdResult;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.database.Cursor;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.DrawableContainer;
import android.graphics.drawable.StateListDrawable;
import android.net.Uri;
import android.os.Bundle;
@@ -38,14 +39,15 @@
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.Filter;
import android.widget.ImageView;
import android.widget.ResourceCursorAdapter;
import android.widget.TextView;
-import android.widget.Filter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import java.util.List;
import java.util.WeakHashMap;
/**
@@ -580,14 +582,26 @@
// Not cached, try using it as a plain resource ID in the provider's context.
int resourceId = Integer.parseInt(drawableId);
drawable = mProviderContext.getResources().getDrawable(resourceId);
- if (DBG) Log.d(LOG_TAG, "Found icon by resource ID: " + drawableId);
} catch (NumberFormatException nfe) {
- // The id was not an integer resource id.
- // Let the ContentResolver handle content, android.resource and file URIs.
+ // The id was not an integer resource id, use it as a URI
try {
Uri uri = Uri.parse(drawableId);
- InputStream stream = mProviderContext.getContentResolver().openInputStream(uri);
- if (stream != null) {
+ String scheme = uri.getScheme();
+ if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
+ // Load drawables through Resources, to get the source density information
+ OpenResourceIdResult r =
+ mProviderContext.getContentResolver().getResourceId(uri);
+ try {
+ drawable = r.r.getDrawable(r.id);
+ } catch (Resources.NotFoundException ex) {
+ throw new FileNotFoundException("Resource does not exist: " + uri);
+ }
+ } else {
+ // Let the ContentResolver handle content and file URIs.
+ InputStream stream = mProviderContext.getContentResolver().openInputStream(uri);
+ if (stream == null) {
+ throw new FileNotFoundException("Failed to open " + uri);
+ }
try {
drawable = Drawable.createFromStream(stream, null);
} finally {
@@ -598,22 +612,25 @@
}
}
}
- if (DBG) Log.d(LOG_TAG, "Opened icon input stream: " + drawableId);
} catch (FileNotFoundException fnfe) {
- if (DBG) Log.d(LOG_TAG, "Icon stream not found: " + drawableId);
+ Log.w(LOG_TAG, "Icon not found: " + drawableId + ", " + fnfe.getMessage());
// drawable = null;
}
-
- // If we got a drawable for this resource id, then stick it in the
- // map so we don't do this lookup again.
- if (drawable != null) {
- mOutsideDrawablesCache.put(drawableId, drawable.getConstantState());
- }
} catch (Resources.NotFoundException nfe) {
- if (DBG) Log.d(LOG_TAG, "Icon resource not found: " + drawableId);
+ Log.w(LOG_TAG, "Icon resource not found: " + drawableId);
// drawable = null;
}
+ if (drawable == null) {
+ if (DBG) Log.d(LOG_TAG, "Didn't find icon: " + drawableId);
+ } else {
+ if (DBG) {
+ Log.d(LOG_TAG, "Found icon: " + drawableId);
+ }
+ // Cache it so we don't do this lookup again
+ mOutsideDrawablesCache.put(drawableId, drawable.getConstantState());
+ }
+
return drawable;
}
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index b1861ac..0b3f3c7 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -503,7 +503,7 @@
}
/** @hide */
- public String[] getUuids() {
+ public ParcelUuid[] getUuids() {
try {
return sService.getRemoteUuids(mAddress);
} catch (RemoteException e) {Log.e(TAG, "", e);}
@@ -511,7 +511,7 @@
}
/** @hide */
- public int getServiceChannel(String uuid) {
+ public int getServiceChannel(ParcelUuid uuid) {
try {
return sService.getRemoteServiceChannel(mAddress, uuid);
} catch (RemoteException e) {Log.e(TAG, "", e);}
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index c15bc20..409c744 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -16,10 +16,11 @@
package android.bluetooth;
-import java.util.UUID;
+import java.util.Arrays;
+import java.util.HashSet;
/**
-* Static helper methods and constants to decode the UUID of remote devices.
+* Static helper methods and constants to decode the ParcelUuid of remote devices.
* @hide
*/
public final class BluetoothUuid {
@@ -30,40 +31,99 @@
* The following 128 bit values are calculated as:
* uuid * 2^96 + BASE_UUID
*/
- public static final UUID AudioSink = UUID.fromString("0000110B-0000-1000-8000-00805F9B34FB");
- public static final UUID AudioSource = UUID.fromString("0000110A-0000-1000-8000-00805F9B34FB");
- public static final UUID AdvAudioDist = UUID.fromString("0000110D-0000-1000-8000-00805F9B34FB");
- public static final UUID HSP = UUID.fromString("00001108-0000-1000-8000-00805F9B34FB");
- public static final UUID Handsfree = UUID.fromString("0000111E-0000-1000-8000-00805F9B34FB");
- public static final UUID AvrcpController =
- UUID.fromString("0000110E-0000-1000-8000-00805F9B34FB");
- public static final UUID AvrcpTarget = UUID.fromString("0000110C-0000-1000-8000-00805F9B34FB");
+ public static final ParcelUuid AudioSink =
+ ParcelUuid.fromString("0000110B-0000-1000-8000-00805F9B34FB");
+ public static final ParcelUuid AudioSource =
+ ParcelUuid.fromString("0000110A-0000-1000-8000-00805F9B34FB");
+ public static final ParcelUuid AdvAudioDist =
+ ParcelUuid.fromString("0000110D-0000-1000-8000-00805F9B34FB");
+ public static final ParcelUuid HSP =
+ ParcelUuid.fromString("00001108-0000-1000-8000-00805F9B34FB");
+ public static final ParcelUuid Handsfree =
+ ParcelUuid.fromString("0000111E-0000-1000-8000-00805F9B34FB");
+ public static final ParcelUuid AvrcpController =
+ ParcelUuid.fromString("0000110E-0000-1000-8000-00805F9B34FB");
+ public static final ParcelUuid AvrcpTarget =
+ ParcelUuid.fromString("0000110C-0000-1000-8000-00805F9B34FB");
+ public static final ParcelUuid ObexObjectPush =
+ ParcelUuid.fromString("00001105-0000-1000-8000-00805f9b34fb");
- public static boolean isAudioSource(UUID uuid) {
+ public static boolean isAudioSource(ParcelUuid uuid) {
return uuid.equals(AudioSource);
}
- public static boolean isAudioSink(UUID uuid) {
+ public static boolean isAudioSink(ParcelUuid uuid) {
return uuid.equals(AudioSink);
}
- public static boolean isAdvAudioDist(UUID uuid) {
+ public static boolean isAdvAudioDist(ParcelUuid uuid) {
return uuid.equals(AdvAudioDist);
}
- public static boolean isHandsfree(UUID uuid) {
+ public static boolean isHandsfree(ParcelUuid uuid) {
return uuid.equals(Handsfree);
}
- public static boolean isHeadset(UUID uuid) {
+ public static boolean isHeadset(ParcelUuid uuid) {
return uuid.equals(HSP);
}
- public static boolean isAvrcpController(UUID uuid) {
+ public static boolean isAvrcpController(ParcelUuid uuid) {
return uuid.equals(AvrcpController);
}
- public static boolean isAvrcpTarget(UUID uuid) {
+ public static boolean isAvrcpTarget(ParcelUuid uuid) {
return uuid.equals(AvrcpTarget);
}
+
+ /**
+ * Returns true if ParcelUuid is present in uuidArray
+ *
+ * @param uuidArray - Array of ParcelUuids
+ * @param uuid
+ */
+ public static boolean isUuidPresent(ParcelUuid[] uuidArray, ParcelUuid uuid) {
+ for (ParcelUuid element: uuidArray) {
+ if (element.equals(uuid)) return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if there any common ParcelUuids in uuidA and uuidB.
+ *
+ * @param uuidA - List of ParcelUuids
+ * @param uuidB - List of ParcelUuids
+ *
+ */
+ public static boolean containsAnyUuid(ParcelUuid[] uuidA, ParcelUuid[] uuidB) {
+ if (uuidA == null && uuidB == null) return true;
+ if (uuidA == null || uuidB == null) return false;
+
+ HashSet<ParcelUuid> uuidSet = new HashSet<ParcelUuid> (Arrays.asList(uuidA));
+ for (ParcelUuid uuid: uuidB) {
+ if (uuidSet.contains(uuid)) return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if all the ParcelUuids in ParcelUuidB are present in
+ * ParcelUuidA
+ *
+ * @param uuidA - Array of ParcelUuidsA
+ * @param uuidB - Array of ParcelUuidsB
+ *
+ */
+ public static boolean containsAllUuids(ParcelUuid[] uuidA, ParcelUuid[] uuidB) {
+ if (uuidA == null && uuidB == null) return true;
+ if (uuidA == null || uuidB == null) return false;
+
+ HashSet<ParcelUuid> uuidSet = new HashSet<ParcelUuid> (Arrays.asList(uuidA));
+ for (ParcelUuid uuid: uuidB) {
+ if (!uuidSet.contains(uuid)) return false;
+ }
+ return true;
+ }
+
}
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index a11ceac..04c8ec9 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -16,6 +16,8 @@
package android.bluetooth;
+import android.bluetooth.ParcelUuid;
+
/**
* System private API for talking with the Bluetooth service.
*
@@ -50,8 +52,8 @@
String getRemoteName(in String address);
int getRemoteClass(in String address);
- String[] getRemoteUuids(in String address);
- int getRemoteServiceChannel(in String address, String uuid);
+ ParcelUuid[] getRemoteUuids(in String address);
+ int getRemoteServiceChannel(in String address,in ParcelUuid uuid);
boolean setPin(in String address, in byte[] pin);
boolean setPasskey(in String address, int passkey);
diff --git a/core/java/android/bluetooth/ParcelUuid.aidl b/core/java/android/bluetooth/ParcelUuid.aidl
new file mode 100644
index 0000000..70bcc4b
--- /dev/null
+++ b/core/java/android/bluetooth/ParcelUuid.aidl
@@ -0,0 +1,19 @@
+/*
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.bluetooth;
+
+parcelable ParcelUuid;
diff --git a/core/java/android/bluetooth/ParcelUuid.java b/core/java/android/bluetooth/ParcelUuid.java
new file mode 100644
index 0000000..27166a0
--- /dev/null
+++ b/core/java/android/bluetooth/ParcelUuid.java
@@ -0,0 +1,135 @@
+/*
+ * 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.Parcel;
+import android.os.Parcelable;
+
+import java.util.UUID;
+
+/**
+ * This class is a Parcelable wrapper around {@link UUID} which is an
+ * immutable representation of a 128-bit universally unique
+ * identifier.
+ */
+public final class ParcelUuid implements Parcelable {
+
+ private final UUID mUuid;
+
+ /**
+ * Constructor creates a ParcelUuid instance from the
+ * given {@link UUID}.
+ *
+ * @param uuid UUID
+ */
+ public ParcelUuid(UUID uuid) {
+ mUuid = uuid;
+ }
+
+ /**
+ * Creates a new ParcelUuid from a string representation of {@link UUID}.
+ *
+ * @param uuid
+ * the UUID string to parse.
+ * @return an ParcelUuid instance.
+ * @throws NullPointerException
+ * if {@code uuid} is {@code null}.
+ * @throws IllegalArgumentException
+ * if {@code uuid} is not formatted correctly.
+ */
+ public static ParcelUuid fromString(String uuid) {
+ return new ParcelUuid(UUID.fromString(uuid));
+ }
+
+ /**
+ * Get the {@link UUID} represented by the ParcelUuid.
+ *
+ * @return UUID contained in the ParcelUuid.
+ */
+ public UUID getUuid() {
+ return mUuid;
+ }
+
+ /**
+ * Returns a string representation of the ParcelUuid
+ * For example: 0000110B-0000-1000-8000-00805F9B34FB will be the return value.
+ *
+ * @return a String instance.
+ */
+ @Override
+ public String toString() {
+ return mUuid.toString();
+ }
+
+
+ @Override
+ public int hashCode() {
+ return mUuid.hashCode();
+ }
+
+ /**
+ * Compares this ParcelUuid to another object for equality. If {@code object}
+ * is not {@code null}, is a ParcelUuid instance, and all bits are equal, then
+ * {@code true} is returned.
+ *
+ * @param object
+ * the {@code Object} to compare to.
+ * @return {@code true} if this ParcelUuid is equal to {@code object}
+ * or {@code false} if not.
+ */
+ @Override
+ public boolean equals(Object object) {
+ if (object == null) {
+ return false;
+ }
+
+ if (this == object) {
+ return true;
+ }
+
+ if (!(object instanceof ParcelUuid)) {
+ return false;
+ }
+
+ ParcelUuid that = (ParcelUuid) object;
+
+ return (this.mUuid.equals(that.mUuid));
+ }
+
+ public static final Parcelable.Creator<ParcelUuid> CREATOR =
+ new Parcelable.Creator<ParcelUuid>() {
+ public ParcelUuid createFromParcel(Parcel source) {
+ long mostSigBits = source.readLong();
+ long leastSigBits = source.readLong();
+ UUID uuid = new UUID(mostSigBits, leastSigBits);
+ return new ParcelUuid(uuid);
+ }
+
+ public ParcelUuid[] newArray(int size) {
+ return new ParcelUuid[size];
+ }
+ };
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(mUuid.getMostSignificantBits());
+ dest.writeLong(mUuid.getLeastSignificantBits());
+ }
+}
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 238792b..60b406d 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -221,26 +221,30 @@
} else if (mType == TYPE_UPDATE) {
numRows = provider.update(mUri, values, mSelection, selectionArgs);
} else if (mType == TYPE_ASSERT) {
- // Build projection map from expected values
- final ArrayList<String> projectionList = new ArrayList<String>();
- for (Map.Entry<String, Object> entry : values.valueSet()) {
- projectionList.add(entry.getKey());
- }
-
// Assert that all rows match expected values
- final String[] projection = projectionList.toArray(new String[projectionList.size()]);
+ String[] projection = null;
+ if (values != null) {
+ // Build projection map from expected values
+ final ArrayList<String> projectionList = new ArrayList<String>();
+ for (Map.Entry<String, Object> entry : values.valueSet()) {
+ projectionList.add(entry.getKey());
+ }
+ projection = projectionList.toArray(new String[projectionList.size()]);
+ }
final Cursor cursor = provider.query(mUri, projection, mSelection, selectionArgs, null);
- numRows = cursor.getCount();
try {
- while (cursor.moveToNext()) {
- for (int i = 0; i < projection.length; i++) {
- final String cursorValue = cursor.getString(i);
- final String expectedValue = values.getAsString(projection[i]);
- if (!TextUtils.equals(cursorValue, expectedValue)) {
- // Throw exception when expected values don't match
- throw new OperationApplicationException("Found value " + cursorValue
- + " when expected " + expectedValue + " for column "
- + projection[i]);
+ numRows = cursor.getCount();
+ if (projection != null) {
+ while (cursor.moveToNext()) {
+ for (int i = 0; i < projection.length; i++) {
+ final String cursorValue = cursor.getString(i);
+ final String expectedValue = values.getAsString(projection[i]);
+ if (!TextUtils.equals(cursorValue, expectedValue)) {
+ // Throw exception when expected values don't match
+ throw new OperationApplicationException("Found value " + cursorValue
+ + " when expected " + expectedValue + " for column "
+ + projection[i]);
+ }
}
}
}
@@ -395,12 +399,19 @@
/** Create a ContentProviderOperation from this {@link Builder}. */
public ContentProviderOperation build() {
- if (mType == TYPE_UPDATE || mType == TYPE_ASSERT) {
+ if (mType == TYPE_UPDATE) {
if ((mValues == null || mValues.size() == 0)
&& (mValuesBackReferences == null || mValuesBackReferences.size() == 0)) {
throw new IllegalArgumentException("Empty values");
}
}
+ if (mType == TYPE_ASSERT) {
+ if ((mValues == null || mValues.size() == 0)
+ && (mValuesBackReferences == null || mValuesBackReferences.size() == 0)
+ && (mExpectedCount == null)) {
+ throw new IllegalArgumentException("Empty values");
+ }
+ }
return new ContentProviderOperation(this);
}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 88a4d02f..307899a 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -527,12 +527,22 @@
}
}
- class OpenResourceIdResult {
- Resources r;
- int id;
+ /**
+ * A resource identified by the {@link Resources} that contains it, and a resource id.
+ *
+ * @hide
+ */
+ public class OpenResourceIdResult {
+ public Resources r;
+ public int id;
}
-
- OpenResourceIdResult getResourceId(Uri uri) throws FileNotFoundException {
+
+ /**
+ * Resolves an android.resource URI to a {@link Resources} and a resource id.
+ *
+ * @hide
+ */
+ public OpenResourceIdResult getResourceId(Uri uri) throws FileNotFoundException {
String authority = uri.getAuthority();
Resources r;
if (TextUtils.isEmpty(authority)) {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index c053ace..fc977c8 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -529,6 +529,8 @@
* <li> {@link #CATEGORY_HOME}
* <li> {@link #CATEGORY_PREFERENCE}
* <li> {@link #CATEGORY_TEST}
+ * <li> {@link #CATEGORY_CAR_DOCK}
+ * <li> {@link #CATEGORY_DESK_DOCK}
* </ul>
*
* <h3>Standard Extra Data</h3>
@@ -1861,12 +1863,29 @@
*/
public static final String CATEGORY_FRAMEWORK_INSTRUMENTATION_TEST =
"android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST";
+ /**
+ * An activity to run when device is inserted into a car dock.
+ * Used with {@link #ACTION_MAIN} to launch an activity.
+ * To monitor dock state, use {@link #ACTION_DOCK_EVENT} instead.
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_CAR_DOCK = "android.intent.category.CAR_DOCK";
+ /**
+ * An activity to run when device is inserted into a car dock.
+ * Used with {@link #ACTION_MAIN} to launch an activity.
+ * To monitor dock state, use {@link #ACTION_DOCK_EVENT} instead.
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_DESK_DOCK = "android.intent.category.DESK_DOCK";
/**
* Broadcast Action: The phone was docked or undocked. Includes the extra
* field {@link #EXTRA_DOCK_STATE}, containing the current dock state.
- * @hide
+ * This is intended for monitoring the current dock state.
+ * To launch an activity from a dock state change, use {@link #CATEGORY_CAR_DOCK}
+ * or {@link #CATEGORY_DESK_DOCK} instead.
*/
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_DOCK_EVENT = "android.intent.action.DOCK_EVENT";
// ---------------------------------------------------------------------
@@ -2005,28 +2024,24 @@
* {@link android.content.Intent#EXTRA_DOCK_STATE_UNDOCKED},
* {@link android.content.Intent#EXTRA_DOCK_STATE_DESK}, or
* {@link android.content.Intent#EXTRA_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;
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 27783ef..1ad13c5 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -217,7 +217,9 @@
public static final int CONFIG_KEYBOARD = 0x0010;
/**
* Bit in {@link #configChanges} that indicates that the activity
- * can itself handle changes to the keyboard being hidden/exposed.
+ * can itself handle changes to the keyboard or navigation being hidden/exposed.
+ * Note that inspite of the name, this applies to the changes to any
+ * hidden states: keyboard or navigation.
* Set from the {@link android.R.attr#configChanges} attribute.
*/
public static final int CONFIG_KEYBOARD_HIDDEN = 0x0020;
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index cbf8410..1fe34b5 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -138,6 +138,18 @@
*/
public int navigation;
+ public static final int NAVIGATIONHIDDEN_UNDEFINED = 0;
+ public static final int NAVIGATIONHIDDEN_NO = 1;
+ public static final int NAVIGATIONHIDDEN_YES = 2;
+
+ /**
+ * A flag indicating whether any 5-way or DPAD navigation available.
+ * This will be set on a device with a mechanism to hide the navigation
+ * controls from the user, when that mechanism is closed. One of:
+ * {@link #NAVIGATIONHIDDEN_NO}, {@link #NAVIGATIONHIDDEN_YES}.
+ */
+ public int navigationHidden;
+
public static final int ORIENTATION_UNDEFINED = 0;
public static final int ORIENTATION_PORTRAIT = 1;
public static final int ORIENTATION_LANDSCAPE = 2;
@@ -174,6 +186,7 @@
keyboardHidden = o.keyboardHidden;
hardKeyboardHidden = o.hardKeyboardHidden;
navigation = o.navigation;
+ navigationHidden = o.navigationHidden;
orientation = o.orientation;
screenLayout = o.screenLayout;
}
@@ -198,6 +211,8 @@
sb.append(hardKeyboardHidden);
sb.append(" nav=");
sb.append(navigation);
+ sb.append("/");
+ sb.append(navigationHidden);
sb.append(" orien=");
sb.append(orientation);
sb.append(" layout=");
@@ -219,6 +234,7 @@
keyboardHidden = KEYBOARDHIDDEN_UNDEFINED;
hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED;
navigation = NAVIGATION_UNDEFINED;
+ navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
orientation = ORIENTATION_UNDEFINED;
screenLayout = SCREENLAYOUT_SIZE_UNDEFINED;
}
@@ -286,6 +302,11 @@
changed |= ActivityInfo.CONFIG_NAVIGATION;
navigation = delta.navigation;
}
+ if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
+ && navigationHidden != delta.navigationHidden) {
+ changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
+ navigationHidden = delta.navigationHidden;
+ }
if (delta.orientation != ORIENTATION_UNDEFINED
&& orientation != delta.orientation) {
changed |= ActivityInfo.CONFIG_ORIENTATION;
@@ -360,6 +381,10 @@
&& navigation != delta.navigation) {
changed |= ActivityInfo.CONFIG_NAVIGATION;
}
+ if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
+ && navigationHidden != delta.navigationHidden) {
+ changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
+ }
if (delta.orientation != ORIENTATION_UNDEFINED
&& orientation != delta.orientation) {
changed |= ActivityInfo.CONFIG_ORIENTATION;
@@ -416,6 +441,7 @@
dest.writeInt(keyboardHidden);
dest.writeInt(hardKeyboardHidden);
dest.writeInt(navigation);
+ dest.writeInt(navigationHidden);
dest.writeInt(orientation);
dest.writeInt(screenLayout);
}
@@ -448,6 +474,7 @@
keyboardHidden = source.readInt();
hardKeyboardHidden = source.readInt();
navigation = source.readInt();
+ navigationHidden = source.readInt();
orientation = source.readInt();
screenLayout = source.readInt();
}
@@ -478,6 +505,8 @@
if (n != 0) return n;
n = this.navigation - that.navigation;
if (n != 0) return n;
+ n = this.navigationHidden - that.navigationHidden;
+ if (n != 0) return n;
n = this.orientation - that.orientation;
if (n != 0) return n;
n = this.screenLayout - that.screenLayout;
@@ -503,6 +532,7 @@
return ((int)this.fontScale) + this.mcc + this.mnc
+ this.locale.hashCode() + this.touchscreen
+ this.keyboard + this.keyboardHidden + this.hardKeyboardHidden
- + this.navigation + this.orientation + this.screenLayout;
+ + this.navigation + this.navigationHidden
+ + this.orientation + this.screenLayout;
}
}
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 9991600..13effe0 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -38,12 +38,12 @@
* <p>There is no default constructor for this class. Use {@link #open()} to
* get a Camera object.</p>
*
- * <p>In order to use the device camera, you must declare the
- * {@link android.Manifest.permission#CAMERA} permission in your Android
+ * <p>In order to use the device camera, you must declare the
+ * {@link android.Manifest.permission#CAMERA} permission in your Android
* Manifest. Also be sure to include the
* <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><uses-feature></a>
- * manifest element in order to declare camera features used by your application.
- * For example, if you use the camera and auto-focus feature, your Manifest
+ * manifest element in order to declare camera features used by your application.
+ * For example, if you use the camera and auto-focus feature, your Manifest
* should include the following:</p>
* <pre> <uses-permission android:name="android.permission.CAMERA" />
* <uses-feature android:name="android.hardware.camera" />
@@ -52,7 +52,7 @@
* <p class="caution"><strong>Caution:</strong> Different Android-powered devices
* may have different hardware specifications, such as megapixel ratings and
* auto-focus capabilities. In order for your application to be compatible with
- * more devices, you should not make assumptions about the device camera
+ * more devices, you should not make assumptions about the device camera
* specifications.</p>
*/
public class Camera {
@@ -197,7 +197,7 @@
* The callback that delivers the preview frames.
*
* @param data The contents of the preview frame in the format defined
- * by {@link android.graphics.PixelFormat}, which can be queried
+ * by {@link android.graphics.PixelFormat}, which can be queried
* with {@link android.hardware.Camera.Parameters#getPreviewFormat()}.
* If {@link android.hardware.Camera.Parameters#setPreviewFormat(int)}
* is never called, the default will be the YCbCr_420_SP
@@ -340,11 +340,11 @@
/**
* Handles the callback for the camera auto focus.
- * <p>Devices that do not support auto-focus will receive a "fake"
- * callback to this interface. If your application needs auto-focus and
+ * <p>Devices that do not support auto-focus will receive a "fake"
+ * callback to this interface. If your application needs auto-focus and
* should not be installed on devices <em>without</em> auto-focus, you must
* declare that your app uses the
- * {@code android.hardware.camera.autofocus} feature, in the
+ * {@code android.hardware.camera.autofocus} feature, in the
* <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><uses-feature></a>
* manifest element.</p>
*/
@@ -368,11 +368,11 @@
* AutoFocusCallback#onAutoFocus(boolean, Camera)} callback will be called
* immediately.
* <p>If your application should not be installed
- * on devices without auto-focus, you must declare that your application
- * uses auto-focus with the
+ * on devices without auto-focus, you must declare that your application
+ * uses auto-focus with the
* <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><uses-feature></a>
* manifest element.</p>
- *
+ *
* @param cb the callback to run
*/
public final void autoFocus(AutoFocusCallback cb)
@@ -387,7 +387,6 @@
* this function will cancel it. Whether the auto-focus is in progress
* or not, this function will return the focus position to the default.
* If the camera does not support auto-focus, this is a no-op.
- * @hide
*/
public final void cancelAutoFocus()
{
@@ -917,11 +916,11 @@
}
/**
- * Sets the image format for preview pictures.
+ * Sets the image format for preview pictures.
* <p>If this is never called, the default format will be
* {@link android.graphics.PixelFormat#YCbCr_420_SP}, which
* uses the NV21 encoding format.</p>
- *
+ *
* @param pixel_format the desired preview picture format, defined
* by one of the {@link android.graphics.PixelFormat} constants.
* (E.g., <var>PixelFormat.YCbCr_420_SP</var> (default),
@@ -942,8 +941,8 @@
/**
* Returns the image format for preview pictures got from
* {@link PreviewCallback}.
- *
- * @return the {@link android.graphics.PixelFormat} int representing
+ *
+ * @return the {@link android.graphics.PixelFormat} int representing
* the preview picture format.
*/
public int getPreviewFormat() {
diff --git a/core/java/android/preference/DialogPreference.java b/core/java/android/preference/DialogPreference.java
index 666efae..cc48aeb 100644
--- a/core/java/android/preference/DialogPreference.java
+++ b/core/java/android/preference/DialogPreference.java
@@ -31,6 +31,9 @@
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
/**
@@ -297,10 +300,32 @@
if (state != null) {
dialog.onRestoreInstanceState(state);
}
+ if (needInputMethod()) {
+ requestInputMethod(dialog);
+ }
dialog.setOnDismissListener(this);
dialog.show();
}
-
+
+ /**
+ * Returns whether the preference needs to display a soft input method when the dialog
+ * is displayed. Default is false. Subclasses should override this method if they need
+ * the soft input method brought up automatically.
+ * @hide
+ */
+ protected boolean needInputMethod() {
+ return false;
+ }
+
+ /**
+ * Sets the required flags on the dialog window to enable input method window to show up.
+ */
+ private void requestInputMethod(Dialog dialog) {
+ Window window = dialog.getWindow();
+ window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE |
+ WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
+ }
+
/**
* Creates the content view for the dialog (if a custom content view is
* required). By default, it inflates the dialog layout resource if it is
diff --git a/core/java/android/preference/EditTextPreference.java b/core/java/android/preference/EditTextPreference.java
index a12704f..84ee950 100644
--- a/core/java/android/preference/EditTextPreference.java
+++ b/core/java/android/preference/EditTextPreference.java
@@ -169,6 +169,13 @@
return mEditText;
}
+ /** @hide */
+ @Override
+ protected boolean needInputMethod() {
+ // We want the input method to show, if possible, when dialog is displayed
+ return true;
+ }
+
@Override
protected Parcelable onSaveInstanceState() {
final Parcelable superState = super.onSaveInstanceState();
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index b0ac7f4..6eaf9dd 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1039,6 +1039,7 @@
public static final int TYPE_WORK_MOBILE = 17;
public static final int TYPE_WORK_PAGER = 18;
public static final int TYPE_ASSISTANT = 19;
+ public static final int TYPE_MMS = 20;
/**
* The phone number as the user entered it.
@@ -1529,7 +1530,7 @@
* called on a raw contact, it is marked for deletion and removed from its
* aggregate contact. The sync adaptor deletes the raw contact on the server and
* then calls ContactResolver.delete once more, this time setting the the
- * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize
+ * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize
* the data removal.
* <P>Type: INTEGER</P>
*/
@@ -1686,6 +1687,13 @@
public static final String UNGROUPED_VISIBLE = "ungrouped_visible";
/**
+ * Read-only flag indicating if this {@link #SHOULD_SYNC} or any
+ * {@link Groups#SHOULD_SYNC} under this account have been marked as
+ * unsynced.
+ */
+ public static final String ANY_UNSYNCED = "any_unsynced";
+
+ /**
* Read-only count of {@link Contacts} from a specific source that have
* no {@link CommonDataKinds.GroupMembership} entries.
* <p>
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0bbd1fc..6d03095 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2758,11 +2758,19 @@
/**
* Controls whether Gmail will discard uphill operations that repeatedly fail. Value must be
- * an integer where non-zero means true. Defaults to 1.
+ * an integer where non-zero means true. Defaults to 1. This flag controls Donut devices.
*/
public static final String GMAIL_DISCARD_ERROR_UPHILL_OP = "gmail_discard_error_uphill_op";
/**
+ * Controls whether Gmail will discard uphill operations that repeatedly fail. Value must be
+ * an integer where non-zero means true. Defaults to 1. This flag controls Eclair and
+ * future devices.
+ */
+ public static final String GMAIL_DISCARD_ERROR_UPHILL_OP_NEW =
+ "gmail_discard_error_uphill_op_new";
+
+ /**
* Controls how many attempts Gmail will try to upload an uphill operations before it
* abandons the operation. Defaults to 20.
*/
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index 9c687e2..be8c777 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -27,6 +27,7 @@
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.IBluetoothA2dp;
+import android.bluetooth.ParcelUuid;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -42,7 +43,6 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
-import java.util.UUID;
public class BluetoothA2dpService extends IBluetoothA2dp.Stub {
private static final String TAG = "BluetoothA2dpService";
@@ -188,15 +188,9 @@
}
private boolean isSinkDevice(BluetoothDevice device) {
- String uuids[] = mBluetoothService.getRemoteUuids(device.getAddress());
- UUID uuid;
- if (uuids != null) {
- for (String deviceUuid: uuids) {
- uuid = UUID.fromString(deviceUuid);
- if (BluetoothUuid.isAudioSink(uuid)) {
- return true;
- }
- }
+ ParcelUuid[] uuids = mBluetoothService.getRemoteUuids(device.getAddress());
+ if (uuids != null && BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.AudioSink)) {
+ return true;
}
return false;
}
@@ -229,18 +223,14 @@
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) {
- UUID remoteUuid = UUID.fromString(uuid);
- if (BluetoothUuid.isAudioSink(remoteUuid) ||
- BluetoothUuid.isAudioSource(remoteUuid) ||
- BluetoothUuid.isAdvAudioDist(remoteUuid)) {
- addAudioSink(device);
- break;
- }
+ ParcelUuid[] remoteUuids = mBluetoothService.getRemoteUuids(address);
+ if (remoteUuids != null)
+ if (BluetoothUuid.containsAnyUuid(remoteUuids,
+ new ParcelUuid[] {BluetoothUuid.AudioSink,
+ BluetoothUuid.AdvAudioDist})) {
+ addAudioSink(device);
}
- }
+ }
}
mAudioManager.setParameters(BLUETOOTH_ENABLED+"=true");
}
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 1ed5c49..ba53307 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -21,6 +21,7 @@
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothUuid;
+import android.bluetooth.ParcelUuid;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
@@ -28,7 +29,6 @@
import android.util.Log;
import java.util.HashMap;
-import java.util.UUID;
/**
* TODO: Move this to
@@ -501,7 +501,7 @@
}
boolean authorized = false;
- UUID uuid = UUID.fromString(deviceUuid);
+ ParcelUuid uuid = ParcelUuid.fromString(deviceUuid);
// Bluez sends the UUID of the local service being accessed, _not_ the
// remote service
if (mBluetoothService.isEnabled() &&
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index de0cad7..c0e4f34 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -24,11 +24,12 @@
package android.server;
-import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.IBluetooth;
+import android.bluetooth.ParcelUuid;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -51,7 +52,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
-import java.util.Iterator;
import java.util.Map;
public class BluetoothService extends IBluetooth.Stub {
@@ -967,22 +967,26 @@
/**
- * Gets the remote features encoded as bit mask.
+ * Gets the UUIDs supported by the remote device
*
- * Note: This method may be obsoleted soon.
- *
- * @return String array of 128bit UUIDs
+ * @return array of 128bit ParcelUuids
*/
- public synchronized String[] getRemoteUuids(String address) {
+ public synchronized ParcelUuid[] getRemoteUuids(String address) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
return null;
}
String value = getRemoteDeviceProperty(address, "UUIDs");
- String[] uuids = null;
+ if (value == null) return null;
+
+ String[] uuidStrings = null;
// The UUIDs are stored as a "," separated string.
- if (value != null)
- uuids = value.split(",");
+ uuidStrings = value.split(",");
+ ParcelUuid[] uuids = new ParcelUuid[uuidStrings.length];
+
+ for (int i = 0; i < uuidStrings.length; i++) {
+ uuids[i] = ParcelUuid.fromString(uuidStrings[i]);
+ }
return uuids;
}
@@ -990,16 +994,17 @@
* Gets the rfcomm channel associated with the UUID.
*
* @param address Address of the remote device
- * @param uuid UUID of the service attribute
+ * @param uuid ParcelUuid of the service attribute
*
* @return rfcomm channel associated with the service attribute
*/
- public int getRemoteServiceChannel(String address, String uuid) {
+ public int getRemoteServiceChannel(String address, ParcelUuid uuid) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
return BluetoothDevice.ERROR;
}
- return getDeviceServiceChannelNative(getObjectPathFromAddress(address), uuid, 0x0004);
+ return getDeviceServiceChannelNative(getObjectPathFromAddress(address), uuid.toString(),
+ 0x0004);
}
public synchronized boolean setPin(String address, byte[] pin) {
@@ -1148,11 +1153,11 @@
mBondState.getAttempt(address),
getRemoteName(address));
if (bondState == BluetoothDevice.BOND_BONDED) {
- String[] uuids = getRemoteUuids(address);
+ ParcelUuid[] uuids = getRemoteUuids(address);
if (uuids == null) {
pw.printf("\tuuids = null\n");
} else {
- for (String uuid : uuids) {
+ for (ParcelUuid uuid : uuids) {
pw.printf("\t" + uuid + "\n");
}
}
diff --git a/core/java/android/text/InputType.java b/core/java/android/text/InputType.java
index d50684a..14b8308 100644
--- a/core/java/android/text/InputType.java
+++ b/core/java/android/text/InputType.java
@@ -128,6 +128,15 @@
*/
public static final int TYPE_TEXT_FLAG_IME_MULTI_LINE = 0x00040000;
+ /**
+ * Flag for {@link #TYPE_CLASS_TEXT}: the input method does not need to
+ * display any dictionary-based candidates. This is useful for text views that
+ * do not contain words from the language and do not benefit from any
+ * dictionary-based completions or corrections. It overrides the
+ * {@link #TYPE_TEXT_FLAG_AUTO_CORRECT} value when set.
+ */
+ public static final int TYPE_TEXT_FLAG_NO_SUGGESTIONS = 0x00080000;
+
// ----------------------------------------------------------------------
/**
diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java
index 38881d3..f736f85 100644
--- a/core/java/android/text/method/QwertyKeyListener.java
+++ b/core/java/android/text/method/QwertyKeyListener.java
@@ -431,6 +431,7 @@
PICKER_SETS.put('z', "\u017A\u017C\u017E");
PICKER_SETS.put(KeyCharacterMap.PICKER_DIALOG_INPUT,
"\u2026\u00A5\u2022\u00AE\u00A9\u00B1[]{}\\");
+ PICKER_SETS.put('/', "\\");
// From packages/inputmethods/LatinIME/res/xml/kbd_symbols.xml
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 94acd3f..e5985c1 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -458,11 +458,12 @@
public final View createView(String name, String prefix, AttributeSet attrs)
throws ClassNotFoundException, InflateException {
Constructor constructor = sConstructorMap.get(name);
+ Class clazz = null;
try {
if (constructor == null) {
// Class not found in the cache, see if it's real, and try to add it
- Class clazz = mContext.getClassLoader().loadClass(
+ clazz = mContext.getClassLoader().loadClass(
prefix != null ? (prefix + name) : name);
if (mFilter != null && clazz != null) {
@@ -480,7 +481,7 @@
Boolean allowedState = mFilterMap.get(name);
if (allowedState == null) {
// New class -- remember whether it is allowed
- Class clazz = mContext.getClassLoader().loadClass(
+ clazz = mContext.getClassLoader().loadClass(
prefix != null ? (prefix + name) : name);
boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
@@ -511,7 +512,7 @@
} catch (Exception e) {
InflateException ie = new InflateException(attrs.getPositionDescription()
+ ": Error inflating class "
- + (constructor == null ? "<unknown>" : constructor.getClass().getName()));
+ + (clazz == null ? "<unknown>" : clazz.getName()));
ie.initCause(e);
throw ie;
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 8c12656..f67c4aa 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -500,6 +500,12 @@
*/
public static final int FLAG_SHOW_WALLPAPER = 0x00100000;
+ /** Window flag: when set as a window is being added or made
+ * visible, once the window has been shown then the system will
+ * poke the power manager's user activity (as if the user had woken
+ * up the device) to turn the screen on. */
+ public static final int FLAG_TURN_SCREEN_ON = 0x00200000;
+
/** Window flag: special flag to limit the size of the window to be
* original size ([320x480] x density). Used to create window for applications
* running under compatibility mode.
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 95b3a12..39a2470 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -16,6 +16,8 @@
package android.webkit;
+import com.android.internal.widget.EditableInputConnection;
+
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -38,6 +40,7 @@
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
@@ -346,6 +349,16 @@
@Override
protected void onSelectionChanged(int selStart, int selEnd) {
+ // This code is copied from TextView.onDraw(). That code does not get
+ // executed, however, because the WebTextView does not draw, allowing
+ // webkit's drawing to show through.
+ InputMethodManager imm = InputMethodManager.peekInstance();
+ if (imm != null && imm.isActive(this)) {
+ Spannable sp = (Spannable) getText();
+ int candStart = EditableInputConnection.getComposingSpanStart(sp);
+ int candEnd = EditableInputConnection.getComposingSpanEnd(sp);
+ imm.updateSelection(this, selStart, selEnd, candStart, candEnd);
+ }
if (!mFromWebKit && mWebView != null) {
if (DebugFlags.WEB_TEXT_VIEW) {
Log.v(LOGTAG, "onSelectionChanged selStart=" + selStart
@@ -430,18 +443,26 @@
mGotTouchDown = true;
break;
case MotionEvent.ACTION_MOVE:
+ int slop = ViewConfiguration.get(mContext).getScaledTouchSlop();
Spannable buffer = getText();
int initialScrollX = Touch.getInitialScrollX(this, buffer);
int initialScrollY = Touch.getInitialScrollY(this, buffer);
super.onTouchEvent(event);
- if (mScrollX != initialScrollX
- || mScrollY != initialScrollY) {
+ if (Math.abs(mScrollX - initialScrollX) > slop
+ || Math.abs(mScrollY - initialScrollY) > slop) {
if (mWebView != null) {
mWebView.scrollFocusedTextInput(mScrollX, mScrollY);
}
mScrolled = true;
return true;
}
+ if (Math.abs((int) event.getX() - mDragStartX) < slop
+ && Math.abs((int) event.getY() - mDragStartY) < slop) {
+ // If the user has not scrolled further than slop, we should not
+ // send the drag. Instead, do nothing, and when the user lifts
+ // their finger, we will change the selection.
+ return true;
+ }
if (mWebView != null) {
// Only want to set the initial state once.
if (!mDragSent) {
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 081f67a..abbbc00 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -420,6 +420,7 @@
private static final int STD_SPEED = 480; // pixels per second
// time for the longest scroll animation
private static final int MAX_DURATION = 750; // milliseconds
+ private static final int SLIDE_TITLE_DURATION = 300; // milliseconds
private Scroller mScroller;
private boolean mWrapContent;
@@ -2416,10 +2417,18 @@
if ((dx | dy) == 0) {
return false;
}
-
- if (true && animate) {
+ // mobile sites prefer to scroll to (0, 1), thus the + 1 below
+ boolean slideTitle = getVisibleTitleHeight() > 0
+ && y <= getTitleHeight() + 1;
+ if (DebugFlags.WEB_VIEW) {
+ Log.v(LOGTAG, "pinScrollTo slideTitle=" + slideTitle
+ + " getVisibleTitleHeight()=" + getVisibleTitleHeight()
+ + " animationDuration=" + animationDuration + " y=" + y);
+ }
+ if (slideTitle || animate) {
// Log.d(LOGTAG, "startScroll: " + dx + " " + dy);
-
+ if (slideTitle && animationDuration < SLIDE_TITLE_DURATION)
+ animationDuration = SLIDE_TITLE_DURATION;
mScroller.startScroll(mScrollX, mScrollY, dx, dy,
animationDuration > 0 ? animationDuration : computeDuration(dx, dy));
invalidate();
@@ -4791,8 +4800,11 @@
mMaxZoomScale = restoreState.mMaxScale;
}
setNewZoomScale(mLastScale, false);
- setContentScrollTo(restoreState.mScrollX,
- restoreState.mScrollY);
+ if (getVisibleTitleHeight() == 0
+ || restoreState.mScrollY != 0) {
+ setContentScrollTo(restoreState.mScrollX,
+ restoreState.mScrollY);
+ }
if (useWideViewport
&& settings.getLoadWithOverviewMode()) {
if (restoreState.mViewScale == 0
diff --git a/core/java/com/android/internal/widget/ContactHeaderWidget.java b/core/java/com/android/internal/widget/ContactHeaderWidget.java
index fe01866..4ec597c 100644
--- a/core/java/com/android/internal/widget/ContactHeaderWidget.java
+++ b/core/java/com/android/internal/widget/ContactHeaderWidget.java
@@ -42,6 +42,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.widget.CheckBox;
+import android.widget.FasttrackBadgeWidget;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
@@ -64,15 +65,13 @@
private TextView mDisplayNameView;
private TextView mPhoneticNameView;
private CheckBox mStarredView;
- private ImageView mPhotoView;
+ private FasttrackBadgeWidget mPhotoView;
private ImageView mPresenceView;
private TextView mStatusView;
private int mNoPhotoResource;
private QueryHandler mQueryHandler;
- protected long mContactId;
protected Uri mContactUri;
- protected Uri mStatusUri;
protected String[] mExcludeMimes = null;
@@ -94,6 +93,8 @@
Contacts.STARRED,
Contacts.PHOTO_ID,
Contacts.PRESENCE_STATUS,
+ Contacts._ID,
+ Contacts.LOOKUP_KEY,
};
protected static final int HEADER_DISPLAY_NAME_COLUMN_INDEX = 0;
//TODO: We need to figure out how we're going to get the phonetic name.
@@ -101,6 +102,8 @@
protected static final int HEADER_STARRED_COLUMN_INDEX = 1;
protected static final int HEADER_PHOTO_ID_COLUMN_INDEX = 2;
protected static final int HEADER_PRESENCE_STATUS_COLUMN_INDEX = 3;
+ protected static final int HEADER_CONTACT_ID_COLUMN_INDEX = 4;
+ protected static final int HEADER_LOOKUP_KEY_COLUMN_INDEX = 5;
//Projection used for finding the most recent social status.
protected static final String[] SOCIAL_PROJECTION = new String[] {
@@ -113,18 +116,29 @@
//Projection used for looking up contact id from phone number
protected static final String[] PHONE_LOOKUP_PROJECTION = new String[] {
PhoneLookup._ID,
+ PhoneLookup.LOOKUP_KEY,
};
protected static final int PHONE_LOOKUP_CONTACT_ID_COLUMN_INDEX = 0;
+ protected static final int PHONE_LOOKUP_CONTACT_LOOKUP_KEY_COLUMN_INDEX = 1;
//Projection used for looking up contact id from email address
protected static final String[] EMAIL_LOOKUP_PROJECTION = new String[] {
RawContacts.CONTACT_ID,
+ Contacts.LOOKUP_KEY,
};
protected static final int EMAIL_LOOKUP_CONTACT_ID_COLUMN_INDEX = 0;
+ protected static final int EMAIL_LOOKUP_CONTACT_LOOKUP_KEY_COLUMN_INDEX = 1;
+ protected static final String[] CONTACT_LOOKUP_PROJECTION = new String[] {
+ Contacts._ID,
+ };
+ protected static final int CONTACT_LOOKUP_ID_COLUMN_INDEX = 0;
private static final int TOKEN_CONTACT_INFO = 0;
private static final int TOKEN_SOCIAL = 1;
+ private static final int TOKEN_PHONE_LOOKUP = 2;
+ private static final int TOKEN_EMAIL_LOOKUP = 3;
+ private static final int TOKEN_LOOKUP_CONTACT_FOR_SOCIAL_QUERY = 4;
public ContactHeaderWidget(Context context) {
this(context, null);
@@ -151,8 +165,7 @@
mStarredView = (CheckBox)findViewById(R.id.star);
mStarredView.setOnClickListener(this);
- mPhotoView = (ImageView)findViewById(R.id.photo);
- mPhotoView.setOnClickListener(this);
+ mPhotoView = (FasttrackBadgeWidget) findViewById(R.id.photo);
mPhotoView.setOnLongClickListener(this);
mPresenceView = (ImageView) findViewById(R.id.presence);
@@ -217,12 +230,46 @@
@Override
protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
try{
- if (token == TOKEN_CONTACT_INFO) {
- bindContactInfo(cursor);
- invalidate();
- } else if (token == TOKEN_SOCIAL) {
- bindSocial(cursor);
- invalidate();
+ switch (token) {
+ case TOKEN_CONTACT_INFO: {
+ bindContactInfo(cursor);
+ invalidate();
+ break;
+ }
+ case TOKEN_SOCIAL: {
+ bindSocial(cursor);
+ invalidate();
+ break;
+ }
+ case TOKEN_PHONE_LOOKUP: {
+ if (cursor != null && cursor.moveToFirst()) {
+ long contactId = cursor.getLong(PHONE_LOOKUP_CONTACT_ID_COLUMN_INDEX);
+ String lookupKey = cursor.getString(
+ PHONE_LOOKUP_CONTACT_LOOKUP_KEY_COLUMN_INDEX);
+ bindFromContactUri(Contacts.getLookupUri(contactId, lookupKey));
+ } else {
+ setDisplayName((String) cookie, null);
+ }
+ break;
+ }
+ case TOKEN_EMAIL_LOOKUP: {
+ if (cursor != null && cursor.moveToFirst()) {
+ long contactId = cursor.getLong(EMAIL_LOOKUP_CONTACT_ID_COLUMN_INDEX);
+ String lookupKey = cursor.getString(
+ EMAIL_LOOKUP_CONTACT_LOOKUP_KEY_COLUMN_INDEX);
+ bindFromContactUri(Contacts.getLookupUri(contactId, lookupKey));
+ } else {
+ setDisplayName((String) cookie, null);
+ }
+ break;
+ }
+ case TOKEN_LOOKUP_CONTACT_FOR_SOCIAL_QUERY: {
+ if (cursor != null && cursor.moveToFirst()) {
+ long contactId = cursor.getLong(CONTACT_LOOKUP_ID_COLUMN_INDEX);
+ startSocialQuery(ContentUris.withAppendedId(
+ Activities.CONTENT_CONTACT_STATUS_URI, contactId));
+ }
+ }
}
} finally {
if (cursor != null) {
@@ -300,33 +347,31 @@
* Convenience method for binding all available data from an existing
* contact.
*
- * @param contactId the contact id of the contact whose info should be displayed.
+ * @param conatctUri a {Contacts.CONTENT_LOOKUP_URI} style URI.
*/
- public void bindFromContactId(long contactId) {
- mContactId = contactId;
- mContactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, mContactId);
+ public void bindFromContactLookupUri(Uri contactLookupUri) {
+ mContactUri = contactLookupUri;
- bindContactUri(mContactUri);
- bindSocialUri(ContentUris.withAppendedId(Activities.CONTENT_CONTACT_STATUS_URI, mContactId));
+ // Query for the contactId so we can do the social query.
+ mQueryHandler.startQuery(TOKEN_LOOKUP_CONTACT_FOR_SOCIAL_QUERY, null, contactLookupUri,
+ CONTACT_LOOKUP_PROJECTION, null, null, null);
+
+ startContactQuery(contactLookupUri);
}
/**
- * Convenience method for binding {@link Contacts} header details from a
- * {@link Contacts#CONTENT_URI} reference.
+ * Convenience method for binding all available data from an existing
+ * contact.
+ *
+ * @param conatctUri a {Contacts.CONTENT_URI} style URI.
*/
- public void bindContactUri(Uri contactUri) {
- mQueryHandler.startQuery(TOKEN_CONTACT_INFO, null, contactUri, HEADER_PROJECTION,
- null, null, null);
- }
+ public void bindFromContactUri(Uri contactUri) {
+ mContactUri = contactUri;
+ long contactId = ContentUris.parseId(contactUri);
- /**
- * Convenience method for binding {@link Activities} header details from a
- * {@link Activities#CONTENT_CONTACT_STATUS_URI}.
- */
- public void bindSocialUri(Uri contactSocial) {
- mStatusUri = contactSocial;
- mQueryHandler.startQuery(TOKEN_SOCIAL, null, mStatusUri, SOCIAL_PROJECTION, null, null,
- null);
+ startContactQuery(contactUri);
+ startSocialQuery(ContentUris.withAppendedId(
+ Activities.CONTENT_CONTACT_STATUS_URI, contactId));
}
/**
@@ -338,21 +383,9 @@
* address, one of them will be chosen to bind to.
*/
public void bindFromEmail(String emailAddress) {
- Cursor c = null;
- try {
- c = mContentResolver.query(Uri.withAppendedPath(Email.CONTENT_FILTER_EMAIL_URI, Uri
- .encode(emailAddress)), EMAIL_LOOKUP_PROJECTION, null, null, null);
- if (c != null && c.moveToFirst()) {
- long contactId = c.getLong(EMAIL_LOOKUP_CONTACT_ID_COLUMN_INDEX);
- bindFromContactId(contactId);
- } else {
- setDisplayName(emailAddress, null);
- }
- } finally {
- if (c != null) {
- c.close();
- }
- }
+ mQueryHandler.startQuery(TOKEN_EMAIL_LOOKUP, emailAddress,
+ Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(emailAddress)),
+ EMAIL_LOOKUP_PROJECTION, null, null, null);
}
/**
@@ -364,22 +397,19 @@
* number, one of them will be chosen to bind to.
*/
public void bindFromPhoneNumber(String number) {
- Cursor c = null;
- try {
- c = mContentResolver.query(
- Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number)),
- PHONE_LOOKUP_PROJECTION, null, null, null);
- if (c != null && c.moveToFirst()) {
- long contactId = c.getLong(PHONE_LOOKUP_CONTACT_ID_COLUMN_INDEX);
- bindFromContactId(contactId);
- } else {
- setDisplayName(number, null);
- }
- } finally {
- if (c != null) {
- c.close();
- }
- }
+ mQueryHandler.startQuery(TOKEN_PHONE_LOOKUP, number,
+ Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, number),
+ PHONE_LOOKUP_PROJECTION, null, null, null);
+ }
+
+ private void startSocialQuery(Uri contactSocial) {
+ mQueryHandler.startQuery(TOKEN_SOCIAL, null, contactSocial, SOCIAL_PROJECTION, null, null,
+ null);
+ }
+
+ private void startContactQuery(Uri contactUri) {
+ mQueryHandler.startQuery(TOKEN_CONTACT_INFO, null, contactUri, HEADER_PROJECTION,
+ null, null, null);
}
/**
@@ -390,6 +420,8 @@
// TODO: Bring back phonetic name
final String displayName = c.getString(HEADER_DISPLAY_NAME_COLUMN_INDEX);
+ final long contactId = c.getLong(HEADER_CONTACT_ID_COLUMN_INDEX);
+ final String lookupKey = c.getString(HEADER_LOOKUP_KEY_COLUMN_INDEX);
final String phoneticName = null;
this.setDisplayName(displayName, null);
@@ -402,6 +434,7 @@
photoBitmap = loadPlaceholderPhoto(null);
}
mPhotoView.setImageBitmap(photoBitmap);
+ mPhotoView.assignContactUri(Contacts.getLookupUri(contactId, lookupKey));
//Set the presence status
int presence = c.getInt(HEADER_PRESENCE_STATUS_COLUMN_INDEX);
@@ -423,27 +456,11 @@
return;
}
- switch (view.getId()) {
- case R.id.star: {
- // Toggle "starred" state
- final ContentValues values = new ContentValues(1);
- values.put(Contacts.STARRED, mStarredView.isChecked());
- mContentResolver.update(mContactUri, values, null, null);
- break;
- }
- case R.id.photo: {
- // Photo launches contact detail action
- final Intent intent = new Intent(Intents.SHOW_OR_CREATE_CONTACT, mContactUri);
- final Rect target = getTargetRect(view);
- intent.putExtra(Intents.EXTRA_TARGET_RECT, target);
- intent.putExtra(Intents.EXTRA_MODE, Intents.MODE_SMALL);
- if (mExcludeMimes != null) {
- // Exclude specific MIME-types when requested
- intent.putExtra(Intents.EXTRA_EXCLUDE_MIMES, mExcludeMimes);
- }
- mContext.startActivity(intent);
- break;
- }
+ if (view.getId() == R.id.star) {
+ // Toggle "starred" state
+ final ContentValues values = new ContentValues(1);
+ values.put(Contacts.STARRED, mStarredView.isChecked());
+ mContentResolver.update(mContactUri, values, null, null);
}
}
diff --git a/core/java/com/android/internal/widget/RotarySelector.java b/core/java/com/android/internal/widget/RotarySelector.java
index 7b940c9..aff92b8 100644
--- a/core/java/com/android/internal/widget/RotarySelector.java
+++ b/core/java/com/android/internal/widget/RotarySelector.java
@@ -19,8 +19,6 @@
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Vibrator;
import android.util.AttributeSet;
@@ -28,7 +26,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
-
+import static android.view.animation.AnimationUtils.currentAnimationTimeMillis;
import com.android.internal.R;
@@ -69,7 +67,7 @@
private boolean mAnimating = false;
private long mAnimationEndTime;
private int mAnimatingDelta;
- AccelerateInterpolator mInterpolator;
+ private AccelerateInterpolator mInterpolator;
/**
* True after triggering an action if the user of {@link OnDialTriggerListener} wants to
@@ -96,12 +94,6 @@
private static final long VIBRATE_SHORT = 60; // msec
private static final long VIBRATE_LONG = 100; // msec
- // Various tweakable layout or behavior parameters:
-
- // How close to the edge of the screen, we let the handle get before
- // triggering an action:
- private static final int EDGE_THRESHOLD_DIP = 70;
-
/**
* The drawable for the arrows need to be scrunched this many dips towards the rotary bg below
* it.
@@ -122,6 +114,11 @@
private static final boolean DRAW_CENTER_DIMPLE = false;
+ public RotarySelector(Context context) {
+ this(context, null);
+ }
+
+
/**
* Constructor used when this widget is created from a layout file.
*/
@@ -132,8 +129,6 @@
Resources r = getResources();
mDensity = r.getDisplayMetrics().density;
if (DBG) log("- Density: " + mDensity);
- // Density is 1.0 on HVGA (like Dream), and 1.5 on WVGA.
- // Usage: raw_pixel_value = (int) (dpi_value * mDensity + 0.5f)
// Assets (all are BitmapDrawables).
mBackground = r.getDrawable(R.drawable.jog_dial_bg_cropped);
@@ -143,6 +138,15 @@
mArrowLongRight = r.getDrawable(R.drawable.jog_dial_arrow_long_right_red);
mArrowShortLeftAndRight = r.getDrawable(R.drawable.jog_dial_arrow_short_left_and_right);
+ // Arrows:
+ // All arrow assets are the same size (they're the full width of
+ // the screen) regardless of which arrows are actually visible.
+ int arrowW = mArrowShortLeftAndRight.getIntrinsicWidth();
+ int arrowH = mArrowShortLeftAndRight.getIntrinsicHeight();
+ mArrowShortLeftAndRight.setBounds(0, 0, arrowW, arrowH);
+ mArrowLongLeft.setBounds(0, 0, arrowW, arrowH);
+ mArrowLongRight.setBounds(0, 0, arrowW, arrowH);
+
mInterpolator = new AccelerateInterpolator();
}
@@ -237,7 +241,7 @@
// update animating state before we draw anything
if (mAnimating && !mFrozen) {
- long millisLeft = mAnimationEndTime - System.currentTimeMillis();
+ long millisLeft = mAnimationEndTime - currentAnimationTimeMillis();
if (DBG) log("millisleft for animating: " + millisLeft);
if (millisLeft <= 0) {
reset();
@@ -259,11 +263,6 @@
if (DBG) log(" Background BOUNDS: " + mBackground.getBounds());
mBackground.draw(canvas);
- // Arrows:
- // All arrow assets are the same size (they're the full width of
- // the screen) regardless of which arrows are actually visible.
- int arrowW = mArrowShortLeftAndRight.getIntrinsicWidth();
- int arrowH = mArrowShortLeftAndRight.getIntrinsicHeight();
// Draw the correct arrow(s) depending on the current state:
Drawable currentArrow;
@@ -280,7 +279,6 @@
default:
throw new IllegalStateException("invalid mGrabbedState: " + mGrabbedState);
}
- currentArrow.setBounds(0, 0, arrowW, arrowH);
currentArrow.draw(canvas);
// debug: draw circle that should match the outer arc (good sanity check)
@@ -382,63 +380,70 @@
final int eventX = (int) event.getX();
final int hitWindow = mDimple.getIntrinsicWidth();
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- if (DBG) log("touch-down");
- mTriggered = false;
- if (mGrabbedState != RotarySelector.NOTHING_GRABBED) {
+ final int action = event.getAction();
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ if (DBG) log("touch-down");
+ mTriggered = false;
+ if (mGrabbedState != NOTHING_GRABBED) {
+ reset();
+ invalidate();
+ }
+ if (eventX < mLeftHandleX + hitWindow) {
+ mTouchDragOffset = eventX - mLeftHandleX;
+ mGrabbedState = LEFT_HANDLE_GRABBED;
+ invalidate();
+ vibrate(VIBRATE_SHORT);
+ } else if (eventX > mRightHandleX - hitWindow) {
+ mTouchDragOffset = eventX - mRightHandleX;
+ mGrabbedState = RIGHT_HANDLE_GRABBED;
+ invalidate();
+ vibrate(VIBRATE_SHORT);
+ }
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ if (DBG) log("touch-move");
+ if (mGrabbedState == LEFT_HANDLE_GRABBED) {
+ mTouchDragOffset = eventX - mLeftHandleX;
+ invalidate();
+ if (eventX >= mRightHandleX - EDGE_PADDING_DIP && !mTriggered) {
+ mTriggered = true;
+ mFrozen = dispatchTriggerEvent(OnDialTriggerListener.LEFT_HANDLE);
+ }
+ } else if (mGrabbedState == RIGHT_HANDLE_GRABBED) {
+ mTouchDragOffset = eventX - mRightHandleX;
+ invalidate();
+ if (eventX <= mLeftHandleX + EDGE_PADDING_DIP && !mTriggered) {
+ mTriggered = true;
+ mFrozen = dispatchTriggerEvent(OnDialTriggerListener.RIGHT_HANDLE);
+ }
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ if (DBG) log("touch-up");
+ // handle animating back to start if they didn't trigger
+ if (mGrabbedState == LEFT_HANDLE_GRABBED
+ && Math.abs(eventX - mLeftHandleX) > 5) {
+ mAnimating = true;
+ mAnimationEndTime = currentAnimationTimeMillis() + ANIMATION_DURATION_MILLIS;
+ mAnimatingDelta = eventX - mLeftHandleX;
+ } else if (mGrabbedState == RIGHT_HANDLE_GRABBED
+ && Math.abs(eventX - mRightHandleX) > 5) {
+ mAnimating = true;
+ mAnimationEndTime = currentAnimationTimeMillis() + ANIMATION_DURATION_MILLIS;
+ mAnimatingDelta = eventX - mRightHandleX;
+ }
+
+ mTouchDragOffset = 0;
+ mGrabbedState = NOTHING_GRABBED;
+ invalidate();
+ break;
+ case MotionEvent.ACTION_CANCEL:
+ if (DBG) log("touch-cancel");
reset();
invalidate();
- }
- if (eventX < mLeftHandleX + hitWindow) {
- mTouchDragOffset = eventX - mLeftHandleX;
- mGrabbedState = RotarySelector.LEFT_HANDLE_GRABBED;
- invalidate();
- vibrate(VIBRATE_SHORT);
- } else if (eventX > mRightHandleX - hitWindow) {
- mTouchDragOffset = eventX - mRightHandleX;
- mGrabbedState = RotarySelector.RIGHT_HANDLE_GRABBED;
- invalidate();
- vibrate(VIBRATE_SHORT);
- }
- } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
- if (DBG) log("touch-move");
- if (mGrabbedState == RotarySelector.LEFT_HANDLE_GRABBED) {
- mTouchDragOffset = eventX - mLeftHandleX;
- invalidate();
- if (eventX >= mRightHandleX - EDGE_PADDING_DIP && !mTriggered) {
- mTriggered = true;
- mFrozen = dispatchTriggerEvent(OnDialTriggerListener.LEFT_HANDLE);
- }
- } else if (mGrabbedState == RotarySelector.RIGHT_HANDLE_GRABBED) {
- mTouchDragOffset = eventX - mRightHandleX;
- invalidate();
- if (eventX <= mLeftHandleX + EDGE_PADDING_DIP && !mTriggered) {
- mTriggered = true;
- mFrozen = dispatchTriggerEvent(OnDialTriggerListener.RIGHT_HANDLE);
- }
- }
- } else if ((event.getAction() == MotionEvent.ACTION_UP)) {
- if (DBG) log("touch-up");
- // handle animating back to start if they didn't trigger
- if (mGrabbedState == RotarySelector.LEFT_HANDLE_GRABBED
- && Math.abs(eventX - mLeftHandleX) > 5) {
- mAnimating = true;
- mAnimationEndTime = System.currentTimeMillis() + ANIMATION_DURATION_MILLIS;
- mAnimatingDelta = eventX - mLeftHandleX;
- } else if (mGrabbedState == RotarySelector.RIGHT_HANDLE_GRABBED
- && Math.abs(eventX - mRightHandleX) > 5) {
- mAnimating = true;
- mAnimationEndTime = System.currentTimeMillis() + ANIMATION_DURATION_MILLIS;
- mAnimatingDelta = eventX - mRightHandleX;
- }
-
- mTouchDragOffset = 0;
- mGrabbedState = RotarySelector.NOTHING_GRABBED;
- invalidate();
- } else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
- if (DBG) log("touch-cancel");
- reset();
- invalidate();
+ break;
}
return true;
}
@@ -446,7 +451,7 @@
private void reset() {
mAnimating = false;
mTouchDragOffset = 0;
- mGrabbedState = RotarySelector.NOTHING_GRABBED;
+ mGrabbedState = NOTHING_GRABBED;
mTriggered = false;
}
diff --git a/core/jni/android_server_BluetoothA2dpService.cpp b/core/jni/android_server_BluetoothA2dpService.cpp
index a185d8d..ba13519 100644
--- a/core/jni/android_server_BluetoothA2dpService.cpp
+++ b/core/jni/android_server_BluetoothA2dpService.cpp
@@ -133,23 +133,13 @@
LOGV(__FUNCTION__);
if (nat) {
const char *c_path = env->GetStringUTFChars(path, NULL);
- DBusError err;
- dbus_error_init(&err);
- DBusMessage *reply =
- dbus_func_args_timeout(env, nat->conn, -1, c_path,
- "org.bluez.AudioSink", "Connect",
- DBUS_TYPE_INVALID);
+ bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
+ c_path, "org.bluez.AudioSink", "Connect",
+ DBUS_TYPE_INVALID);
+
env->ReleaseStringUTFChars(path, c_path);
-
- if (!reply && dbus_error_is_set(&err)) {
- LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
- return JNI_FALSE;
- } else if (!reply) {
- LOGE("DBus reply is NULL in function %s", __FUNCTION__);
- return JNI_FALSE;
- }
- return JNI_TRUE;
+ return ret ? JNI_TRUE : JNI_FALSE;
}
#endif
return JNI_FALSE;
@@ -161,23 +151,13 @@
LOGV(__FUNCTION__);
if (nat) {
const char *c_path = env->GetStringUTFChars(path, NULL);
- DBusError err;
- dbus_error_init(&err);
- DBusMessage *reply =
- dbus_func_args_timeout(env, nat->conn, -1, c_path,
- "org.bluez.AudioSink", "Disconnect",
- DBUS_TYPE_INVALID);
+ bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat,
+ c_path, "org.bluez.AudioSink", "Disconnect",
+ DBUS_TYPE_INVALID);
+
env->ReleaseStringUTFChars(path, c_path);
-
- if (!reply && dbus_error_is_set(&err)) {
- LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
- return JNI_FALSE;
- } else if (!reply) {
- LOGE("DBus reply is NULL in function %s", __FUNCTION__);
- return JNI_FALSE;
- }
- return JNI_TRUE;
+ return ret ? JNI_TRUE : JNI_FALSE;
}
#endif
return JNI_FALSE;
diff --git a/core/res/res/drawable-hdpi/title_bar_medium.png b/core/res/res/drawable-hdpi/title_bar_medium.png
new file mode 100644
index 0000000..c13dd26
--- /dev/null
+++ b/core/res/res/drawable-hdpi/title_bar_medium.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/title_bar_medium.png b/core/res/res/drawable-mdpi/title_bar_medium.png
new file mode 100644
index 0000000..9d01f79
--- /dev/null
+++ b/core/res/res/drawable-mdpi/title_bar_medium.png
Binary files differ
diff --git a/core/res/res/layout/contact_header.xml b/core/res/res/layout/contact_header.xml
index 8d7e470..e800dfa 100644
--- a/core/res/res/layout/contact_header.xml
+++ b/core/res/res/layout/contact_header.xml
@@ -19,17 +19,17 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
- android:background="@drawable/title_bar_tall"
+ android:background="@drawable/title_bar_medium"
android:paddingRight="5dip"
android:gravity="center_vertical">
- <ImageView android:id="@+id/photo"
- android:layout_width="56dip"
- android:layout_height="62dip"
+ <android.widget.FasttrackBadgeWidget android:id="@+id/photo"
+ android:layout_alignParentLeft="true"
+ android:layout_centerVertical="true"
android:layout_marginRight="10dip"
android:layout_marginLeft="10dip"
- android:scaleType="fitCenter"
- android:background="@drawable/fasttrack_badge_middle_large"/>
+ style="@*android:style/Widget.FasttrackBadgeWidget.WindowSmall" />
+ />
<LinearLayout
android:layout_width="0dip"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a1a179b..eae838a 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -530,6 +530,11 @@
lines, the IME should provide multiple lines if it can. Corresponds to
{@link android.text.InputType#TYPE_TEXT_FLAG_IME_MULTI_LINE}. -->
<flag name="textImeMultiLine" value="0x00040001" />
+ <!-- Can be combined with <var>text</var> and its variations to
+ indicate that the IME should not show any
+ dictionary-based word suggestions. Corresponds to
+ {@link android.text.InputType#TYPE_TEXT_FLAG_NO_SUGGESTIONS}. -->
+ <flag name="textNoSuggestions" value="0x00080001" />
<!-- Text that will be used as a URI. Corresponds to
{@link android.text.InputType#TYPE_CLASS_TEXT} |
{@link android.text.InputType#TYPE_TEXT_VARIATION_URI}. -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 7aaf218..365363a 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -504,8 +504,10 @@
<!-- The keyboard type has changed, for example the user has plugged
in an external keyboard. -->
<flag name="keyboard" value="0x0010" />
- <!-- The keyboard accessibility has changed, for example the user has
- slid the keyboard out to expose it. -->
+ <!-- The keyboard or navigation accessibility has changed, for example
+ the user has slid the keyboard out to expose it. Note that
+ inspite of its name, this applied to any accessibility: keyboard
+ or navigation. -->
<flag name="keyboardHidden" value="0x0020" />
<!-- The navigation type has changed. Should never normally happen. -->
<flag name="navigation" value="0x0040" />
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 62a230c..c967c4c 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -18,7 +18,7 @@
*/
-->
<resources>
- <drawable name="screen_background_light">#fff9f9f9</drawable>
+ <drawable name="screen_background_light">#ffffffff</drawable>
<drawable name="screen_background_dark">#ff202020</drawable>
<drawable name="status_bar_closed_default_background">#ff000000</drawable>
<drawable name="status_bar_opened_default_background">#ff000000</drawable>
@@ -45,7 +45,7 @@
<color name="dim_foreground_dark_inverse">#323232</color>
<color name="dim_foreground_dark_inverse_disabled">#80323232</color>
<color name="hint_foreground_dark">#808080</color>
- <color name="background_light">#fff9f9f9</color>
+ <color name="background_light">#ffffffff</color>
<color name="bright_foreground_light">#ff000000</color>
<color name="bright_foreground_light_inverse">#ffffffff</color>
<color name="bright_foreground_light_disabled">#80000000</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 117e139..b710acb6 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -35,6 +35,9 @@
<!-- The duration (in milliseconds) of a long animation. -->
<integer name="config_longAnimTime">300</integer>
+ <!-- XXXXX NOTE THE FOLLOWING RESOURCES USE THE WRONG NAMING CONVENTION.
+ Please don't copy them, copy anything else. -->
+
<!-- This string array should be overridden by the device to present a list of network attributes. This is used by the connectivity manager to decide which networks can coexist based on the hardward -->
<!-- An Array of "[type-name],[associated radio-name],[priority] -->
<string-array translatable="false" name="networkAttributes">
@@ -53,18 +56,40 @@
<item>"wifi,1,1"</item>
<item>"mobile,0,1"</item>
</string-array>
-
- <!-- The number of degrees to rotate the display when the keyboard is open. -->
- <integer name="config_lidOpenRotation">90</integer>
-
- <!-- The number of degrees to rotate the display when the device is in a dock. -->
- <integer name="config_dockedRotation">90</integer>
-
+
<!-- Flag indicating whether the keyguard should be bypassed when
the slider is open. This can be set or unset depending how easily
the slider can be opened (for example, in a pocket or purse). -->
<bool name="config_bypass_keyguard_if_slider_open">true</bool>
+ <!-- Flag indicating whether the device supports automatic brightness mode. -->
+ <bool name="config_automatic_brightness_available">false</bool>
+
+ <!-- XXXXXX END OF RESOURCES USING WRONG NAMING CONVENTION -->
+
+ <!-- The number of degrees to rotate the display when the keyboard is open. -->
+ <integer name="config_lidOpenRotation">90</integer>
+
+ <!-- The number of degrees to rotate the display when the device is in a desk dock.
+ A value of -1 means no change in orientation by default. -->
+ <integer name="config_deskDockRotation">-1</integer>
+
+ <!-- The number of degrees to rotate the display when the device is in a car dock.
+ A value of -1 means no change in orientation by default. -->
+ <integer name="config_carDockRotation">-1</integer>
+
+ <!-- Indicate whether the lid state impacts the accessibility of
+ the physical keyboard. 0 means it doesn't, 1 means it is accessible
+ when the lid is open, 2 means it is accessible when the lid is
+ closed. The default is 1. -->
+ <integer name="config_lidKeyboardAccessibility">1</integer>
+
+ <!-- Indicate whether the lid state impacts the accessibility of
+ the physical keyboard. 0 means it doesn't, 1 means it is accessible
+ when the lid is open, 2 means it is accessible when the lid is
+ closed. The default is 0. -->
+ <integer name="config_lidNavigationAccessibility">0</integer>
+
<!-- Vibrator pattern for feedback about a long screen/key press -->
<integer-array name="config_longPressVibePattern">
<item>0</item>
@@ -81,6 +106,4 @@
<item>30</item>
</integer-array>
- <!-- Flag indicating whether the device supports automatic brightness mode. -->
- <bool name="config_automatic_brightness_available">false</bool>
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 69ddd63..bd79c75 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1962,7 +1962,7 @@
<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="permission_request_notification_with_subtitle">Permission Requested\nfor 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>
diff --git a/data/etc/Android.mk b/data/etc/Android.mk
index a32d8ea..041c5d3 100644
--- a/data/etc/Android.mk
+++ b/data/etc/Android.mk
@@ -32,3 +32,20 @@
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)
+
+########################
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := required_hardware.xml
+
+LOCAL_MODULE_TAGS := user
+
+LOCAL_MODULE_CLASS := ETC
+
+# This will install the file in /system/etc/permissions
+#
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
+
+LOCAL_SRC_FILES := $(LOCAL_MODULE)
+
+include $(BUILD_PREBUILT)
diff --git a/data/etc/android.hardware.camera.flash-autofocus.xml b/data/etc/android.hardware.camera.flash-autofocus.xml
new file mode 100644
index 0000000..55f1900
--- /dev/null
+++ b/data/etc/android.hardware.camera.flash-autofocus.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- This is the standard set of features for a camera with a flash. Note
+ that this currently requires having auto-focus as well. -->
+<permissions>
+ <feature name="android.hardware.camera" />
+ <feature name="android.hardware.camera.autofocus" />
+ <feature name="android.hardware.camera.flash" />
+</permissions>
diff --git a/data/etc/android.hardware.sensor.light.xml b/data/etc/android.hardware.sensor.light.xml
new file mode 100644
index 0000000..78b0fec
--- /dev/null
+++ b/data/etc/android.hardware.sensor.light.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Feature for devices with an ambient light sensor. -->
+<permissions>
+ <feature name="android.hardware.sensor.light" />
+</permissions>
diff --git a/data/etc/android.hardware.sensor.proximity.xml b/data/etc/android.hardware.sensor.proximity.xml
new file mode 100644
index 0000000..d1948de
--- /dev/null
+++ b/data/etc/android.hardware.sensor.proximity.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Feature for devices with a proximity sensor. -->
+<permissions>
+ <feature name="android.hardware.sensor.proximity" />
+</permissions>
diff --git a/data/etc/android.hardware.telephony.cdma.xml b/data/etc/android.hardware.telephony.cdma.xml
new file mode 100644
index 0000000..72e0485
--- /dev/null
+++ b/data/etc/android.hardware.telephony.cdma.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- This is the standard set of features for a CDMA phone. -->
+<permissions>
+ <feature name="android.hardware.telephony" />
+ <feature name="android.hardware.telephony.cdma" />
+</permissions>
diff --git a/data/etc/android.hardware.telephony.gsm.xml b/data/etc/android.hardware.telephony.gsm.xml
new file mode 100644
index 0000000..ffde433
--- /dev/null
+++ b/data/etc/android.hardware.telephony.gsm.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- This is the standard set of features for a GSM phone. -->
+<permissions>
+ <feature name="android.hardware.telephony" />
+ <feature name="android.hardware.telephony.gsm" />
+</permissions>
diff --git a/data/etc/required_hardware.xml b/data/etc/required_hardware.xml
new file mode 100644
index 0000000..896a148
--- /dev/null
+++ b/data/etc/required_hardware.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- These are the hardware features that all devices must possess.
+ These are always added for you by the build system, you do not need
+ to add them yourself. -->
+<permissions>
+ <feature name="android.hardware.sensor.compass" />
+ <feature name="android.hardware.sensor.accelerometer" />
+ <feature name="android.hardware.bluetooth" />
+ <feature name="android.hardware.wifi" />
+</permissions>
diff --git a/docs/html/guide/topics/resources/resources-i18n.jd b/docs/html/guide/topics/resources/resources-i18n.jd
index 85b89d1..ff9579f 100755
--- a/docs/html/guide/topics/resources/resources-i18n.jd
+++ b/docs/html/guide/topics/resources/resources-i18n.jd
@@ -441,7 +441,7 @@
<pre>
MyApp/
res/
- drawable-en-rUS-large-long-port-mdpi-finger-keysexposed-qwerty-dpad-480x320/
+ drawable-en-rUS-large-long-port-mdpi-finger-keysexposed-qwerty-navexposed-dpad-480x320/
</pre>
<p>More typically, you will only specify a few specific configuration options. You may drop any of the values from the
@@ -575,6 +575,14 @@
<td><code>nokeys</code>, <code>qwerty</code>, <code>12key</code> </td>
</tr>
<tr>
+ <td>Whether the navigation keys are available to the user</td>
+ <td><p><code>navexposed</code>, <code>navhidden</code>
+ </p><p>
+ If the hardware's navigation keys are currently available to
+ the user, the navexposed resources will be used; if they are not
+ available (such as behind a closed lid), navhidden will be used.</p></td>
+ </tr>
+ <tr>
<td>Primary non-touchscreen<br />
navigation method</td>
<td><code>nonav</code>, <code>dpad</code>, <code>trackball</code>, <code>wheel</code> </td>
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 3266f1e..c6f57d4 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -36,7 +36,6 @@
private Drawable mCurrDrawable;
private int mAlpha = 0xFF;
private ColorFilter mColorFilter;
- private boolean mDither = DEFAULT_DITHER;
private int mCurIndex = -1;
private boolean mMutated;
@@ -83,10 +82,10 @@
@Override
public void setDither(boolean dither) {
- if (mDither != dither) {
- mDither = dither;
+ if (mDrawableContainerState.mDither != dither) {
+ mDrawableContainerState.mDither = dither;
if (mCurrDrawable != null) {
- mCurrDrawable.setDither(mDither);
+ mCurrDrawable.setDither(mDrawableContainerState.mDither);
}
}
}
@@ -212,7 +211,7 @@
if (d != null) {
d.setVisible(isVisible(), true);
d.setAlpha(mAlpha);
- d.setDither(mDither);
+ d.setDither(mDrawableContainerState.mDither);
d.setColorFilter(mColorFilter);
d.setState(getState());
d.setLevel(getLevel());
@@ -285,6 +284,8 @@
boolean mCanConstantState;
boolean mPaddingChecked = false;
+
+ boolean mDither = DEFAULT_DITHER;
DrawableContainerState(DrawableContainerState orig, DrawableContainer owner,
Resources res) {
@@ -323,6 +324,8 @@
mOpacity = orig.mOpacity;
mHaveStateful = orig.mHaveStateful;
mStateful = orig.mStateful;
+
+ mDither = orig.mDither;
} else {
mDrawables = new Drawable[10];
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 89db4fa..d35c5e3 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -140,6 +140,8 @@
native void nScriptSetTimeZone(int script, byte[] timeZone);
native void nScriptSetType(int type, boolean writable, String name, int slot);
native void nScriptSetRoot(boolean isRoot);
+ native void nScriptSetInvokable(String name, int slot);
+ native void nScriptInvoke(int id, int slot);
native void nScriptCBegin();
native void nScriptCSetScript(byte[] script, int offset, int length);
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index a402471..35791a3 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -25,6 +25,22 @@
boolean mIsRoot;
Type[] mTypes;
boolean[] mWritable;
+ Invokable[] mInvokables;
+
+ public static class Invokable {
+ RenderScript mRS;
+ Script mScript;
+ int mSlot;
+ String mName;
+
+ Invokable() {
+ mSlot = -1;
+ }
+
+ public void execute() {
+ mRS.nScriptInvoke(mScript.mID, mSlot);
+ }
+ }
Script(int id, RenderScript rs) {
super(rs);
@@ -61,12 +77,15 @@
Type[] mTypes;
String[] mNames;
boolean[] mWritable;
+ int mInvokableCount = 0;
+ Invokable[] mInvokables;
Builder(RenderScript rs) {
mRS = rs;
mTypes = new Type[MAX_SLOT];
mNames = new String[MAX_SLOT];
mWritable = new boolean[MAX_SLOT];
+ mInvokables = new Invokable[MAX_SLOT];
}
public void setType(Type t, int slot) {
@@ -79,6 +98,15 @@
mNames[slot] = name;
}
+ public Invokable addInvokable(String func) {
+ Invokable i = new Invokable();
+ i.mName = func;
+ i.mRS = mRS;
+ i.mSlot = mInvokableCount;
+ mInvokables[mInvokableCount++] = i;
+ return i;
+ }
+
public void setType(boolean writable, int slot) {
mWritable[slot] = writable;
}
@@ -90,11 +118,20 @@
mRS.nScriptSetType(mTypes[ct].mID, mWritable[ct], mNames[ct], ct);
}
}
+ for(int ct=0; ct < mInvokableCount; ct++) {
+ mRS.nScriptSetInvokable(mInvokables[ct].mName, ct);
+ }
}
void transferObject(Script s) {
s.mIsRoot = mIsRoot;
s.mTypes = mTypes;
+ s.mInvokables = new Invokable[mInvokableCount];
+ for(int ct=0; ct < mInvokableCount; ct++) {
+ s.mInvokables[ct] = mInvokables[ct];
+ s.mInvokables[ct].mScript = s;
+ }
+ s.mInvokables = null;
}
public void setRoot(boolean r) {
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 90b5958..eae6f24 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -891,6 +891,29 @@
}
static void
+nScriptSetInvoke(JNIEnv *_env, jobject _this, jstring _str, jint slot)
+{
+ RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+ LOG_API("nScriptSetInvoke, con(%p)", con);
+ const char* n = NULL;
+ if (_str) {
+ n = _env->GetStringUTFChars(_str, NULL);
+ }
+ rsScriptSetInvoke(con, n, slot);
+ if (n) {
+ _env->ReleaseStringUTFChars(_str, n);
+ }
+}
+
+static void
+nScriptInvoke(JNIEnv *_env, jobject _this, jint obj, jint slot)
+{
+ RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+ LOG_API("nScriptInvoke, con(%p), script(%p)", con, (void *)obj);
+ rsScriptInvoke(con, (RsScript)obj, slot);
+}
+
+static void
nScriptSetRoot(JNIEnv *_env, jobject _this, jboolean isRoot)
{
RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
@@ -1366,6 +1389,8 @@
{"nScriptSetTimeZone", "(I[B)V", (void*)nScriptSetTimeZone },
{"nScriptSetType", "(IZLjava/lang/String;I)V", (void*)nScriptSetType },
{"nScriptSetRoot", "(Z)V", (void*)nScriptSetRoot },
+{"nScriptSetInvokable", "(Ljava/lang/String;I)V", (void*)nScriptSetInvoke },
+{"nScriptInvoke", "(II)V", (void*)nScriptInvoke },
{"nScriptCBegin", "()V", (void*)nScriptCBegin },
{"nScriptCSetScript", "([BII)V", (void*)nScriptCSetScript },
diff --git a/include/media/stagefright/SoftwareRenderer.h b/include/media/stagefright/SoftwareRenderer.h
index b61858c..1545493 100644
--- a/include/media/stagefright/SoftwareRenderer.h
+++ b/include/media/stagefright/SoftwareRenderer.h
@@ -45,6 +45,7 @@
void renderCbYCrY(const void *data, size_t size);
void renderYUV420Planar(const void *data, size_t size);
+ void renderQCOMYUV420SemiPlanar(const void *data, size_t size);
OMX_COLOR_FORMATTYPE mColorFormat;
sp<ISurface> mISurface;
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index e524e2a..17ccad6 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -864,6 +864,13 @@
KEYSHIDDEN_SOFT = 0x0003,
};
+ enum {
+ MASK_NAVHIDDEN = 0x000c,
+ NAVHIDDEN_ANY = 0x0000,
+ NAVHIDDEN_NO = 0x0004,
+ NAVHIDDEN_YES = 0x0008,
+ };
+
union {
struct {
uint8_t keyboard;
@@ -1011,7 +1018,8 @@
if (orientation != o.orientation) diffs |= CONFIG_ORIENTATION;
if (density != o.density) diffs |= CONFIG_DENSITY;
if (touchscreen != o.touchscreen) diffs |= CONFIG_TOUCHSCREEN;
- if (((inputFlags^o.inputFlags)&MASK_KEYSHIDDEN) != 0) diffs |= CONFIG_KEYBOARD_HIDDEN;
+ if (((inputFlags^o.inputFlags)&(MASK_KEYSHIDDEN|MASK_NAVHIDDEN)) != 0)
+ diffs |= CONFIG_KEYBOARD_HIDDEN;
if (keyboard != o.keyboard) diffs |= CONFIG_KEYBOARD;
if (navigation != o.navigation) diffs |= CONFIG_NAVIGATION;
if (screenSize != o.screenSize) diffs |= CONFIG_SCREEN_SIZE;
@@ -1082,6 +1090,11 @@
if (!(o.inputFlags & MASK_KEYSHIDDEN)) return true;
}
+ if (((inputFlags^o.inputFlags) & MASK_NAVHIDDEN) != 0) {
+ if (!(inputFlags & MASK_NAVHIDDEN)) return false;
+ if (!(o.inputFlags & MASK_NAVHIDDEN)) return true;
+ }
+
if (keyboard != o.keyboard) {
if (!keyboard) return false;
if (!o.keyboard) return true;
@@ -1225,6 +1238,18 @@
}
}
+ const int navHidden = inputFlags & MASK_NAVHIDDEN;
+ const int oNavHidden = o.inputFlags & MASK_NAVHIDDEN;
+ if (navHidden != oNavHidden) {
+ const int reqNavHidden =
+ requested->inputFlags & MASK_NAVHIDDEN;
+ if (reqNavHidden) {
+
+ if (!navHidden) return false;
+ if (!oNavHidden) return true;
+ }
+ }
+
if ((keyboard != o.keyboard) && requested->keyboard) {
return (keyboard);
}
@@ -1332,6 +1357,12 @@
return false;
}
}
+ const int navHidden = inputFlags&MASK_NAVHIDDEN;
+ const int setNavHidden = settings.inputFlags&MASK_NAVHIDDEN;
+ if (setNavHidden != 0 && navHidden != 0
+ && navHidden != setNavHidden) {
+ return false;
+ }
if (settings.keyboard != 0 && keyboard != 0
&& keyboard != settings.keyboard) {
return false;
diff --git a/keystore/java/android/security/ServiceCommand.java b/keystore/java/android/security/ServiceCommand.java
index ee80014..9923011 100644
--- a/keystore/java/android/security/ServiceCommand.java
+++ b/keystore/java/android/security/ServiceCommand.java
@@ -49,8 +49,6 @@
public static final int BUFFER_LENGTH = 4096;
- private static final boolean DBG = true;
-
private String mServiceName;
private String mTag;
private InputStream mIn;
@@ -61,7 +59,6 @@
if (mSocket != null) {
return true;
}
- if (DBG) Log.d(mTag, "connecting...");
try {
mSocket = new LocalSocket();
@@ -80,7 +77,6 @@
}
private void disconnect() {
- if (DBG) Log.d(mTag,"disconnecting...");
try {
if (mSocket != null) mSocket.close();
} catch (IOException ex) { }
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 4f7500f..add358b 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -2069,7 +2069,7 @@
}
}
-AudioFlinger::PlaybackThread::TrackBase::~TrackBase()
+AudioFlinger::ThreadBase::TrackBase::~TrackBase()
{
if (mCblk) {
mCblk->~audio_track_cblk_t(); // destroy our shared-structure.
@@ -2081,7 +2081,7 @@
mClient.clear();
}
-void AudioFlinger::PlaybackThread::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
{
buffer->raw = 0;
mFrameCount = buffer->frameCount;
@@ -2089,7 +2089,7 @@
buffer->frameCount = 0;
}
-bool AudioFlinger::PlaybackThread::TrackBase::step() {
+bool AudioFlinger::ThreadBase::TrackBase::step() {
bool result;
audio_track_cblk_t* cblk = this->cblk();
@@ -2101,7 +2101,7 @@
return result;
}
-void AudioFlinger::PlaybackThread::TrackBase::reset() {
+void AudioFlinger::ThreadBase::TrackBase::reset() {
audio_track_cblk_t* cblk = this->cblk();
cblk->user = 0;
@@ -2112,20 +2112,20 @@
LOGV("TrackBase::reset");
}
-sp<IMemory> AudioFlinger::PlaybackThread::TrackBase::getCblk() const
+sp<IMemory> AudioFlinger::ThreadBase::TrackBase::getCblk() const
{
return mCblkMemory;
}
-int AudioFlinger::PlaybackThread::TrackBase::sampleRate() const {
+int AudioFlinger::ThreadBase::TrackBase::sampleRate() const {
return (int)mCblk->sampleRate;
}
-int AudioFlinger::PlaybackThread::TrackBase::channelCount() const {
+int AudioFlinger::ThreadBase::TrackBase::channelCount() const {
return (int)mCblk->channels;
}
-void* AudioFlinger::PlaybackThread::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
+void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const {
audio_track_cblk_t* cblk = this->cblk();
int8_t *bufferStart = (int8_t *)mBuffer + (offset-cblk->serverBase)*cblk->frameSize;
int8_t *bufferEnd = bufferStart + frames * cblk->frameSize;
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index ac2e738..87ad97c 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -297,6 +297,16 @@
param const char * name
}
+ScriptSetInvoke {
+ param const char * name
+ param uint32_t slot
+ }
+
+ScriptInvoke {
+ param RsScript s
+ param uint32_t slot
+ }
+
ScriptSetRoot {
param bool isRoot
}
diff --git a/libs/rs/rsScript.cpp b/libs/rs/rsScript.cpp
index fde31a1..99a085d 100644
--- a/libs/rs/rsScript.cpp
+++ b/libs/rs/rsScript.cpp
@@ -27,6 +27,8 @@
mEnviroment.mClearColor[2] = 0;
mEnviroment.mClearColor[3] = 1;
mEnviroment.mClearDepth = 1;
+ mEnviroment.mClearStencil = 0;
+ mEnviroment.mIsRoot = false;
}
Script::~Script()
@@ -83,10 +85,23 @@
}
}
+void rsi_ScriptSetInvoke(Context *rsc, const char *name, uint32_t slot)
+{
+ ScriptCState *ss = &rsc->mScriptC;
+ ss->mInvokableNames[slot] = name;
+}
+
+void rsi_ScriptInvoke(Context *rsc, RsScript vs, uint32_t slot)
+{
+ Script *s = static_cast<Script *>(vs);
+ s->mEnviroment.mInvokables[slot]();
+}
+
+
void rsi_ScriptSetRoot(Context * rsc, bool isRoot)
{
ScriptCState *ss = &rsc->mScriptC;
- ss->mEnviroment.mIsRoot = isRoot;
+ ss->mScript->mEnviroment.mIsRoot = isRoot;
}
diff --git a/libs/rs/rsScript.h b/libs/rs/rsScript.h
index 60f83a6..e40531e 100644
--- a/libs/rs/rsScript.h
+++ b/libs/rs/rsScript.h
@@ -34,6 +34,7 @@
class Script : public ObjectBase
{
public:
+ typedef void (* InvokeFunc_t)(void);
Script();
virtual ~Script();
@@ -52,17 +53,22 @@
ObjectBaseRef<ProgramFragment> mFragment;
//ObjectBaseRef<ProgramRaster> mRaster;
ObjectBaseRef<ProgramFragmentStore> mFragmentStore;
-
+ InvokeFunc_t mInvokables[MAX_SCRIPT_BANKS];
+ const char * mScriptText;
+ uint32_t mScriptTextLength;
};
Enviroment_t mEnviroment;
uint32_t mCounstantBufferCount;
+
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 8230cbc..108ae5a 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -82,36 +82,27 @@
ScriptCState::ScriptCState()
{
+ mScript = NULL;
clear();
}
ScriptCState::~ScriptCState()
{
- if (mAccScript) {
- accDeleteScript(mAccScript);
- }
+ delete mScript;
+ mScript = NULL;
}
void ScriptCState::clear()
{
- memset(&mProgram, 0, sizeof(mProgram));
-
for (uint32_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
mConstantBufferTypes[ct].clear();
mSlotNames[ct].setTo("");
+ mInvokableNames[ct].setTo("");
mSlotWritable[ct] = false;
}
- memset(&mEnviroment, 0, sizeof(mEnviroment));
- mEnviroment.mClearColor[0] = 0;
- mEnviroment.mClearColor[1] = 0;
- mEnviroment.mClearColor[2] = 0;
- mEnviroment.mClearColor[3] = 1;
- mEnviroment.mClearDepth = 1;
- mEnviroment.mClearStencil = 0;
- mEnviroment.mIsRoot = false;
-
- mAccScript = NULL;
+ delete mScript;
+ mScript = new ScriptC();
mInt32Defines.clear();
mFloatDefines.clear();
@@ -127,9 +118,9 @@
return NULL;
}
-void ScriptCState::runCompiler(Context *rsc)
+void ScriptCState::runCompiler(Context *rsc, ScriptC *s)
{
- mAccScript = accCreateScript();
+ s->mAccScript = accCreateScript();
String8 tmp;
rsc->appendNameDefines(&tmp);
@@ -139,44 +130,51 @@
appendTypes(&tmp);
tmp.append("#line 1\n");
- const char* scriptSource[] = {tmp.string(), mProgram.mScriptText};
- int scriptLength[] = {tmp.length(), mProgram.mScriptTextLength} ;
- accScriptSource(mAccScript, sizeof(scriptLength) / sizeof(int), scriptSource, scriptLength);
- accRegisterSymbolCallback(mAccScript, symbolLookup, NULL);
- accCompileScript(mAccScript);
- accGetScriptLabel(mAccScript, "main", (ACCvoid**) &mProgram.mScript);
- accGetScriptLabel(mAccScript, "init", (ACCvoid**) &mProgram.mInit);
- rsAssert(mProgram.mScript);
+ const char* scriptSource[] = {tmp.string(), s->mEnviroment.mScriptText};
+ int scriptLength[] = {tmp.length(), s->mEnviroment.mScriptTextLength} ;
+ accScriptSource(s->mAccScript, sizeof(scriptLength) / sizeof(int), scriptSource, scriptLength);
+ accRegisterSymbolCallback(s->mAccScript, symbolLookup, NULL);
+ accCompileScript(s->mAccScript);
+ accGetScriptLabel(s->mAccScript, "main", (ACCvoid**) &s->mProgram.mScript);
+ accGetScriptLabel(s->mAccScript, "init", (ACCvoid**) &s->mProgram.mInit);
+ rsAssert(s->mProgram.mScript);
- if (!mProgram.mScript) {
+ if (!s->mProgram.mScript) {
ACCchar buf[4096];
ACCsizei len;
- accGetScriptInfoLog(mAccScript, sizeof(buf), &len, buf);
+ accGetScriptInfoLog(s->mAccScript, sizeof(buf), &len, buf);
LOGE(buf);
}
- if (mProgram.mInit) {
- mProgram.mInit();
+ if (s->mProgram.mInit) {
+ s->mProgram.mInit();
}
for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
if (mSlotNames[ct].length() > 0) {
- accGetScriptLabel(mAccScript,
+ accGetScriptLabel(s->mAccScript,
mSlotNames[ct].string(),
- (ACCvoid**) &mProgram.mSlotPointers[ct]);
- LOGE("var %s %p", mSlotNames[ct].string(), mProgram.mSlotPointers[ct]);
+ (ACCvoid**) &s->mProgram.mSlotPointers[ct]);
}
}
- mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
- mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
- mEnviroment.mFragmentStore.set(rsc->getDefaultProgramFragmentStore());
+ for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
+ if (mInvokableNames[ct].length() > 0) {
+ accGetScriptLabel(s->mAccScript,
+ mInvokableNames[ct].string(),
+ (ACCvoid**) &s->mEnviroment.mInvokables[ct]);
+ }
+ }
- if (mProgram.mScript) {
+ s->mEnviroment.mFragment.set(rsc->getDefaultProgramFragment());
+ s->mEnviroment.mVertex.set(rsc->getDefaultProgramVertex());
+ s->mEnviroment.mFragmentStore.set(rsc->getDefaultProgramFragmentStore());
+
+ if (s->mProgram.mScript) {
const static int pragmaMax = 16;
ACCsizei pragmaCount;
ACCchar * str[pragmaMax];
- accGetPragmas(mAccScript, &pragmaCount, pragmaMax, &str[0]);
+ accGetPragmas(s->mAccScript, &pragmaCount, pragmaMax, &str[0]);
for (int ct=0; ct < pragmaCount; ct+=2) {
if (!strcmp(str[ct], "version")) {
@@ -188,12 +186,12 @@
continue;
}
if (!strcmp(str[ct+1], "parent")) {
- mEnviroment.mVertex.clear();
+ s->mEnviroment.mVertex.clear();
continue;
}
ProgramVertex * pv = (ProgramVertex *)rsc->lookupName(str[ct+1]);
if (pv != NULL) {
- mEnviroment.mVertex.set(pv);
+ s->mEnviroment.mVertex.set(pv);
continue;
}
LOGE("Unreconized value %s passed to stateVertex", str[ct+1]);
@@ -208,12 +206,12 @@
continue;
}
if (!strcmp(str[ct+1], "parent")) {
- mEnviroment.mFragment.clear();
+ s->mEnviroment.mFragment.clear();
continue;
}
ProgramFragment * pf = (ProgramFragment *)rsc->lookupName(str[ct+1]);
if (pf != NULL) {
- mEnviroment.mFragment.set(pf);
+ s->mEnviroment.mFragment.set(pf);
continue;
}
LOGE("Unreconized value %s passed to stateFragment", str[ct+1]);
@@ -224,13 +222,13 @@
continue;
}
if (!strcmp(str[ct+1], "parent")) {
- mEnviroment.mFragmentStore.clear();
+ s->mEnviroment.mFragmentStore.clear();
continue;
}
ProgramFragmentStore * pfs =
(ProgramFragmentStore *)rsc->lookupName(str[ct+1]);
if (pfs != NULL) {
- mEnviroment.mFragmentStore.set(pfs);
+ s->mEnviroment.mFragmentStore.set(pfs);
continue;
}
LOGE("Unreconized value %s passed to stateFragmentStore", str[ct+1]);
@@ -351,33 +349,6 @@
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 ");
- tmp.append(mSlotNames[ct]);
- tmp.append("_");
- tmp.append(c->getComponentName());
- switch (c->getType()) {
- case Component::FLOAT:
- tmp.append(" loadF(");
- break;
- case Component::SIGNED:
- sprintf(buf, " loadI%i(", c->getBits());
- tmp.append(buf);
- break;
- case Component::UNSIGNED:
- sprintf(buf, " loadU%i(", c->getBits());
- tmp.append(buf);
- break;
- }
- sprintf(buf, "%i, %i)\n", ct, ct2);
- tmp.append(buf);
-
- LOGD(tmp);
- str->append(tmp);
- }
-#endif
}
}
}
@@ -394,15 +365,16 @@
void rsi_ScriptCSetScript(Context * rsc, void *vp)
{
- ScriptCState *ss = &rsc->mScriptC;
- ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp);
+ rsAssert(0);
+ //ScriptCState *ss = &rsc->mScriptC;
+ //ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp);
}
void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len)
{
ScriptCState *ss = &rsc->mScriptC;
- ss->mProgram.mScriptText = text;
- ss->mProgram.mScriptTextLength = len;
+ ss->mScript->mEnviroment.mScriptText = text;
+ ss->mScript->mEnviroment.mScriptTextLength = len;
}
@@ -410,14 +382,11 @@
{
ScriptCState *ss = &rsc->mScriptC;
- ss->runCompiler(rsc);
+ ScriptC *s = ss->mScript;
+ ss->mScript = NULL;
- ScriptC *s = new ScriptC();
+ ss->runCompiler(rsc, s);
s->incUserRef();
- s->mAccScript = ss->mAccScript;
- ss->mAccScript = NULL;
- s->mEnviroment = ss->mEnviroment;
- s->mProgram = ss->mProgram;
for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
s->mTypes[ct].set(ss->mConstantBufferTypes[ct].get());
s->mSlotNames[ct] = ss->mSlotNames[ct];
diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h
index 8aa99ef..355f0c3 100644
--- a/libs/rs/rsScriptC.h
+++ b/libs/rs/rsScriptC.h
@@ -67,17 +67,15 @@
ScriptCState();
~ScriptCState();
- ACCscript* mAccScript;
-
- ScriptC::Program_t mProgram;
- Script::Enviroment_t mEnviroment;
+ ScriptC *mScript;
ObjectBaseRef<const Type> mConstantBufferTypes[MAX_SCRIPT_BANKS];
String8 mSlotNames[MAX_SCRIPT_BANKS];
bool mSlotWritable[MAX_SCRIPT_BANKS];
+ String8 mInvokableNames[MAX_SCRIPT_BANKS];
void clear();
- void runCompiler(Context *rsc);
+ void runCompiler(Context *rsc, ScriptC *s);
void appendVarDefines(String8 *str);
void appendTypes(String8 *str);
diff --git a/libs/surfaceflinger/BlurFilter.cpp b/libs/surfaceflinger/BlurFilter.cpp
index 5dc0ba0..1ffbd5b 100644
--- a/libs/surfaceflinger/BlurFilter.cpp
+++ b/libs/surfaceflinger/BlurFilter.cpp
@@ -111,6 +111,50 @@
}
};
+template <int FACTOR = 0>
+struct BlurColor888X
+{
+ typedef uint32_t type;
+ int r, g, b;
+ inline BlurColor888X() { }
+ inline BlurColor888X(uint32_t v) {
+ v = BLUR_RGBA_TO_HOST(v);
+ r = v & 0xFF;
+ g = (v >> 8) & 0xFF;
+ b = (v >> 16) & 0xFF;
+ }
+ inline void clear() { r=g=b=0; }
+ inline uint32_t to(int shift, int last, int dither) const {
+ int R = r;
+ int G = g;
+ int B = b;
+ if (UNLIKELY(last)) {
+ if (FACTOR>0) {
+ int L = (R+G+G+B)>>2;
+ R += ((L - R) * FACTOR) >> 8;
+ G += ((L - G) * FACTOR) >> 8;
+ B += ((L - B) * FACTOR) >> 8;
+ }
+ }
+ R >>= shift;
+ G >>= shift;
+ B >>= shift;
+ return BLUR_HOST_TO_RGBA((0xFF<<24) | (B<<16) | (G<<8) | R);
+ }
+ inline BlurColor888X& operator += (const BlurColor888X& rhs) {
+ r += rhs.r;
+ g += rhs.g;
+ b += rhs.b;
+ return *this;
+ }
+ inline BlurColor888X& operator -= (const BlurColor888X& rhs) {
+ r -= rhs.r;
+ g -= rhs.g;
+ b -= rhs.b;
+ return *this;
+ }
+};
+
struct BlurGray565
{
typedef uint16_t type;
@@ -316,7 +360,13 @@
int kernelSizeUser,
int repeat)
{
- return blurFilter< BlurColor565<0x80> >(image, image, kernelSizeUser, repeat);
+ status_t err = BAD_VALUE;
+ if (image->format == GGL_PIXEL_FORMAT_RGB_565) {
+ err = blurFilter< BlurColor565<0x80> >(image, image, kernelSizeUser, repeat);
+ } else if (image->format == GGL_PIXEL_FORMAT_RGBX_8888) {
+ err = blurFilter< BlurColor888X<0x80> >(image, image, kernelSizeUser, repeat);
+ }
+ return err;
}
} // namespace android
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index d893f0a..cc913cbd 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -174,6 +174,13 @@
surface = eglCreateWindowSurface(display, config, mNativeWindow.get(), NULL);
+ if (mFlags & UPDATE_ON_DEMAND) {
+ // if we have update on demand, we definitely don't need to
+ // preserve the backbuffer, which is usually costly.
+ eglSurfaceAttrib(display, surface,
+ EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);
+ }
+
if (eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &dummy) == EGL_TRUE) {
if (dummy == EGL_BUFFER_PRESERVED) {
mFlags |= BUFFER_PRESERVED;
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index 1e7f1e6..7387c85 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -303,7 +303,6 @@
// Index of the back buffer
const bool backbufferChanged = (front.w != temp.w) || (front.h != temp.h);
-
if (backbufferChanged) {
// the size changed, we need to ask our client to request a new buffer
LOGD_IF(DEBUG_RESIZE,
@@ -318,17 +317,6 @@
// buffer, it'll get the new size.
setDrawingSize(temp.w, temp.h);
- // all buffers need reallocation
- lcblk->reallocate();
-
- // recompute the visible region
- // FIXME: ideally we would do that only when we have received
- // a buffer of the right size
- flags |= Layer::eVisibleRegion;
- this->contentDirty = true;
-
-#if 0
- // FIXME: handle freeze lock
// we're being resized and there is a freeze display request,
// acquire a freeze lock, so that the screen stays put
// until we've redrawn at the new size; this is to avoid
@@ -340,7 +328,12 @@
mFreezeLock = mFlinger->getFreezeLock();
}
}
-#endif
+
+ // recompute the visible region
+ flags |= Layer::eVisibleRegion;
+ this->contentDirty = true;
+ // all buffers need reallocation
+ lcblk->reallocate();
}
if (temp.sequence != front.sequence) {
@@ -382,6 +375,13 @@
const Region dirty(lcblk->getDirtyRegion(buf));
mPostedDirtyRegion = dirty.intersect( newFrontBuffer->getBounds() );
+
+ const Layer::State& front(drawingState());
+ if (newFrontBuffer->getWidth() == front.w &&
+ newFrontBuffer->getHeight() ==front.h) {
+ mFreezeLock.clear();
+ }
+
// FIXME: signal an event if we have more buffers waiting
// mFlinger->signalEvent();
diff --git a/libs/surfaceflinger/LayerBlur.cpp b/libs/surfaceflinger/LayerBlur.cpp
index e14f35b..0ef663f 100644
--- a/libs/surfaceflinger/LayerBlur.cpp
+++ b/libs/surfaceflinger/LayerBlur.cpp
@@ -40,9 +40,9 @@
LayerBlur::LayerBlur(SurfaceFlinger* flinger, DisplayID display,
const sp<Client>& client, int32_t i)
- : LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
- mRefreshCache(true), mCacheAge(0), mTextureName(-1U),
- mWidthScale(1.0f), mHeightScale(1.0f)
+: LayerBaseClient(flinger, display, client, i), mCacheDirty(true),
+mRefreshCache(true), mCacheAge(0), mTextureName(-1U),
+mWidthScale(1.0f), mHeightScale(1.0f)
{
}
@@ -136,6 +136,13 @@
// create the texture name the first time
// can't do that in the ctor, because it runs in another thread.
glGenTextures(1, &mTextureName);
+ glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, &mReadFormat);
+ glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, &mReadType);
+ if (mReadFormat != GL_RGB || mReadType != GL_UNSIGNED_SHORT_5_6_5) {
+ mReadFormat = GL_RGBA;
+ mReadType = GL_UNSIGNED_BYTE;
+ mBlurFormat = GGL_PIXEL_FORMAT_RGBX_8888;
+ }
}
Region::const_iterator it = clip.begin();
@@ -143,33 +150,39 @@
if (it != end) {
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, mTextureName);
-
+
if (mRefreshCache) {
mRefreshCache = false;
mAutoRefreshPending = false;
-
- // allocate enough memory for 4-bytes (2 pixels) aligned data
- const int32_t s = (w + 1) & ~1;
- uint16_t* const pixels = (uint16_t*)malloc(s*h*2);
+
+ int32_t pixelSize = 4;
+ int32_t s = w;
+ if (mReadType == GL_UNSIGNED_SHORT_5_6_5) {
+ // allocate enough memory for 4-bytes (2 pixels) aligned data
+ s = (w + 1) & ~1;
+ pixelSize = 2;
+ }
+
+ uint16_t* const pixels = (uint16_t*)malloc(s*h*pixelSize);
// This reads the frame-buffer, so a h/w GL would have to
// finish() its rendering first. we don't want to do that
// too often. Read data is 4-bytes aligned.
- glReadPixels(X, Y, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
-
+ glReadPixels(X, Y, w, h, mReadFormat, mReadType, pixels);
+
// blur that texture.
GGLSurface bl;
bl.version = sizeof(GGLSurface);
bl.width = w;
bl.height = h;
bl.stride = s;
- bl.format = GGL_PIXEL_FORMAT_RGB_565;
+ bl.format = mBlurFormat;
bl.data = (GGLubyte*)pixels;
blurFilter(&bl, 8, 2);
if (mFlags & (DisplayHardware::NPOT_EXTENSION)) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0,
- GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+ glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, w, h, 0,
+ mReadFormat, mReadType, pixels);
mWidthScale = 1.0f / w;
mHeightScale =-1.0f / h;
mYOffset = 0;
@@ -178,10 +191,10 @@
GLuint th = 1 << (31 - clz(h));
if (tw < w) tw <<= 1;
if (th < h) th <<= 1;
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tw, th, 0,
- GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
+ glTexImage2D(GL_TEXTURE_2D, 0, mReadFormat, tw, th, 0,
+ mReadFormat, mReadType, NULL);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h,
- GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
+ mReadFormat, mReadType, pixels);
mWidthScale = 1.0f / tw;
mHeightScale =-1.0f / th;
mYOffset = th-h;
@@ -189,7 +202,7 @@
free((void*)pixels);
}
-
+
const State& s = drawingState();
if (UNLIKELY(s.alpha < 0xFF)) {
const GGLfixed alpha = (s.alpha << 16)/255;
diff --git a/libs/surfaceflinger/LayerBlur.h b/libs/surfaceflinger/LayerBlur.h
index bf36ae4..2e9d7c6 100644
--- a/libs/surfaceflinger/LayerBlur.h
+++ b/libs/surfaceflinger/LayerBlur.h
@@ -59,6 +59,9 @@
mutable GLfloat mWidthScale;
mutable GLfloat mHeightScale;
mutable GLfloat mYOffset;
+ mutable GLint mReadFormat;
+ mutable GLint mReadType;
+ mutable uint32_t mBlurFormat;
};
// ---------------------------------------------------------------------------
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 38a897d..667571b 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -595,6 +595,7 @@
*overlayRef = new OverlayRef(mOverlayHandle, channel,
mWidth, mHeight, mFormat, mWidthStride, mHeightStride);
+ mLayer.mFlinger->signalEvent();
}
LayerBuffer::OverlaySource::~OverlaySource()
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 1dd644b..d6463a1 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -345,6 +345,9 @@
/**
* Adjusts the volume of a particular stream by one step in a direction.
+ * <p>
+ * This method should only be used by applications that replace the platform-wide
+ * management of audio settings or the main telephony application.
*
* @param streamType The stream type to adjust. One of {@link #STREAM_VOICE_CALL},
* {@link #STREAM_SYSTEM}, {@link #STREAM_RING}, {@link #STREAM_MUSIC} or
@@ -370,6 +373,9 @@
* active, it will have the highest priority regardless of if the in-call
* screen is showing. Another example, if music is playing in the background
* and a call is not active, the music stream will be adjusted.
+ * <p>
+ * This method should only be used by applications that replace the platform-wide
+ * management of audio settings or the main telephony application.
*
* @param direction The direction to adjust the volume. One of
* {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
@@ -391,6 +397,9 @@
/**
* Adjusts the volume of the most relevant stream, or the given fallback
* stream.
+ * <p>
+ * This method should only be used by applications that replace the platform-wide
+ * management of audio settings or the main telephony application.
*
* @param direction The direction to adjust the volume. One of
* {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
@@ -541,6 +550,9 @@
* <p>
* For a better user experience, applications MUST unmute a muted stream
* in onPause() and mute is again in onResume() if appropriate.
+ * <p>
+ * This method should only be used by applications that replace the platform-wide
+ * management of audio settings or the main telephony application.
*
* @param streamType The stream to be muted/unmuted.
* @param state The required mute state: true for mute ON, false for mute OFF
@@ -608,6 +620,9 @@
/**
* Sets the setting for when the vibrate type should vibrate.
+ * <p>
+ * This method should only be used by applications that replace the platform-wide
+ * management of audio settings or the main telephony application.
*
* @param vibrateType The type of vibrate. One of
* {@link #VIBRATE_TYPE_NOTIFICATION} or
@@ -630,6 +645,9 @@
/**
* Sets the speakerphone on or off.
+ * <p>
+ * This method should only be used by applications that replace the platform-wide
+ * management of audio settings or the main telephony application.
*
* @param on set <var>true</var> to turn on speakerphone;
* <var>false</var> to turn it off
@@ -660,6 +678,9 @@
/**
* Request use of Bluetooth SCO headset for communications.
+ * <p>
+ * This method should only be used by applications that replace the platform-wide
+ * management of audio settings or the main telephony application.
*
* @param on set <var>true</var> to use bluetooth SCO for communications;
* <var>false</var> to not use bluetooth SCO for communications
@@ -739,6 +760,9 @@
/**
* Sets the microphone mute on or off.
+ * <p>
+ * This method should only be used by applications that replace the platform-wide
+ * management of audio settings or the main telephony application.
*
* @param on set <var>true</var> to mute the microphone;
* <var>false</var> to turn mute off
@@ -758,6 +782,13 @@
/**
* Sets the audio mode.
+ * <p>
+ * The audio mode encompasses audio routing AND the behavior of
+ * the telephony layer. Therefore this method should only be used by applications that
+ * replace the platform-wide management of audio settings or the main telephony application.
+ * In particular, the {@link #MODE_IN_CALL} mode should only be used by the telephony
+ * application when it places a phone call, as it will cause signals from the radio layer
+ * to feed the platform mixer.
*
* @param mode the requested audio mode (NORMAL, RINGTONE, or IN_CALL).
* Informs the HAL about the current audio state so that
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index aba40b3..73b6483 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -16,8 +16,7 @@
package android.media;
-import android.util.Log;
-
+import java.io.IOException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -25,171 +24,102 @@
import java.util.Map;
/**
- * Wrapper for native Exif library
- * {@hide}
+ * This is a class for reading and writing Exif tags in a JPEG file.
*/
public class ExifInterface {
- private static final String TAG = "ExifInterface";
- private String mFilename;
-
- // Constants used for the Orientation Exif tag.
- public static final int ORIENTATION_UNDEFINED = 0;
- public static final int ORIENTATION_NORMAL = 1;
-
- // Constants used for white balance
- public static final int WHITEBALANCE_AUTO = 0;
- public static final int WHITEBALANCE_MANUAL = 1;
-
- // left right reversed mirror
- public static final int ORIENTATION_FLIP_HORIZONTAL = 2;
- public static final int ORIENTATION_ROTATE_180 = 3;
-
- // upside down mirror
- public static final int ORIENTATION_FLIP_VERTICAL = 4;
-
- // flipped about top-left <--> bottom-right axis
- public static final int ORIENTATION_TRANSPOSE = 5;
-
- // rotate 90 cw to right it
- public static final int ORIENTATION_ROTATE_90 = 6;
-
- // flipped about top-right <--> bottom-left axis
- public static final int ORIENTATION_TRANSVERSE = 7;
-
- // rotate 270 to right it
- public static final int ORIENTATION_ROTATE_270 = 8;
// The Exif tag names
public static final String TAG_ORIENTATION = "Orientation";
-
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";
public static final String TAG_IMAGE_WIDTH = "ImageWidth";
public static final String TAG_IMAGE_LENGTH = "ImageLength";
-
public static final String TAG_GPS_LATITUDE = "GPSLatitude";
public static final String TAG_GPS_LONGITUDE = "GPSLongitude";
-
public static final String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
public static final String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
public static final String TAG_WHITE_BALANCE = "WhiteBalance";
- private boolean mSavedAttributes = false;
- private boolean mHasThumbnail = false;
- private HashMap<String, String> mCachedAttributes = null;
+ // Constants used for the Orientation Exif tag.
+ public static final int ORIENTATION_UNDEFINED = 0;
+ public static final int ORIENTATION_NORMAL = 1;
+ public static final int ORIENTATION_FLIP_HORIZONTAL = 2; // left right reversed mirror
+ public static final int ORIENTATION_ROTATE_180 = 3;
+ public static final int ORIENTATION_FLIP_VERTICAL = 4; // upside down mirror
+ public static final int ORIENTATION_TRANSPOSE = 5; // flipped about top-left <--> bottom-right axis
+ public static final int ORIENTATION_ROTATE_90 = 6; // rotate 90 cw to right it
+ public static final int ORIENTATION_TRANSVERSE = 7; // flipped about top-right <--> bottom-left axis
+ public static final int ORIENTATION_ROTATE_270 = 8; // rotate 270 to right it
+
+ // Constants used for white balance
+ public static final int WHITEBALANCE_AUTO = 0;
+ public static final int WHITEBALANCE_MANUAL = 1;
static {
System.loadLibrary("exif");
}
- private static ExifInterface sExifObj = null;
- /**
- * Since the underlying jhead native code is not thread-safe,
- * ExifInterface should use singleton interface instead of public
- * constructor.
- */
- private static synchronized ExifInterface instance() {
- if (sExifObj == null) {
- sExifObj = new ExifInterface();
- }
+ private String mFilename;
+ private HashMap<String, String> mAttributes;
+ private boolean mHasThumbnail = false;
- return sExifObj;
+ // Because the underlying implementation (jhead) uses static variables,
+ // there can only be one user at a time for the native functions (and
+ // they cannot keep state in the native code across function calls). We
+ // use sLock the serialize the accesses.
+ private static Object sLock = new Object();
+
+ /**
+ * Reads Exif tags from the specified JPEG file.
+ */
+ public ExifInterface(String filename) throws IOException {
+ mFilename = filename;
+ loadAttributes();
}
/**
- * The following 3 static methods are handy routines for atomic operation
- * of underlying jhead library. It retrieves EXIF data and then release
- * ExifInterface immediately.
+ * Returns the value of the specified tag or {@code null} if there
+ * is no such tag in the file.
+ *
+ * @param tag the name of the tag.
*/
- public static synchronized HashMap<String, String> loadExifData(String filename) {
- ExifInterface exif = instance();
- HashMap<String, String> exifData = null;
- if (exif != null) {
- exif.setFilename(filename);
- exifData = exif.getAttributes();
- }
- return exifData;
- }
-
- public static synchronized void saveExifData(String filename, HashMap<String, String> exifData) {
- ExifInterface exif = instance();
- if (exif != null) {
- exif.setFilename(filename);
- exif.saveAttributes(exifData);
- }
- }
-
- public static synchronized byte[] getExifThumbnail(String filename) {
- ExifInterface exif = instance();
- if (exif != null) {
- exif.setFilename(filename);
- return exif.getThumbnail();
- }
- return null;
- }
-
- public void setFilename(String filename) {
- if (mFilename == null || !mFilename.equals(filename)) {
- mFilename = filename;
- mCachedAttributes = null;
- }
+ public String getAttribute(String tag) {
+ return mAttributes.get(tag);
}
/**
- * Given a HashMap of Exif tags and associated values, an Exif section in
- * the JPG file is created and loaded with the tag data. saveAttributes()
- * is expensive because it involves copying all the JPG data from one file
- * to another and deleting the old file and renaming the other. It's best
- * to collect all the attributes to write and make a single call rather
- * than multiple calls for each attribute. You must call "commitChanges()"
- * at some point to commit the changes.
+ * Set the value of the specified tag.
+ *
+ * @param tag the name of the tag.
+ * @param value the value of the tag.
*/
- public void saveAttributes(HashMap<String, String> attributes) {
- // format of string passed to native C code:
- // "attrCnt attr1=valueLen value1attr2=value2Len value2..."
- // example:
- // "4 attrPtr ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO"
- StringBuilder sb = new StringBuilder();
- int size = attributes.size();
- if (attributes.containsKey("hasThumbnail")) {
- --size;
- }
- sb.append(size + " ");
- for (Map.Entry<String, String> iter : attributes.entrySet()) {
- String key = iter.getKey();
- if (key.equals("hasThumbnail")) {
- // this is a fake attribute not saved as an exif tag
- continue;
- }
- String val = iter.getValue();
- sb.append(key + "=");
- sb.append(val.length() + " ");
- sb.append(val);
- }
- String s = sb.toString();
- saveAttributesNative(mFilename, s);
- commitChangesNative(mFilename);
- mSavedAttributes = true;
+ public void setAttribute(String tag, String value) {
+ mAttributes.put(tag, value);
}
/**
- * Returns a HashMap loaded with the Exif attributes of the file. The key
- * is the standard tag name and the value is the tag's value: e.g.
- * Model -> Nikon. Numeric values are returned as strings.
+ * Initialize mAttributes with the attributes from the file mFilename.
+ *
+ * mAttributes is a HashMap which stores the Exif attributes of the file.
+ * The key is the standard tag name and the value is the tag's value: e.g.
+ * Model -> Nikon. Numeric values are stored as strings.
+ *
+ * This function also initialize mHasThumbnail to indicate whether the
+ * file has a thumbnail inside.
*/
- public HashMap<String, String> getAttributes() {
- if (mCachedAttributes != null) {
- return mCachedAttributes;
- }
+ private void loadAttributes() {
// format of string passed from native C code:
// "attrCnt attr1=valueLen value1attr2=value2Len value2..."
// example:
// "4 attrPtr ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO"
- mCachedAttributes = new HashMap<String, String>();
+ mAttributes = new HashMap<String, String>();
- String attrStr = getAttributesNative(mFilename);
+ String attrStr;
+ synchronized (sLock) {
+ attrStr = getAttributesNative(mFilename);
+ }
// get count
int ptr = attrStr.indexOf(' ');
@@ -215,17 +145,78 @@
if (attrName.equals("hasThumbnail")) {
mHasThumbnail = attrValue.equalsIgnoreCase("true");
} else {
- mCachedAttributes.put(attrName, attrValue);
+ mAttributes.put(attrName, attrValue);
}
}
- return mCachedAttributes;
}
/**
- * Given a numerical white balance value, return a
- * human-readable string describing it.
+ * Save the tag data into the JPEG file. This is expensive because it involves
+ * copying all the JPG data from one file to another and deleting the old file
+ * and renaming the other. It's best to use {@link #setAttribute(String,String)} to set all
+ * attributes to write and make a single call rather than multiple calls for
+ * each attribute.
*/
- public static String whiteBalanceToString(int whitebalance) {
+ public void saveAttributes() throws IOException {
+ // format of string passed to native C code:
+ // "attrCnt attr1=valueLen value1attr2=value2Len value2..."
+ // example:
+ // "4 attrPtr ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO"
+ StringBuilder sb = new StringBuilder();
+ int size = mAttributes.size();
+ if (mAttributes.containsKey("hasThumbnail")) {
+ --size;
+ }
+ sb.append(size + " ");
+ for (Map.Entry<String, String> iter : mAttributes.entrySet()) {
+ String key = iter.getKey();
+ if (key.equals("hasThumbnail")) {
+ // this is a fake attribute not saved as an exif tag
+ continue;
+ }
+ String val = iter.getValue();
+ sb.append(key + "=");
+ sb.append(val.length() + " ");
+ sb.append(val);
+ }
+ String s = sb.toString();
+ synchronized (sLock) {
+ saveAttributesNative(mFilename, s);
+ commitChangesNative(mFilename);
+ }
+ }
+
+ /**
+ * Returns true if the JPEG file has a thumbnail.
+ */
+ public boolean hasThumbnail() {
+ return mHasThumbnail;
+ }
+
+ /**
+ * Returns the thumbnail inside the JPEG file, or {@code null} if there is no thumbnail.
+ */
+ public byte[] getThumbnail() {
+ synchronized (sLock) {
+ return getThumbnailNative(mFilename);
+ }
+ }
+
+ /**
+ * Returns a human-readable string describing the white balance value. Returns empty
+ * string if there is no white balance value or it is not recognized.
+ */
+ public String getWhiteBalanceString() {
+ String value = getAttribute(TAG_WHITE_BALANCE);
+ if (value == null) return "";
+
+ int whitebalance;
+ try {
+ whitebalance = Integer.parseInt(value);
+ } catch (NumberFormatException ex) {
+ return "";
+ }
+
switch (whitebalance) {
case WHITEBALANCE_AUTO:
return "Auto";
@@ -237,12 +228,21 @@
}
/**
- * Given a numerical orientation, return a human-readable string describing
- * the orientation.
+ * Returns a human-readable string describing the orientation value. Returns empty
+ * string if there is no orientation value or it it not recognized.
*/
- public static String orientationToString(int orientation) {
- // TODO: this function needs to be localized and use string resource ids
- // rather than strings
+ public String getOrientationString() {
+ // TODO: this function needs to be localized.
+ String value = getAttribute(TAG_ORIENTATION);
+ if (value == null) return "";
+
+ int orientation;
+ try {
+ orientation = Integer.parseInt(value);
+ } catch (NumberFormatException ex) {
+ return "";
+ }
+
String orientationString;
switch (orientation) {
case ORIENTATION_NORMAL:
@@ -277,48 +277,21 @@
}
/**
- * Copies the thumbnail data out of the filename and puts it in the Exif
- * data associated with the file used to create this object. You must call
- * "commitChanges()" at some point to commit the changes.
+ * Returns the latitude and longitude value in a float array. The first element is
+ * the latitude, and the second element is the longitude.
*/
- public boolean appendThumbnail(String thumbnailFileName) {
- if (!mSavedAttributes) {
- throw new RuntimeException("Must call saveAttributes "
- + "before calling appendThumbnail");
- }
- mHasThumbnail = appendThumbnailNative(mFilename, thumbnailFileName);
- return mHasThumbnail;
- }
-
- public boolean hasThumbnail() {
- if (!mSavedAttributes) {
- getAttributes();
- }
- return mHasThumbnail;
- }
-
- public byte[] getThumbnail() {
- return getThumbnailNative(mFilename);
- }
-
- public static float[] getLatLng(HashMap<String, String> exifData) {
- if (exifData == null) {
- return null;
- }
-
- String latValue = exifData.get(ExifInterface.TAG_GPS_LATITUDE);
- String latRef = exifData.get(ExifInterface.TAG_GPS_LATITUDE_REF);
- String lngValue = exifData.get(ExifInterface.TAG_GPS_LONGITUDE);
- String lngRef = exifData.get(ExifInterface.TAG_GPS_LONGITUDE_REF);
+ public float[] getLatLong() {
+ String latValue = mAttributes.get(ExifInterface.TAG_GPS_LATITUDE);
+ String latRef = mAttributes.get(ExifInterface.TAG_GPS_LATITUDE_REF);
+ String lngValue = mAttributes.get(ExifInterface.TAG_GPS_LONGITUDE);
+ String lngRef = mAttributes.get(ExifInterface.TAG_GPS_LONGITUDE_REF);
float[] latlng = null;
if (latValue != null && latRef != null
&& lngValue != null && lngRef != null) {
latlng = new float[2];
- latlng[0] = ExifInterface.convertRationalLatLonToFloat(
- latValue, latRef);
- latlng[1] = ExifInterface.convertRationalLatLonToFloat(
- lngValue, lngRef);
+ latlng[0] = convertRationalLatLonToFloat(latValue, latRef);
+ latlng[1] = convertRationalLatLonToFloat(lngValue, lngRef);
}
return latlng;
@@ -327,14 +300,12 @@
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);
+ /**
+ * Returns number of milliseconds since Jan. 1, 1970, midnight GMT.
+ * Returns -1 if the date time information if not available.
+ */
+ public long getDateTime() {
+ String dateTimeString = mAttributes.get(TAG_DATETIME);
if (dateTimeString == null) return -1;
ParsePosition pos = new ParsePosition(0);
@@ -347,7 +318,7 @@
}
}
- public static float convertRationalLatLonToFloat(
+ private static float convertRationalLatLonToFloat(
String rationalString, String ref) {
try {
String [] parts = rationalString.split(",");
@@ -377,42 +348,6 @@
}
}
- public static String convertRationalLatLonToDecimalString(
- String rationalString, String ref, boolean usePositiveNegative) {
- float result = convertRationalLatLonToFloat(rationalString, ref);
-
- String preliminaryResult = String.valueOf(result);
- if (usePositiveNegative) {
- String neg = (ref.equals("S") || ref.equals("E")) ? "-" : "";
- return neg + preliminaryResult;
- } else {
- return preliminaryResult + String.valueOf((char) 186) + " "
- + ref;
- }
- }
-
- public static String makeLatLongString(double d) {
- d = Math.abs(d);
-
- int degrees = (int) d;
-
- double remainder = d - degrees;
- int minutes = (int) (remainder * 60D);
- // really seconds * 1000
- int seconds = (int) (((remainder * 60D) - minutes) * 60D * 1000D);
-
- String retVal = degrees + "/1," + minutes + "/1," + seconds + "/1000";
- return retVal;
- }
-
- public static String makeLatStringRef(double lat) {
- return lat >= 0D ? "N" : "S";
- }
-
- public static String makeLonStringRef(double lon) {
- return lon >= 0D ? "W" : "E";
- }
-
private native boolean appendThumbnailNative(String fileName,
String thumbnailFileName);
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index f6d30e0..d9127e7 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -719,16 +719,20 @@
values.put(Audio.Media.IS_MUSIC, music);
values.put(Audio.Media.IS_PODCAST, podcasts);
} else if (mFileType == MediaFile.FILE_TYPE_JPEG) {
- HashMap<String, String> exifData =
- ExifInterface.loadExifData(entry.mPath);
- if (exifData != null) {
- float[] latlng = ExifInterface.getLatLng(exifData);
+ ExifInterface exif = null;
+ try {
+ exif = new ExifInterface(entry.mPath);
+ } catch (IOException ex) {
+ // exif is null
+ }
+ if (exif != null) {
+ float[] latlng = exif.getLatLong();
if (latlng != null) {
values.put(Images.Media.LATITUDE, latlng[0]);
values.put(Images.Media.LONGITUDE, latlng[1]);
}
- long time = ExifInterface.getDateTime(exifData);
+ long time = exif.getDateTime();
if (time != -1) {
values.put(Images.Media.DATE_TAKEN, time);
}
diff --git a/media/libstagefright/omx/SoftwareRenderer.cpp b/media/libstagefright/omx/SoftwareRenderer.cpp
index a1c478f..4ed6869 100644
--- a/media/libstagefright/omx/SoftwareRenderer.cpp
+++ b/media/libstagefright/omx/SoftwareRenderer.cpp
@@ -65,6 +65,8 @@
void SoftwareRenderer::render(
const void *data, size_t size, void *platformPrivate) {
+ static const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
+
switch (mColorFormat) {
case OMX_COLOR_FormatYUV420Planar:
return renderYUV420Planar(data, size);
@@ -72,6 +74,9 @@
case OMX_COLOR_FormatCbYCrY:
return renderCbYCrY(data, size);
+ case OMX_QCOM_COLOR_FormatYVU420SemiPlanar:
+ return renderQCOMYUV420SemiPlanar(data, size);
+
default:
{
LOGW("Cannot render color format %ld", mColorFormat);
@@ -242,6 +247,76 @@
mIndex = 1 - mIndex;
}
+void SoftwareRenderer::renderQCOMYUV420SemiPlanar(
+ const void *data, size_t size) {
+ if (size != (mDecodedHeight * mDecodedWidth * 3) / 2) {
+ LOGE("size is %d, expected %d",
+ size, (mDecodedHeight * mDecodedWidth * 3) / 2);
+ }
+ CHECK(size >= (mDecodedWidth * mDecodedHeight * 3) / 2);
+
+ uint8_t *kAdjustedClip = initClip();
+
+ size_t offset = mIndex * mFrameSize;
+
+ void *dst = (uint8_t *)mMemoryHeap->getBase() + offset;
+
+ uint32_t *dst_ptr = (uint32_t *)dst;
+
+ const uint8_t *src_y = (const uint8_t *)data;
+
+ const uint8_t *src_u =
+ (const uint8_t *)src_y + mDecodedWidth * mDecodedHeight;
+
+ for (size_t y = 0; y < mDecodedHeight; ++y) {
+ for (size_t x = 0; x < mDecodedWidth; x += 2) {
+ signed y1 = (signed)src_y[x] - 16;
+ signed y2 = (signed)src_y[x + 1] - 16;
+
+ signed u = (signed)src_u[x & ~1] - 128;
+ signed v = (signed)src_u[(x & ~1) + 1] - 128;
+
+ signed u_b = u * 517;
+ signed u_g = -u * 100;
+ signed v_g = -v * 208;
+ signed v_r = v * 409;
+
+ signed tmp1 = y1 * 298;
+ signed b1 = (tmp1 + u_b) / 256;
+ signed g1 = (tmp1 + v_g + u_g) / 256;
+ signed r1 = (tmp1 + v_r) / 256;
+
+ signed tmp2 = y2 * 298;
+ signed b2 = (tmp2 + u_b) / 256;
+ signed g2 = (tmp2 + v_g + u_g) / 256;
+ signed r2 = (tmp2 + v_r) / 256;
+
+ uint32_t rgb1 =
+ ((kAdjustedClip[b1] >> 3) << 11)
+ | ((kAdjustedClip[g1] >> 2) << 5)
+ | (kAdjustedClip[r1] >> 3);
+
+ uint32_t rgb2 =
+ ((kAdjustedClip[b2] >> 3) << 11)
+ | ((kAdjustedClip[g2] >> 2) << 5)
+ | (kAdjustedClip[r2] >> 3);
+
+ dst_ptr[x / 2] = (rgb2 << 16) | rgb1;
+ }
+
+ src_y += mDecodedWidth;
+
+ if (y & 1) {
+ src_u += mDecodedWidth;
+ }
+
+ dst_ptr += mDecodedWidth / 2;
+ }
+
+ mISurface->postBuffer(offset);
+ mIndex = 1 - mIndex;
+}
+
uint8_t *SoftwareRenderer::initClip() {
static const signed kClipMin = -278;
static const signed kClipMax = 535;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
index 69e93a1..10796f1 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
@@ -16,6 +16,7 @@
package com.android.mediaframeworktest.stress;
+
import com.android.mediaframeworktest.MediaFrameworkTest;
import java.io.BufferedWriter;
@@ -26,6 +27,7 @@
import android.hardware.Camera;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
+import android.os.Looper;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
@@ -54,7 +56,14 @@
private static final String OUTPUT_FILE_EXT = ".3gp";
private static final String MEDIA_STRESS_OUTPUT =
"/sdcard/mediaStressOutput.txt";
-
+ private Looper mCameraLooper = null;
+ private Looper mRecorderLooper = null;
+ private final Object lock = new Object();
+ private final Object recorderlock = new Object();
+ private static int WAIT_FOR_COMMAND_TO_COMPLETE = 10000; // Milliseconds.
+ private final CameraErrorCallback mCameraErrorCallback = new CameraErrorCallback();
+ private final RecorderErrorCallback mRecorderErrorCallback = new RecorderErrorCallback();
+
public MediaRecorderStressTest() {
super("com.android.mediaframeworktest", MediaFrameworkTest.class);
}
@@ -63,41 +72,129 @@
getActivity();
super.setUp();
}
-
+
+ private final class CameraErrorCallback implements android.hardware.Camera.ErrorCallback {
+ public void onError(int error, android.hardware.Camera camera) {
+ if (error == android.hardware.Camera.CAMERA_ERROR_SERVER_DIED) {
+ assertTrue("Camera test mediaserver died", false);
+ }
+ }
+ }
+
+ private final class RecorderErrorCallback implements MediaRecorder.OnErrorListener {
+ public void onError(MediaRecorder mr, int what, int extra) {
+ // fail the test case no matter what error come up
+ assertTrue("mediaRecorder error", false);
+ }
+ }
+
+ private void initializeCameraMessageLooper() {
+ Log.v(TAG, "start looper");
+ new Thread() {
+ @Override
+ public void run() {
+ // Set up a looper to be used by camera.
+ Looper.prepare();
+ Log.v(TAG, "start loopRun");
+ mCameraLooper = Looper.myLooper();
+ mCamera = Camera.open();
+ synchronized (lock) {
+ lock.notify();
+ }
+ Looper.loop();
+ Log.v(TAG, "initializeMessageLooper: quit.");
+ }
+ }.start();
+ }
+
+ private void initializeRecorderMessageLooper() {
+ Log.v(TAG, "start looper");
+ new Thread() {
+ @Override
+ public void run() {
+ Looper.prepare();
+ Log.v(TAG, "start loopRun");
+ mRecorderLooper = Looper.myLooper();
+ mRecorder = new MediaRecorder();
+ synchronized (recorderlock) {
+ recorderlock.notify();
+ }
+ Looper.loop(); // Blocks forever until Looper.quit() is called.
+ Log.v(TAG, "initializeMessageLooper: quit.");
+ }
+ }.start();
+ }
+
+ /*
+ * Terminates the message looper thread.
+ */
+ private void terminateCameraMessageLooper() {
+ mCameraLooper.quit();
+ try {
+ Thread.sleep(1000);
+ } catch (Exception e){
+ Log.v(TAG, e.toString());
+ }
+ mCamera.release();
+ }
+
+ /*
+ * Terminates the message looper thread.
+ */
+ private void terminateRecorderMessageLooper() {
+ mRecorderLooper.quit();
+ try {
+ Thread.sleep(1000);
+ } catch (Exception e){
+ Log.v(TAG, e.toString());
+ }
+ mRecorder.release();
+ }
+
//Test case for stressing the camera preview.
@LargeTest
public void testStressCamera() throws Exception {
- SurfaceHolder mSurfaceHolder;
+ SurfaceHolder mSurfaceHolder;
mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
output.write("Camera start preview stress:\n");
- output.write("Total number of loops:" +
+ output.write("Total number of loops:" +
NUMBER_OF_CAMERA_STRESS_LOOPS + "\n");
- try {
+ try {
Log.v(TAG, "Start preview");
output.write("No of loop: ");
+
for (int i = 0; i< NUMBER_OF_CAMERA_STRESS_LOOPS; i++){
- mCamera = Camera.open();
+ synchronized (lock) {
+ initializeCameraMessageLooper();
+ try {
+ lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+ } catch(Exception e) {
+ Log.v(TAG, "wait was interrupted.");
+ }
+ }
+ mCamera.setErrorCallback(mCameraErrorCallback);
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
Thread.sleep(WAIT_TIME_CAMERA_TEST);
mCamera.stopPreview();
- mCamera.release();
+ terminateCameraMessageLooper();
output.write(" ," + i);
}
} catch (Exception e) {
- Log.v(TAG, e.toString());
+ assertTrue("CameraStressTest", false);
+ Log.v(TAG, e.toString());
}
output.write("\n\n");
output.close();
}
-
+
//Test case for stressing the camera preview.
@LargeTest
public void testStressRecorder() throws Exception {
String filename;
- SurfaceHolder mSurfaceHolder;
+ SurfaceHolder mSurfaceHolder;
mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
@@ -108,12 +205,20 @@
output.write("No of loop: ");
Log.v(TAG, "Start preview");
for (int i = 0; i < NUMBER_OF_RECORDER_STRESS_LOOPS; i++){
+ synchronized (recorderlock) {
+ initializeRecorderMessageLooper();
+ try {
+ recorderlock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+ } catch(Exception e) {
+ Log.v(TAG, "wait was interrupted.");
+ }
+ }
Log.v(TAG, "counter = " + i);
filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
Log.v(TAG, filename);
- mRecorder = new MediaRecorder();
+ mRecorder.setOnErrorListener(mRecorderErrorCallback);
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
- mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+ mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(filename);
mRecorder.setVideoFrameRate(20);
mRecorder.setVideoSize(176,144);
@@ -125,47 +230,63 @@
Log.v(TAG, "prepare");
mRecorder.prepare();
Log.v(TAG, "before release");
- Thread.sleep(WAIT_TIME_RECORDER_TEST);
+ Thread.sleep(WAIT_TIME_RECORDER_TEST);
mRecorder.reset();
- mRecorder.release();
+ terminateRecorderMessageLooper();
output.write(", " + i);
}
} catch (Exception e) {
- Log.v(TAG, e.toString());
+ assertTrue("Recorder Stress test", false);
+ Log.v(TAG, e.toString());
}
output.write("\n\n");
output.close();
}
-
-
+
//Stress test case for switching camera and video recorder preview.
@LargeTest
public void testStressCameraSwitchRecorder() throws Exception {
String filename;
- SurfaceHolder mSurfaceHolder;
+ SurfaceHolder mSurfaceHolder;
mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
output.write("Camera and video recorder preview switching\n");
output.write("Total number of loops:"
+ NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER + "\n");
- try {
+ try {
Log.v(TAG, "Start preview");
output.write("No of loop: ");
for (int i = 0; i < NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER; i++){
- mCamera = Camera.open();
+ synchronized (lock) {
+ initializeCameraMessageLooper();
+ try {
+ lock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+ } catch(Exception e) {
+ Log.v(TAG, "wait was interrupted.");
+ }
+ }
+ mCamera.setErrorCallback(mCameraErrorCallback);
mCamera.setPreviewDisplay(mSurfaceHolder);
mCamera.startPreview();
Thread.sleep(WAIT_TIME_CAMERA_TEST);
mCamera.stopPreview();
- mCamera.release();
+ terminateCameraMessageLooper();
mCamera = null;
Log.v(TAG, "release camera");
filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
Log.v(TAG, filename);
- mRecorder = new MediaRecorder();
+ synchronized (recorderlock) {
+ initializeRecorderMessageLooper();
+ try {
+ recorderlock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+ } catch(Exception e) {
+ Log.v(TAG, "wait was interrupted.");
+ }
+ }
+ mRecorder.setOnErrorListener(mRecorderErrorCallback);
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
- mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+ mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(filename);
mRecorder.setVideoFrameRate(20);
mRecorder.setVideoSize(176,144);
@@ -176,23 +297,24 @@
Log.v(TAG, "prepare");
mRecorder.prepare();
Log.v(TAG, "before release");
- Thread.sleep(WAIT_TIME_CAMERA_TEST);
- mRecorder.release();
+ Thread.sleep(WAIT_TIME_CAMERA_TEST);
+ terminateRecorderMessageLooper();
Log.v(TAG, "release video recorder");
output.write(", " + i);
}
} catch (Exception e) {
+ assertTrue("Camer and recorder switch mode", false);
Log.v(TAG, e.toString());
}
output.write("\n\n");
output.close();
}
-
+
//Stress test case for record a video and play right away.
@LargeTest
public void testStressRecordVideoAndPlayback() throws Exception {
String filename;
- SurfaceHolder mSurfaceHolder;
+ SurfaceHolder mSurfaceHolder;
mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
@@ -204,10 +326,18 @@
for (int i = 0; i < NUMBER_OF_RECORDERANDPLAY_STRESS_LOOPS; i++){
filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
Log.v(TAG, filename);
- mRecorder = new MediaRecorder();
+ synchronized (recorderlock) {
+ initializeRecorderMessageLooper();
+ try {
+ recorderlock.wait(WAIT_FOR_COMMAND_TO_COMPLETE);
+ } catch(Exception e) {
+ Log.v(TAG, "wait was interrupted.");
+ }
+ }
+ mRecorder.setOnErrorListener(mRecorderErrorCallback);
mRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
- mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
+ mRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mRecorder.setOutputFile(filename);
mRecorder.setVideoFrameRate(20);
mRecorder.setVideoSize(352,288);
@@ -216,11 +346,11 @@
Log.v(TAG, "mediaRecorder setPreview");
mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
mRecorder.prepare();
- mRecorder.start();
+ mRecorder.start();
Thread.sleep(WAIT_TIME_RECORD);
Log.v(TAG, "Before stop");
mRecorder.stop();
- mRecorder.release();
+ terminateRecorderMessageLooper();
//start the playback
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(filename);
@@ -232,10 +362,10 @@
output.write(", " + i);
}
} catch (Exception e) {
+ assertTrue("record and playback", false);
Log.v(TAG, e.toString());
}
output.write("\n\n");
output.close();
- }
+ }
}
-
diff --git a/opengl/tests/gl2_basic/gl2_basic.cpp b/opengl/tests/gl2_basic/gl2_basic.cpp
index 705794a..f969a46 100644
--- a/opengl/tests/gl2_basic/gl2_basic.cpp
+++ b/opengl/tests/gl2_basic/gl2_basic.cpp
@@ -33,11 +33,45 @@
static void printGLString(const char *name, GLenum s)
{
+ fprintf(stderr, "printGLString %s, %d\n", name, s);
const char *v = (const char *)glGetString(s);
- if (v)
- printf("GL %s = %s\n", name, v);
+ int error = glGetError();
+ fprintf(stderr, "glGetError() = %d, result of glGetString = %x\n", error,
+ (unsigned int)v);
+ if ((v < (const char*) 0) || (v > (const char*) 0x1000))
+ fprintf(stderr, "GL %s = %s\n", name, v);
else
- printf("GL %s = (null)\n", name);
+ fprintf(stderr, "GL %s = (null)\n", name);
+}
+
+static const char* eglErrorToString[] = {
+ "EGL_SUCCESS", // 0x3000 12288
+ "EGL_NOT_INITIALIZED",
+ "EGL_BAD_ACCESS", // 0x3002 12290
+ "EGL_BAD_ALLOC",
+ "EGL_BAD_ATTRIBUTE",
+ "EGL_BAD_CONFIG",
+ "EGL_BAD_CONTEXT", // 0x3006 12294
+ "EGL_BAD_CURRENT_SURFACE",
+ "EGL_BAD_DISPLAY",
+ "EGL_BAD_MATCH",
+ "EGL_BAD_NATIVE_PIXMAP",
+ "EGL_BAD_NATIVE_WINDOW",
+ "EGL_BAD_PARAMETER", // 0x300c 12300
+ "EGL_BAD_SURFACE"
+};
+
+static void checkEglError(const char* op) {
+ for(EGLint error = eglGetError();
+ error != EGL_SUCCESS;
+ error = eglGetError()) {
+ const char* errorString = "unknown";
+ if (error >= EGL_SUCCESS && error <= EGL_BAD_SURFACE) {
+ errorString = eglErrorToString[error - EGL_SUCCESS];
+ }
+ fprintf(stderr, "%s() returned eglError %s (0x%x)\n", op,
+ errorString, error);
+ }
}
int main(int argc, char** argv)
@@ -63,19 +97,33 @@
EGLNativeWindowType window = 0;
window = android_createDisplaySurface();
+ checkEglError("<init>");
dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ checkEglError("eglGetDisplay");
eglInitialize(dpy, &majorVersion, &minorVersion);
+ checkEglError("eglInitialize");
+ fprintf(stderr, "EGL version %d.%d\n", majorVersion, minorVersion);
EGLUtils::selectConfigForNativeWindow(dpy, s_configAttribs, window, &config);
- surface = eglCreateWindowSurface(dpy, config, window, NULL);
+ fprintf(stderr, "Chosen config: 0x%08x\n", (unsigned long) config);
- EGLint gl2_0Attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
+ checkEglError("EGLUtils::selectConfigForNativeWindow");
+ surface = eglCreateWindowSurface(dpy, config, window, NULL);
+ checkEglError("eglCreateWindowSurface");
+
+ EGLint gl2_0Attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
context = eglCreateContext(dpy, config, NULL, gl2_0Attribs);
+ checkEglError("eglCreateContext");
eglMakeCurrent(dpy, surface, surface, context);
+ checkEglError("eglMakeCurrent");
eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
+ checkEglError("eglQuerySurface");
eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
+ checkEglError("eglQuerySurface");
GLint dim = w<h ? w : h;
+ fprintf(stderr, "Window dimensions: %d x %d\n", w, h);
+
printGLString("Version", GL_VERSION);
printGLString("Vendor", GL_VENDOR);
printGLString("Renderer", GL_RENDERER);
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 0e60dd6..c6be61d 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -649,11 +649,21 @@
int N = packages.size();
for (int a = N-1; a >= 0; a--) {
PackageInfo pkg = packages.get(a);
- ApplicationInfo app = pkg.applicationInfo;
- if (((app.flags&ApplicationInfo.FLAG_ALLOW_BACKUP) == 0)
- || app.backupAgentName == null
- || (mPackageManager.checkPermission(android.Manifest.permission.BACKUP_DATA,
- pkg.packageName) != PackageManager.PERMISSION_GRANTED)) {
+ try {
+ ApplicationInfo app = pkg.applicationInfo;
+ if (((app.flags&ApplicationInfo.FLAG_ALLOW_BACKUP) == 0)
+ || app.backupAgentName == null
+ || (mPackageManager.checkPermission(android.Manifest.permission.BACKUP_DATA,
+ pkg.packageName) != PackageManager.PERMISSION_GRANTED)) {
+ packages.remove(a);
+ }
+ else {
+ // we will need the shared library path, so look that up and store it here
+ app = mPackageManager.getApplicationInfo(pkg.packageName,
+ PackageManager.GET_SHARED_LIBRARY_FILES);
+ pkg.applicationInfo.sharedLibraryFiles = app.sharedLibraryFiles;
+ }
+ } catch (NameNotFoundException e) {
packages.remove(a);
}
}
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index 30c25e0..60195b9 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -16,6 +16,7 @@
package com.android.server;
+import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
@@ -111,6 +112,30 @@
Intent intent = new Intent(Intent.ACTION_DOCK_EVENT);
intent.putExtra(Intent.EXTRA_DOCK_STATE, mDockState);
mContext.sendStickyBroadcast(intent);
+
+ // Launch a dock activity
+ String category;
+ switch (mDockState) {
+ case Intent.EXTRA_DOCK_STATE_CAR:
+ category = Intent.CATEGORY_CAR_DOCK;
+ break;
+ case Intent.EXTRA_DOCK_STATE_DESK:
+ category = Intent.CATEGORY_DESK_DOCK;
+ break;
+ default:
+ category = null;
+ break;
+ }
+ if (category != null) {
+ intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(category);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ try {
+ mContext.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Log.w(TAG, e.getCause());
+ }
+ }
}
}
};
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 82cf1bc..45e0ceb 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -3611,9 +3611,18 @@
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
- PackageInstalledInfo res;
- synchronized (mInstallLock) {
- res = installPackageLI(packageURI, flags, true, installerPackageName);
+ // Result object to be returned
+ PackageInstalledInfo res = new PackageInstalledInfo();
+ res.returnCode = PackageManager.INSTALL_SUCCEEDED;
+ res.uid = -1;
+ res.pkg = null;
+ res.removedInfo = new PackageRemovedInfo();
+ // Make a temporary copy of file from given packageURI
+ File tmpPackageFile = copyTempInstallFile(packageURI, res);
+ if (tmpPackageFile != null) {
+ synchronized (mInstallLock) {
+ installPackageLI(packageURI, flags, true, installerPackageName, tmpPackageFile, res);
+ }
}
if (observer != null) {
try {
@@ -3828,11 +3837,30 @@
// Since we failed to install the new package we need to restore the old
// package that we deleted.
if(deletedPkg) {
+ File restoreFile = new File(deletedPackage.mPath);
+ if (restoreFile == null) {
+ Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
+ return;
+ }
+ File restoreTmpFile = createTempPackageFile();
+ if (restoreTmpFile == null) {
+ Log.e(TAG, "Failed creating temp file when restoring pkg : " + pkgName);
+ return;
+ }
+ if (!FileUtils.copyFile(restoreFile, restoreTmpFile)) {
+ Log.e(TAG, "Failed copying temp file when restoring pkg : " + pkgName);
+ return;
+ }
+ PackageInstalledInfo restoreRes = new PackageInstalledInfo();
+ restoreRes.removedInfo = new PackageRemovedInfo();
installPackageLI(
- Uri.fromFile(new File(deletedPackage.mPath)),
+ Uri.fromFile(restoreFile),
isForwardLocked(deletedPackage)
? PackageManager.INSTALL_FORWARD_LOCK
- : 0, false, oldInstallerPackageName);
+ : 0, false, oldInstallerPackageName, restoreTmpFile, restoreRes);
+ if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
+ Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
+ }
}
}
}
@@ -3995,50 +4023,36 @@
return new File(mAppInstallDir, publicZipFileName);
}
- private PackageInstalledInfo installPackageLI(Uri pPackageURI,
- int pFlags, boolean newInstall, String installerPackageName) {
- File tmpPackageFile = null;
- String pkgName = null;
- boolean forwardLocked = false;
- boolean replacingExistingPackage = false;
- // Result object to be returned
- PackageInstalledInfo res = new PackageInstalledInfo();
- res.returnCode = PackageManager.INSTALL_SUCCEEDED;
- res.uid = -1;
- res.pkg = null;
- res.removedInfo = new PackageRemovedInfo();
+ private File copyTempInstallFile(Uri pPackageURI,
+ PackageInstalledInfo res) {
+ File tmpPackageFile = createTempPackageFile();
+ int retCode = PackageManager.INSTALL_SUCCEEDED;
+ if (tmpPackageFile == null) {
+ res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ return null;
+ }
- main_flow: try {
- tmpPackageFile = createTempPackageFile();
- if (tmpPackageFile == null) {
- res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- break main_flow;
+ if (pPackageURI.getScheme().equals("file")) {
+ final File srcPackageFile = new File(pPackageURI.getPath());
+ // We copy the source package file to a temp file and then rename it to the
+ // destination file in order to eliminate a window where the package directory
+ // scanner notices the new package file but it's not completely copied yet.
+ if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
+ Log.e(TAG, "Couldn't copy package file to temp file.");
+ retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
}
- tmpPackageFile.deleteOnExit(); // paranoia
- if (pPackageURI.getScheme().equals("file")) {
- final File srcPackageFile = new File(pPackageURI.getPath());
- // We copy the source package file to a temp file and then rename it to the
- // destination file in order to eliminate a window where the package directory
- // scanner notices the new package file but it's not completely copied yet.
- if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
- Log.e(TAG, "Couldn't copy package file to temp file.");
- res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- break main_flow;
- }
- } else if (pPackageURI.getScheme().equals("content")) {
- ParcelFileDescriptor fd;
- try {
- fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
- } catch (FileNotFoundException e) {
- Log.e(TAG, "Couldn't open file descriptor from download service.");
- res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- break main_flow;
- }
- if (fd == null) {
- Log.e(TAG, "Couldn't open file descriptor from download service (null).");
- res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- break main_flow;
- }
+ } else if (pPackageURI.getScheme().equals("content")) {
+ ParcelFileDescriptor fd = null;
+ try {
+ fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
+ } catch (FileNotFoundException e) {
+ Log.e(TAG, "Couldn't open file descriptor from download service. Failed with exception " + e);
+ retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ }
+ if (fd == null) {
+ Log.e(TAG, "Couldn't open file descriptor from download service (null).");
+ retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ } else {
if (Config.LOGV) {
Log.v(TAG, "Opened file descriptor from download service.");
}
@@ -4049,14 +4063,34 @@
// scanner notices the new package file but it's not completely copied yet.
if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
Log.e(TAG, "Couldn't copy package stream to temp file.");
- res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- break main_flow;
+ retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
}
- } else {
- Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
- res.returnCode = PackageManager.INSTALL_FAILED_INVALID_URI;
- break main_flow;
}
+ } else {
+ Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
+ retCode = PackageManager.INSTALL_FAILED_INVALID_URI;
+ }
+
+ res.returnCode = retCode;
+ if (retCode != PackageManager.INSTALL_SUCCEEDED) {
+ if (tmpPackageFile != null && tmpPackageFile.exists()) {
+ tmpPackageFile.delete();
+ }
+ return null;
+ }
+ return tmpPackageFile;
+ }
+
+ private void installPackageLI(Uri pPackageURI,
+ int pFlags, boolean newInstall, String installerPackageName,
+ File tmpPackageFile, PackageInstalledInfo res) {
+ String pkgName = null;
+ boolean forwardLocked = false;
+ boolean replacingExistingPackage = false;
+ // Result object to be returned
+ res.returnCode = PackageManager.INSTALL_SUCCEEDED;
+
+ main_flow: try {
pkgName = PackageParser.parsePackageName(
tmpPackageFile.getAbsolutePath(), 0);
if (pkgName == null) {
@@ -4128,7 +4162,6 @@
tmpPackageFile.delete();
}
}
- return res;
}
private int setPermissionsLI(String pkgName,
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 53ff78e..63bef54 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -665,6 +665,15 @@
}
}
}
+
+ for (WifiConfiguration.EnterpriseField field :
+ config.enterpriseFields) {
+ value = WifiNative.getNetworkVariableCommand(netId,
+ field.varName());
+ if (!TextUtils.isEmpty(value)) {
+ field.setValue(value);
+ }
+ }
}
/**
@@ -877,103 +886,20 @@
break setVariables;
}
- if ((config.eap != null) && !WifiNative.setNetworkVariableCommand(
+ for (WifiConfiguration.EnterpriseField field
+ : config.enterpriseFields) {
+ String varName = field.varName();
+ String value = field.value();
+ if ((value != null) && !WifiNative.setNetworkVariableCommand(
netId,
- WifiConfiguration.eapVarName,
- config.eap)) {
- if (DBG) {
- Log.d(TAG, config.SSID + ": failed to set eap: "+
- config.eap);
+ varName,
+ value)) {
+ if (DBG) {
+ Log.d(TAG, config.SSID + ": failed to set " + varName +
+ ": " + value);
+ }
+ break setVariables;
}
- break setVariables;
- }
-
- if ((config.phase2 != null) && !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.phase2VarName,
- config.phase2)) {
- if (DBG) {
- Log.d(TAG, config.SSID + ": failed to set phase2: "+
- config.phase2);
- }
- break setVariables;
- }
-
- if ((config.identity != null) && !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.identityVarName,
- config.identity)) {
- if (DBG) {
- Log.d(TAG, config.SSID + ": failed to set identity: "+
- config.identity);
- }
- break setVariables;
- }
-
- if ((config.anonymousIdentity != null) && !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.anonymousIdentityVarName,
- config.anonymousIdentity)) {
- if (DBG) {
- Log.d(TAG, config.SSID + ": failed to set anonymousIdentity: "+
- config.anonymousIdentity);
- }
- break setVariables;
- }
-
- if ((config.password != null) && !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.passwordVarName,
- config.password)) {
- if (DBG) {
- Log.d(TAG, config.SSID + ": failed to set password: "+
- config.password);
- }
- break setVariables;
- }
-
- if ((config.clientCert != null) && !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.clientCertVarName,
- config.clientCert)) {
- if (DBG) {
- Log.d(TAG, config.SSID + ": failed to set clientCert: "+
- config.clientCert);
- }
- break setVariables;
- }
-
- if ((config.caCert != null) && !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.caCertVarName,
- config.caCert)) {
- if (DBG) {
- Log.d(TAG, config.SSID + ": failed to set caCert: "+
- config.caCert);
- }
- break setVariables;
- }
-
- if ((config.privateKey != null) && !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.privateKeyVarName,
- config.privateKey)) {
- if (DBG) {
- Log.d(TAG, config.SSID + ": failed to set privateKey: "+
- config.privateKey);
- }
- break setVariables;
- }
-
- if ((config.privateKeyPasswd != null) && !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.privateKeyPasswdVarName,
- config.privateKeyPasswd)) {
- if (DBG) {
- Log.d(TAG, config.SSID + ": failed to set privateKeyPasswd: "+
- config.privateKeyPasswd);
- }
- break setVariables;
}
return netId;
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index bd2c3ed..d53f002 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -442,6 +442,8 @@
// Who is holding the screen on.
Session mHoldingScreenOn;
+ boolean mTurnOnScreen;
+
/**
* Whether the UI is currently running in touch mode (not showing
* navigational focus because the user is directly pressing the screen).
@@ -2208,6 +2210,10 @@
&& !win.mCommitDrawPending && !mDisplayFrozen) {
applyEnterAnimationLocked(win);
}
+ if (displayed && (win.mAttrs.flags
+ & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
+ win.mTurnOnScreen = true;
+ }
if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
// To change the format, we need to re-build the surface.
win.destroySurfaceLocked();
@@ -6479,6 +6485,7 @@
int mLastLayer;
boolean mHaveFrame;
boolean mObscured;
+ boolean mTurnOnScreen;
WindowState mNextOutsideTouch;
@@ -7049,7 +7056,7 @@
+ " attHidden=" + mAttachedHidden
+ " tok.hiddenRequested="
+ (mAppToken != null ? mAppToken.hiddenRequested : false)
- + " tok.idden="
+ + " tok.hidden="
+ (mAppToken != null ? mAppToken.hidden : false)
+ " animating=" + mAnimating
+ " tok animating="
@@ -7078,10 +7085,20 @@
if (mAttrs.type != TYPE_APPLICATION_STARTING
&& mAppToken != null) {
mAppToken.firstWindowDrawn = true;
- if (mAnimation == null && mAppToken.startingData != null) {
+
+ if (mAppToken.startingData != null) {
if (DEBUG_STARTING_WINDOW) Log.v(TAG, "Finish starting "
+ mToken
+ ": first real window is shown, no animation");
+ // If this initial window is animating, stop it -- we
+ // will do an animation to reveal it from behind the
+ // starting window, so there is no need for it to also
+ // be doing its own stuff.
+ if (mAnimation != null) {
+ mAnimation = null;
+ // Make sure we clean up the animation.
+ mAnimating = true;
+ }
mFinishedStarting.add(mAppToken);
mH.sendEmptyMessage(H.FINISHED_STARTING);
}
@@ -7710,10 +7727,11 @@
pw.print(" mDestroying="); pw.print(mDestroying);
pw.print(" mRemoved="); pw.println(mRemoved);
}
- if (mOrientationChanging || mAppFreezing) {
+ if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
pw.print(prefix); pw.print("mOrientationChanging=");
pw.print(mOrientationChanging);
- pw.print(" mAppFreezing="); pw.println(mAppFreezing);
+ pw.print(" mAppFreezing="); pw.print(mAppFreezing);
+ pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
}
if (mHScale != 1 || mVScale != 1) {
pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
@@ -9782,6 +9800,12 @@
Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen);
mH.sendMessage(m);
}
+
+ if (mTurnOnScreen) {
+ mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
+ LocalPowerManager.BUTTON_EVENT, true);
+ mTurnOnScreen = false;
+ }
}
void requestAnimationLocked(long delay) {
@@ -9803,6 +9827,10 @@
try {
if (win.mSurface != null) {
win.mSurface.show();
+ if (win.mTurnOnScreen) {
+ win.mTurnOnScreen = false;
+ mTurnOnScreen = true;
+ }
}
return true;
} catch (RuntimeException e) {
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 4368464..2672c6d 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -129,6 +129,8 @@
return uri.getSchemeSpecificPart();
}
+ // TODO: We don't check for SecurityException here (requires
+ // READ_PHONE_STATE permission).
if (scheme.equals("voicemail")) {
return TelephonyManager.getDefault().getVoiceMailNumber();
}
@@ -1179,6 +1181,35 @@
}
/**
+ * isVoiceMailNumber: checks a given number against the voicemail
+ * number provided by the RIL and SIM card. The caller must have
+ * the READ_PHONE_STATE credential.
+ *
+ * @param number the number to look up.
+ * @return true if the number is in the list of voicemail. False
+ * otherwise, including if the caller does not have the permission
+ * to read the VM number.
+ * @hide TODO: pending API Council approval
+ */
+ public static boolean isVoiceMailNumber(String number) {
+ String vmNumber;
+
+ try {
+ vmNumber = TelephonyManager.getDefault().getVoiceMailNumber();
+ } catch (SecurityException ex) {
+ return false;
+ }
+
+ // Strip the separators from the number before comparing it
+ // to the list.
+ number = extractNetworkPortion(number);
+
+ // compare tolerates null so we need to make sure that we
+ // don't return true when both are null.
+ return !TextUtils.isEmpty(number) && compare(number, vmNumber);
+ }
+
+ /**
* Translates any alphabetic letters (i.e. [A-Za-z]) in the
* specified phone number into the equivalent numeric digits,
* according to the phone keypad letter mapping described in
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index c8490e9..01b1746 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -101,13 +101,12 @@
public boolean isCachedPhotoCurrent;
private boolean mIsEmergency;
-
- // Don't keep checking VM if it's going to throw an exception for this proc.
- private static boolean sSkipVmCheck = false;
+ private boolean mIsVoiceMail;
public CallerInfo() {
// TODO: Move all the basic initialization here?
mIsEmergency = false;
+ mIsVoiceMail = false;
}
/**
@@ -220,32 +219,15 @@
public static CallerInfo getCallerInfo(Context context, String number) {
if (TextUtils.isEmpty(number)) {
return null;
- } else {
- // Change the callerInfo number ONLY if it is an emergency number
- // or if it is the voicemail number. If it is either, take a
- // shortcut and skip the query.
- if (PhoneNumberUtils.isEmergencyNumber(number)) {
- return new CallerInfo().markAsEmergency(context);
- } else {
- try {
- if (!sSkipVmCheck && PhoneNumberUtils.compare(number,
- TelephonyManager.getDefault().getVoiceMailNumber())) {
- CallerInfo ci = new CallerInfo();
+ }
- // Note we're setting the phone number here (refer to javadoc
- // comments at the top of CallerInfo class).
- ci.phoneNumber = TelephonyManager.getDefault().getVoiceMailAlphaTag();
- // TODO: FIND ANOTHER ICON
- //info.photoResource = android.R.drawable.badge_voicemail;
- return ci;
- }
- } catch (SecurityException ex) {
- // Don't crash if this process doesn't have permission to
- // retrieve VM number. It's still allowed to look up caller info.
- // But don't try it again.
- sSkipVmCheck = true;
- }
- }
+ // Change the callerInfo number ONLY if it is an emergency number
+ // or if it is the voicemail number. If it is either, take a
+ // shortcut and skip the query.
+ if (PhoneNumberUtils.isEmergencyNumber(number)) {
+ return new CallerInfo().markAsEmergency(context);
+ } else if (PhoneNumberUtils.isVoiceMailNumber(number)) {
+ return new CallerInfo().markAsVoiceMail();
}
Uri contactUri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
@@ -304,6 +286,13 @@
}
/**
+ * @return true if the caller info is a voicemail number.
+ */
+ public boolean isVoiceMailNumber() {
+ return mIsVoiceMail;
+ }
+
+ /**
* Mark this CallerInfo as an emergency call.
* @param context To lookup the localized 'Emergency Number' string.
* @return this instance.
@@ -323,6 +312,37 @@
return this;
}
+
+ /**
+ * Mark this CallerInfo as a voicemail call. The voicemail label
+ * is obtained from the telephony manager. Caller must hold the
+ * READ_PHONE_STATE permission otherwise the phoneNumber will be
+ * set to null.
+ * @return this instance.
+ */
+ // TODO: As in the emergency number handling, we end up writing a
+ // string in the phone number field.
+ /* package */ CallerInfo markAsVoiceMail() {
+ mIsVoiceMail = true;
+
+ try {
+ String voiceMailLabel = TelephonyManager.getDefault().getVoiceMailAlphaTag();
+
+ phoneNumber = voiceMailLabel;
+ } catch (SecurityException se) {
+ // Should never happen: if this process does not have
+ // permission to retrieve VM tag, it should not have
+ // permission to retrieve VM number and would not call
+ // this method.
+ // Leave phoneNumber untouched.
+ Log.e(TAG, "Cannot access VoiceMail.", se);
+ }
+ // TODO: There is no voicemail picture?
+ // FIXME: FIND ANOTHER ICON
+ // photoResource = android.R.drawable.badge_voicemail;
+ return this;
+ }
+
private static String normalize(String s) {
if (s == null || s.length() > 0) {
return s;
@@ -330,4 +350,31 @@
return null;
}
}
+
+ /**
+ * @return a string debug representation of this instance.
+ */
+ public String toString() {
+ return new StringBuilder(384)
+ .append("\nname: " + name)
+ .append("\nphoneNumber: " + phoneNumber)
+ .append("\ncnapName: " + cnapName)
+ .append("\nnumberPresentation: " + numberPresentation)
+ .append("\nnamePresentation: " + namePresentation)
+ .append("\ncontactExits: " + contactExists)
+ .append("\nphoneLabel: " + phoneLabel)
+ .append("\nnumberType: " + numberType)
+ .append("\nnumberLabel: " + numberLabel)
+ .append("\nphotoResource: " + photoResource)
+ .append("\nperson_id: " + person_id)
+ .append("\nneedUpdate: " + needUpdate)
+ .append("\ncontactRefUri: " + contactRefUri)
+ .append("\ncontactRingtoneUri: " + contactRefUri)
+ .append("\nshouldSendToVoicemail: " + shouldSendToVoicemail)
+ .append("\ncachedPhoto: " + cachedPhoto)
+ .append("\nisCachedPhotoCurrent: " + isCachedPhotoCurrent)
+ .append("\nemergency: " + mIsEmergency)
+ .append("\nvoicemail " + mIsVoiceMail)
+ .toString();
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
index 4227a84..802e79b 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
@@ -47,9 +47,6 @@
private CallerInfoAsyncQueryHandler mHandler;
- // Don't keep checking VM if it's going to throw an exception for this proc.
- private static boolean sSkipVmCheck = false;
-
/**
* Interface for a CallerInfoAsyncQueryHandler result return.
*/
@@ -227,18 +224,7 @@
// comments at the top of CallerInfo class).
mCallerInfo = new CallerInfo().markAsEmergency(mQueryContext);
} else if (cw.event == EVENT_VOICEMAIL_NUMBER) {
- mCallerInfo = new CallerInfo();
- try {
- // Note we're setting the phone number here (refer to javadoc
- // comments at the top of CallerInfo class).
- mCallerInfo.phoneNumber =
- TelephonyManager.getDefault().getVoiceMailAlphaTag();
- } catch (SecurityException ex) {
- // Should never happen: if this process does not have
- // permission to retrieve VM tag, it should not have
- // permission to retrieve VM number and would not generate
- // an EVENT_VOICEMAIL_NUMBER. But if it happens, don't crash.
- }
+ mCallerInfo = new CallerInfo().markAsVoiceMail();
} else {
mCallerInfo = CallerInfo.getCallerInfo(mQueryContext, mQueryUri, cursor);
// Use the number entered by the user for display.
@@ -258,7 +244,7 @@
//notify the listener that the query is complete.
if (cw.listener != null) {
if (DBG) log("notifying listener: " + cw.listener.getClass().toString() +
- " for token: " + token);
+ " for token: " + token + mCallerInfo);
cw.listener.onQueryComplete(token, cw.cookie, mCallerInfo);
}
}
@@ -315,23 +301,10 @@
// check to see if these are recognized numbers, and use shortcuts if we can.
if (PhoneNumberUtils.isEmergencyNumber(number)) {
cw.event = EVENT_EMERGENCY_NUMBER;
+ } else if (PhoneNumberUtils.isVoiceMailNumber(number)) {
+ cw.event = EVENT_VOICEMAIL_NUMBER;
} else {
- String vmNumber = null;
- if (!sSkipVmCheck){
- try {
- vmNumber = TelephonyManager.getDefault().getVoiceMailNumber();
- } catch (SecurityException ex) {
- // Don't crash if this process doesn't have permission to
- // retrieve VM number. It's still allowed to look up caller info.
- // But don't try it again.
- sSkipVmCheck = true;
- }
- }
- if (PhoneNumberUtils.compare(number, vmNumber)) {
- cw.event = EVENT_VOICEMAIL_NUMBER;
- } else {
- cw.event = EVENT_NEW_QUERY;
- }
+ cw.event = EVENT_NEW_QUERY;
}
c.mHandler.startQuery (token, cw, contactRef, null, null, null, null);
diff --git a/telephony/tests/TelephonyTest/AndroidManifest.xml b/telephony/tests/TelephonyTest/AndroidManifest.xml
index c0cc0d5..b2a481b 100644
--- a/telephony/tests/TelephonyTest/AndroidManifest.xml
+++ b/telephony/tests/TelephonyTest/AndroidManifest.xml
@@ -28,8 +28,9 @@
</intent-filter>
</activity>
</application>
- <instrumentation android:name=".TelephonyUnitTestRunner"
- android:targetPackage="com.android.telephonytest"
- android:label="Telephony unit tests InstrumentationRunner">
- </instrumentation>
+ <instrumentation android:name=".TelephonyUnitTestRunner"
+ android:targetPackage="com.android.telephonytest"
+ android:label="Telephony unit tests InstrumentationRunner">
+ </instrumentation>
+ <uses-permission android:name="android.permission.READ_PHONE_STATE" />
</manifest>
diff --git a/telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java b/telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java
index 5da940d..9e1af31 100644
--- a/telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java
+++ b/telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java
@@ -37,6 +37,7 @@
public TestSuite getAllTests() {
TestSuite suite = new InstrumentationTestSuite(this);
suite.addTestSuite(com.android.telephonytest.unit.CallerInfoUnitTest.class);
+ suite.addTestSuite(com.android.telephonytest.unit.PhoneNumberUtilsUnitTest.class);
return suite;
}
diff --git a/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/CallerInfoUnitTest.java b/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/CallerInfoUnitTest.java
index 4cd0266..0f24f15 100644
--- a/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/CallerInfoUnitTest.java
+++ b/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/CallerInfoUnitTest.java
@@ -107,6 +107,16 @@
assertIsValidEmergencyCallerInfo();
}
+ // TODO: Add more tests:
+ /**
+ * Check if the voice mail number cannot be retrieved that the
+ * original phone number is preserved.
+ */
+ /**
+ * Check the markAs* methods work.
+ */
+
+
//
// Helpers
//
diff --git a/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java b/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java
new file mode 100644
index 0000000..2d3c548
--- /dev/null
+++ b/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/PhoneNumberUtilsUnitTest.java
@@ -0,0 +1,63 @@
+/*
+ * 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.telephonytest.unit;
+import android.test.AndroidTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.util.Log;
+
+import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
+
+/*
+ * Check the PhoneNumberUtils utility class works as expected.
+ *
+ */
+
+public class PhoneNumberUtilsUnitTest extends AndroidTestCase {
+ private String mVoiceMailNumber;
+ private static final String TAG = "PhoneNumberUtilsUnitTest";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ // FIXME: Why are we getting a security exception here? The
+ // permission is declared in the manifest....
+ // mVoiceMailNumber = TelephonyManager.getDefault().getVoiceMailNumber();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Basic checks for the VoiceMail number.
+ * Assumes READ_PHONE_STATE permission and we don't have it.
+ */
+ // TODO: Figure out why we don't have the permission declared in the manifest.
+ @SmallTest
+ public void testWithNumberNotEqualToVoiceMail() throws Exception {
+ assertFalse(PhoneNumberUtils.isVoiceMailNumber("911"));
+ assertFalse(PhoneNumberUtils.isVoiceMailNumber("tel:911"));
+ assertFalse(PhoneNumberUtils.isVoiceMailNumber("+18001234567"));
+ assertFalse(PhoneNumberUtils.isVoiceMailNumber(""));
+ assertFalse(PhoneNumberUtils.isVoiceMailNumber(null));
+ // FIXME:
+ // assertTrue(PhoneNumberUtils.isVoiceMailNumber(mVoiceMailNumber));
+ }
+
+}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/os/HandlerThreadTest.java b/tests/AndroidTests/src/com/android/unit_tests/os/HandlerThreadTest.java
index c62f94f..f2025c6 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/os/HandlerThreadTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/os/HandlerThreadTest.java
@@ -36,8 +36,11 @@
public void testHandlerThread() throws Exception {
HandlerThread th1 = new HandlerThread("HandlerThreadTest") {
protected void onLooperPrepared() {
- mDidSetup = true;
- mLooperTid = Process.myTid();
+ synchronized (HandlerThreadTest.this) {
+ mDidSetup = true;
+ mLooperTid = Process.myTid();
+ HandlerThreadTest.this.notify();
+ }
}
};
@@ -49,14 +52,23 @@
assertTrue(th1.isAlive());
assertNotNull(th1.getLooper());
- /*
- * Since getLooper() will block until the HandlerThread is setup, we are guaranteed
- * that mDidSetup and mLooperTid will have been initalized. If they have not, then
- * this test should fail
- */
+ // The call to getLooper() internally blocks until the looper is
+ // available, but will call onLooperPrepared() after that. So we
+ // need to block here to wait for our onLooperPrepared() to complete
+ // and fill in the values we expect.
+ synchronized (this) {
+ while (!mDidSetup) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ // Make sure that the process was set.
+ assertNotSame(-1, mLooperTid);
// Make sure that the onLooperPrepared() was called on a different thread.
assertNotSame(Process.myTid(), mLooperTid);
- assertTrue(mDidSetup);
final Handler h1 = new Handler(th1.getLooper()) {
public void handleMessage(Message msg) {
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index 8fea967..395e572 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -96,7 +96,9 @@
// Android layout tests are stored in "layout_tests". The following two
// tests expect "LayoutTests" in their output.
"storage/domstorage/localstorage/iframe-events.html",
- "storage/domstorage/sessionstorage/iframe-events.html"
+ "storage/domstorage/sessionstorage/iframe-events.html",
+ // below tests (failed or crashes) are filtered out temporarily due to prioritizing
+ "editing/selection/move-left-right.html",
};
static void fillIgnoreResultSet() {
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
index cc2f1f5..85e0422 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FsUtils.java
@@ -1,5 +1,23 @@
+/*
+ * 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.dumprendertree;
+import com.android.dumprendertree.forwarder.ForwardService;
+
import android.util.Log;
import java.io.BufferedOutputStream;
@@ -12,6 +30,12 @@
public class FsUtils {
private static final String LOGTAG = "FsUtils";
+ static final String HTTP_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/";
+ static final String HTTPS_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/ssl/";
+ static final String HTTP_LOCAL_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/local/";
+ static final String HTTP_MEDIA_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/media/";
+ static final String HTTP_WML_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/wml/";
+
private FsUtils() {
//no creation of instances
}
@@ -77,4 +101,24 @@
return status;
}
+ public static String getTestUrl(String path) {
+ String url = null;
+ if (!path.startsWith(HTTP_TESTS_PREFIX)) {
+ url = "file://" + path;
+ } else {
+ ForwardService.getForwardService().startForwardService();
+ if (path.startsWith(HTTPS_TESTS_PREFIX)) {
+ // still cut the URL after "http/tests/"
+ url = "https://127.0.0.1:8443/" + path.substring(HTTP_TESTS_PREFIX.length());
+ } else if (!path.startsWith(HTTP_LOCAL_TESTS_PREFIX)
+ && !path.startsWith(HTTP_MEDIA_TESTS_PREFIX)
+ && !path.startsWith(HTTP_WML_TESTS_PREFIX)) {
+ url = "http://127.0.0.1:8000/" + path.substring(HTTP_TESTS_PREFIX.length());
+ } else {
+ url = "file://" + path;
+ }
+ }
+ return url;
+ }
+
}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
index e4c8716..235e10e 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestsAutoTest.java
@@ -19,6 +19,7 @@
import com.android.dumprendertree.TestShellActivity.DumpDataType;
import com.android.dumprendertree.forwarder.AdbUtils;
import com.android.dumprendertree.forwarder.ForwardServer;
+import com.android.dumprendertree.forwarder.ForwardService;
import android.app.Instrumentation;
import android.content.Intent;
@@ -143,17 +144,6 @@
static final String LAYOUT_RESULTS_CRASHED_RESULT_FILE = "results/layout_tests_crashed.txt";
static final String LAYOUT_TESTS_RUNNER = "run_layout_tests.py";
- static final String HTTP_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/";
- static final String HTTPS_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/ssl/";
- static final String HTTP_LOCAL_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/local/";
- static final String HTTP_MEDIA_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/media/";
- static final String HTTP_WML_TESTS_PREFIX = "/sdcard/android/layout_tests/http/tests/wml/";
-
-
- static final String DEFAULT_TEST_HOST = "android-browser-test.mtv.corp.google.com";
- static final String FORWARD_HOST_CONF = "/sdcard/drt_forward_host.txt";
- private ForwardServer fs8000, fs8080, fs8443;
-
private MyTestRecorder mResultRecorder;
private Vector<String> mTestList;
private boolean mRebaselineResults;
@@ -162,45 +152,6 @@
public LayoutTestsAutoTest() {
super("com.android.dumprendertree", TestShellActivity.class);
-
- int addr = getForwardHostAddr();
- if(addr != -1) {
- fs8000 = new ForwardServer(8000, addr, 8000);
- fs8080 = new ForwardServer(8080, addr, 8080);
- fs8443 = new ForwardServer(8443, addr, 8443);
- }
- }
-
- private int getForwardHostAddr() {
- int addr = -1;
- String host = null;
- File forwardHostConf = new File(FORWARD_HOST_CONF);
- if (forwardHostConf.isFile()) {
- BufferedReader hostReader = null;
- try {
- hostReader = new BufferedReader(new FileReader(forwardHostConf));
- host = hostReader.readLine();
- Log.v(LOGTAG, "read forward host from file: " + host);
- } catch (IOException ioe) {
- Log.v(LOGTAG, "cannot read forward host from file", ioe);
- } finally {
- if (hostReader != null) {
- try {
- hostReader.close();
- } catch (IOException ioe) {
- // burn!!!
- }
- }
- }
- }
- if (host == null || host.length() == 0)
- host = DEFAULT_TEST_HOST;
- try {
- addr = AdbUtils.resolve(host);
- } catch (IOException ioe) {
- Log.e(LOGTAG, "failed to resolve server address", ioe);
- }
- return addr;
}
// This function writes the result of the layout test to
@@ -366,7 +317,7 @@
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setClass(activity, TestShellActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
- intent.putExtra(TestShellActivity.TEST_URL, getTestUrl(test));
+ intent.putExtra(TestShellActivity.TEST_URL, FsUtils.getTestUrl(test));
intent.putExtra(TestShellActivity.RESULT_FILE, resultFile);
intent.putExtra(TestShellActivity.TIMEOUT_IN_MILLIS, timeout);
activity.startActivity(intent);
@@ -450,49 +401,10 @@
}
FsUtils.updateTestStatus(TEST_STATUS_FILE, "#DONE");
- if(fs8000 != null)
- fs8000.stop();
- if(fs8080 != null)
- fs8080.stop();
- if(fs8443 != null)
- fs8443.stop();
-
+ ForwardService.getForwardService().stopForwardService();
activity.finish();
}
- private void startForwardServerIfNeeded() {
- try {
- if(fs8000 != null)
- fs8000.start();
- if(fs8080 != null)
- fs8080.start();
- if(fs8443 != null)
- fs8443.start();
- } catch (IOException ioe) {
- Log.w(LOGTAG, "failed to start forwarder. http tests will fail.", ioe);
- }
- }
-
- private String getTestUrl(String path) {
- String url = null;
- if (!path.startsWith(HTTP_TESTS_PREFIX)) {
- url = "file://" + path;
- } else {
- startForwardServerIfNeeded();
- if (path.startsWith(HTTPS_TESTS_PREFIX)) {
- // still cut the URL after "http/tests/"
- url = "https://127.0.0.1:8443/" + path.substring(HTTP_TESTS_PREFIX.length());
- } else if (!path.startsWith(HTTP_LOCAL_TESTS_PREFIX)
- && !path.startsWith(HTTP_MEDIA_TESTS_PREFIX)
- && !path.startsWith(HTTP_WML_TESTS_PREFIX)) {
- url = "http://127.0.0.1:8000/" + path.substring(HTTP_TESTS_PREFIX.length());
- } else {
- url = "file://" + path;
- }
- }
- return url;
- }
-
private String getTestPath() {
LayoutTestsAutoRunner runner = (LayoutTestsAutoRunner) getInstrumentation();
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
index 71d9758..50b7c3f 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTest.java
@@ -1,3 +1,19 @@
+/*
+ * 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.dumprendertree;
import android.app.Activity;
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
index 995c129..fbce78a 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/ReliabilityTestActivity.java
@@ -1,3 +1,19 @@
+/*
+ * 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.dumprendertree;
import android.app.Activity;
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index 663df83..074d90f 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -16,6 +16,8 @@
package com.android.dumprendertree;
+import com.android.dumprendertree.forwarder.ForwardService;
+
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
@@ -184,6 +186,7 @@
} catch (IOException ioe) {
Log.w(LOGTAG, "Failed to close test list file.", ioe);
}
+ ForwardService.getForwardService().stopForwardService();
finished();
}
@@ -215,10 +218,9 @@
builder.create().show();
return;
}
- url = "file://" + url;
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
- intent.putExtra(TestShellActivity.TEST_URL, url);
+ intent.putExtra(TestShellActivity.TEST_URL, FsUtils.getTestUrl(url));
intent.putExtra(TIMEOUT_IN_MILLIS, 10000);
executeIntent(intent);
}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/AdbUtils.java b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/AdbUtils.java
index 9a3e9c2..c2ecf3a 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/AdbUtils.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/AdbUtils.java
@@ -1,3 +1,19 @@
+/*
+ * 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.dumprendertree.forwarder;
import android.util.Log;
@@ -44,7 +60,6 @@
DataInputStream dis = new DataInputStream(localSocket.getInputStream());
OutputStream os = localSocket.getOutputStream();
int count_read = 0;
- byte[] buf = new byte[128];
if (localSocket == null || dis == null || os == null)
return -1;
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardServer.java b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardServer.java
index 74e018e..14f8fbe 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardServer.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardServer.java
@@ -1,3 +1,19 @@
+/*
+ * 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.dumprendertree.forwarder;
import android.util.Log;
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardService.java b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardService.java
new file mode 100644
index 0000000..8b7de6e
--- /dev/null
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/ForwardService.java
@@ -0,0 +1,115 @@
+/*
+ * 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.dumprendertree.forwarder;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+import android.util.Log;
+
+public class ForwardService {
+
+ private ForwardServer fs8000, fs8080, fs8443;
+
+ private static ForwardService inst;
+
+ private static final String LOGTAG = "ForwardService";
+
+ private static final String DEFAULT_TEST_HOST = "android-browser-test.mtv.corp.google.com";
+
+ private static final String FORWARD_HOST_CONF = "/sdcard/drt_forward_host.txt";
+
+ private ForwardService() {
+ int addr = getForwardHostAddr();
+ if (addr != -1) {
+ fs8000 = new ForwardServer(8000, addr, 8000);
+ fs8080 = new ForwardServer(8080, addr, 8080);
+ fs8443 = new ForwardServer(8443, addr, 8443);
+ }
+ }
+
+ public static ForwardService getForwardService() {
+ if (inst == null) {
+ inst = new ForwardService();
+ }
+ return inst;
+ }
+
+ public void startForwardService() {
+ try {
+ if (fs8000 != null)
+ fs8000.start();
+ if (fs8080 != null)
+ fs8080.start();
+ if (fs8443 != null)
+ fs8443.start();
+ } catch (IOException ioe) {
+ Log.w(LOGTAG, "failed to start forwarder. http tests will fail.", ioe);
+ return;
+ }
+ }
+
+ public void stopForwardService() {
+ if (fs8000 != null) {
+ fs8000.stop();
+ fs8000 = null;
+ }
+ if (fs8080 != null) {
+ fs8080.stop();
+ fs8080 = null;
+ }
+ if (fs8443 != null) {
+ fs8443.stop();
+ fs8443 = null;
+ }
+ Log.v(LOGTAG, "forwarders stopped.");
+ }
+
+ private static int getForwardHostAddr() {
+ int addr = -1;
+ String host = null;
+ File forwardHostConf = new File(FORWARD_HOST_CONF);
+ if (forwardHostConf.isFile()) {
+ BufferedReader hostReader = null;
+ try {
+ hostReader = new BufferedReader(new FileReader(forwardHostConf));
+ host = hostReader.readLine();
+ Log.v(LOGTAG, "read forward host from file: " + host);
+ } catch (IOException ioe) {
+ Log.v(LOGTAG, "cannot read forward host from file", ioe);
+ } finally {
+ if (hostReader != null) {
+ try {
+ hostReader.close();
+ } catch (IOException ioe) {
+ // burn!!!
+ }
+ }
+ }
+ }
+ if (host == null || host.length() == 0)
+ host = DEFAULT_TEST_HOST;
+ try {
+ addr = AdbUtils.resolve(host);
+ } catch (IOException ioe) {
+ Log.e(LOGTAG, "failed to resolve server address", ioe);
+ }
+ return addr;
+ }
+}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java
index e1e04a7..a1f3cdf 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/forwarder/Forwarder.java
@@ -1,3 +1,19 @@
+/*
+ * 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.dumprendertree.forwarder;
import android.util.Log;
diff --git a/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java b/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java
index dc959f5..aea124b 100644
--- a/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java
+++ b/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java
@@ -29,7 +29,6 @@
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
-import java.util.Hashtable;
import java.util.Set;
import java.util.Map;
import java.util.Map.Entry;
@@ -145,7 +144,7 @@
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
// Return cursor over specific set of values
- return getCursor(sTestValues1);
+ return getCursor(sTestValues1, 1);
}
}, null, 0);
} catch (OperationApplicationException e) {
@@ -153,11 +152,62 @@
}
}
+ public void testAssertNoValues() {
+ // Build an operation to assert values match provider
+ ContentProviderOperation op1 = ContentProviderOperation.newAssertQuery(sTestUri1)
+ .withExpectedCount(1).build();
+
+ try {
+ // Assert that values match from cursor
+ ContentProviderResult result = op1.apply(new TestContentProvider() {
+ public Cursor query(Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder) {
+ // Return cursor over specific set of values
+ return getCursor(sTestValues1, 1);
+ }
+ }, null, 0);
+ } catch (OperationApplicationException e) {
+ fail("newAssert() failed");
+ }
+
+ ContentProviderOperation op2 = ContentProviderOperation.newAssertQuery(sTestUri1)
+ .withExpectedCount(0).build();
+
+ try {
+ // Assert that values match from cursor
+ ContentProviderResult result = op2.apply(new TestContentProvider() {
+ public Cursor query(Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder) {
+ // Return cursor over specific set of values
+ return getCursor(sTestValues1, 0);
+ }
+ }, null, 0);
+ } catch (OperationApplicationException e) {
+ fail("newAssert() failed");
+ }
+
+ ContentProviderOperation op3 = ContentProviderOperation.newAssertQuery(sTestUri1)
+ .withExpectedCount(2).build();
+
+ try {
+ // Assert that values match from cursor
+ ContentProviderResult result = op3.apply(new TestContentProvider() {
+ public Cursor query(Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder) {
+ // Return cursor over specific set of values
+ return getCursor(sTestValues1, 5);
+ }
+ }, null, 0);
+ fail("we expect the exception to be thrown");
+ } catch (OperationApplicationException e) {
+ }
+ }
+
/**
* Build a {@link Cursor} with a single row that contains all values
* provided through the given {@link ContentValues}.
*/
- private Cursor getCursor(ContentValues contentValues) {
+ private Cursor getCursor(ContentValues contentValues, int numRows) {
final Set<Entry<String, Object>> valueSet = contentValues.valueSet();
final String[] keys = new String[valueSet.size()];
final Object[] values = new Object[valueSet.size()];
@@ -170,7 +220,9 @@
}
final MatrixCursor cursor = new MatrixCursor(keys);
- cursor.addRow(values);
+ for (i = 0; i < numRows; i++) {
+ cursor.addRow(values);
+ }
return cursor;
}
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index b00d8b0..b6b0e63 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -187,6 +187,13 @@
return 0;
}
+ // navigation hidden
+ if (getNavHiddenName(part.string(), &config)) {
+ *axis = AXIS_NAVHIDDEN;
+ *value = config.inputFlags;
+ return 0;
+ }
+
// navigation
if (getNavigationName(part.string(), &config)) {
*axis = AXIS_NAVIGATION;
@@ -217,7 +224,7 @@
Vector<String8> parts;
String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den;
- String8 touch, key, keysHidden, nav, size, vers;
+ String8 touch, key, keysHidden, nav, navHidden, size, vers;
const char *p = dir;
const char *q;
@@ -393,6 +400,19 @@
//printf("not keyboard: %s\n", part.string());
}
+ // navigation hidden
+ if (getNavHiddenName(part.string())) {
+ navHidden = part;
+
+ index++;
+ if (index == N) {
+ goto success;
+ }
+ part = parts[index];
+ } else {
+ //printf("not navHidden: %s\n", part.string());
+ }
+
if (getNavigationName(part.string())) {
nav = part;
@@ -443,6 +463,7 @@
this->touchscreen = touch;
this->keysHidden = keysHidden;
this->keyboard = key;
+ this->navHidden = navHidden;
this->navigation = nav;
this->screenSize = size;
this->version = vers;
@@ -476,6 +497,8 @@
s += ",";
s += keyboard;
s += ",";
+ s += navHidden;
+ s += ",";
s += navigation;
s += ",";
s += screenSize;
@@ -528,6 +551,10 @@
s += "-";
s += keyboard;
}
+ if (this->navHidden != "") {
+ s += "-";
+ s += navHidden;
+ }
if (this->navigation != "") {
s += "-";
s += navigation;
@@ -852,6 +879,30 @@
return false;
}
+bool AaptGroupEntry::getNavHiddenName(const char* name,
+ ResTable_config* out)
+{
+ uint8_t mask = 0;
+ uint8_t value = 0;
+ if (strcmp(name, kWildcardName) == 0) {
+ mask = out->MASK_NAVHIDDEN;
+ value = out->NAVHIDDEN_ANY;
+ } else if (strcmp(name, "navexposed") == 0) {
+ mask = out->MASK_NAVHIDDEN;
+ value = out->NAVHIDDEN_NO;
+ } else if (strcmp(name, "navhidden") == 0) {
+ mask = out->MASK_NAVHIDDEN;
+ value = out->NAVHIDDEN_YES;
+ }
+
+ if (mask != 0) {
+ if (out) out->inputFlags = (out->inputFlags&~mask) | value;
+ return true;
+ }
+
+ return false;
+}
+
bool AaptGroupEntry::getNavigationName(const char* name,
ResTable_config* out)
{
@@ -953,6 +1004,7 @@
if (v == 0) v = touchscreen.compare(o.touchscreen);
if (v == 0) v = keysHidden.compare(o.keysHidden);
if (v == 0) v = keyboard.compare(o.keyboard);
+ if (v == 0) v = navHidden.compare(o.navHidden);
if (v == 0) v = navigation.compare(o.navigation);
if (v == 0) v = screenSize.compare(o.screenSize);
if (v == 0) v = version.compare(o.version);
@@ -973,6 +1025,7 @@
getTouchscreenName(touchscreen.string(), ¶ms);
getKeysHiddenName(keysHidden.string(), ¶ms);
getKeyboardName(keyboard.string(), ¶ms);
+ getNavHiddenName(navHidden.string(), ¶ms);
getNavigationName(navigation.string(), ¶ms);
getScreenSizeName(screenSize.string(), ¶ms);
getVersionName(version.string(), ¶ms);
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 865efd1..26500a3 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -37,6 +37,7 @@
AXIS_TOUCHSCREEN,
AXIS_KEYSHIDDEN,
AXIS_KEYBOARD,
+ AXIS_NAVHIDDEN,
AXIS_NAVIGATION,
AXIS_SCREENSIZE,
AXIS_VERSION
@@ -64,6 +65,7 @@
String8 touchscreen;
String8 keysHidden;
String8 keyboard;
+ String8 navHidden;
String8 navigation;
String8 screenSize;
String8 version;
@@ -83,6 +85,7 @@
static bool getKeysHiddenName(const char* name, ResTable_config* out = NULL);
static bool getKeyboardName(const char* name, ResTable_config* out = NULL);
static bool getNavigationName(const char* name, ResTable_config* out = NULL);
+ static bool getNavHiddenName(const char* name, ResTable_config* out = NULL);
static bool getScreenSizeName(const char* name, ResTable_config* out = NULL);
static bool getVersionName(const char* name, ResTable_config* out = NULL);
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index f85aadd..954930e 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -42,24 +42,51 @@
public static final String priorityVarName = "priority";
/** {@hide} */
public static final String hiddenSSIDVarName = "scan_ssid";
+
/** {@hide} */
- public static final String eapVarName = "eap";
+ public class EnterpriseField {
+ private String varName;
+ private String value;
+
+ private EnterpriseField(String varName) {
+ this.varName = varName;
+ this.value = null;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public String varName() {
+ return varName;
+ }
+
+ public String value() {
+ return value;
+ }
+ }
+
/** {@hide} */
- public static final String phase2VarName = "phase2";
+ public EnterpriseField eap = new EnterpriseField("eap");
/** {@hide} */
- public static final String identityVarName = "identity";
+ public EnterpriseField phase2 = new EnterpriseField("phase2");
/** {@hide} */
- public static final String anonymousIdentityVarName = "anonymous_identity";
+ public EnterpriseField identity = new EnterpriseField("anonymous_identity");
/** {@hide} */
- public static final String passwordVarName = "password";
+ public EnterpriseField anonymous_identity = new EnterpriseField("anonymous_identity");
/** {@hide} */
- public static final String clientCertVarName = "client_cert";
+ public EnterpriseField password = new EnterpriseField("password");
/** {@hide} */
- public static final String caCertVarName = "ca_cert";
+ public EnterpriseField client_cert = new EnterpriseField("client_cert");
/** {@hide} */
- public static final String privateKeyVarName = "private_key";
+ public EnterpriseField private_key = new EnterpriseField("private_key");
/** {@hide} */
- public static final String privateKeyPasswdVarName = "private_key_passwd";
+ public EnterpriseField ca_cert = new EnterpriseField("ca_cert");
+
+ /** {@hide} */
+ public EnterpriseField[] enterpriseFields = {
+ eap, phase2, identity, anonymous_identity, password, client_cert,
+ private_key, ca_cert };
/**
* Recognized key management schemes.
@@ -267,44 +294,6 @@
*/
public BitSet allowedGroupCiphers;
- /* The following fields are used for EAP/IEEE8021X authentication */
-
- /**
- * The eap mode should be PEAP, TLS or TTLS.
- * {@hide}
- */
- public String eap;
- /**
- * The phase2 authenication could be PAP, MSCHAP, MSCHAP2, GTC.
- * {@hide}
- */
- public String phase2;
- /**
- * The identity of the user in string,
- * which is used for the authentication.
- * {@hide}
- */
- public String identity;
- /** {@hide} */
- public String anonymousIdentity;
- /** {@hide} */
- public String password;
- /** The path of the client certificate file.
- * {@hide}
- */
- public String clientCert;
- /** The path of the CA certificate file.
- * {@hide}
- */
- public String caCert;
- /** The path of the private key file.
- * {@hide}
- */
- public String privateKey;
- /** The password of the private key file if encrypted.
- * {@hide}
- */
- public String privateKeyPasswd;
public WifiConfiguration() {
networkId = -1;
@@ -320,15 +309,9 @@
wepKeys = new String[4];
for (int i = 0; i < wepKeys.length; i++)
wepKeys[i] = null;
- eap = null;
- phase2 = null;
- identity = null;
- anonymousIdentity = null;
- password = null;
- clientCert = null;
- caCert = null;
- privateKey = null;
- privateKeyPasswd = null;
+ for (EnterpriseField field : enterpriseFields) {
+ field.setValue(null);
+ }
}
public String toString() {
@@ -403,41 +386,11 @@
if (this.preSharedKey != null) {
sbuf.append('*');
}
- sbuf.append('\n').append(" eap: ");
- if (this.eap != null) {
- sbuf.append(eap);
- }
- sbuf.append('\n').append(" phase2: ");
- if (this.phase2 != null) {
- sbuf.append(phase2);
- }
- sbuf.append('\n').append(" Identity: ");
- if (this.identity != null) {
- sbuf.append(identity);
- }
- sbuf.append('\n').append(" AnonymousIdentity: ");
- if (this.anonymousIdentity != null) {
- sbuf.append(anonymousIdentity);
- }
- sbuf.append('\n').append(" Password: ");
- if (this.password != null) {
- sbuf.append(password);
- }
- sbuf.append('\n').append(" ClientCert: ");
- if (this.clientCert != null) {
- sbuf.append(clientCert);
- }
- sbuf.append('\n').append(" CaCert: ");
- if (this.caCert != null) {
- sbuf.append(caCert);
- }
- sbuf.append('\n').append(" PrivateKey: ");
- if (this.privateKey != null) {
- sbuf.append(privateKey);
- }
- sbuf.append('\n').append(" PrivateKeyPasswd: ");
- if (this.privateKeyPasswd != null) {
- sbuf.append(privateKeyPasswd);
+
+ for (EnterpriseField field : enterpriseFields) {
+ sbuf.append('\n').append(" " + field.varName() + ": ");
+ String value = field.value();
+ if (value != null) sbuf.append(value);
}
sbuf.append('\n');
return sbuf.toString();
@@ -497,15 +450,10 @@
writeBitSet(dest, allowedAuthAlgorithms);
writeBitSet(dest, allowedPairwiseCiphers);
writeBitSet(dest, allowedGroupCiphers);
- dest.writeString(eap);
- dest.writeString(phase2);
- dest.writeString(identity);
- dest.writeString(anonymousIdentity);
- dest.writeString(password);
- dest.writeString(clientCert);
- dest.writeString(caCert);
- dest.writeString(privateKey);
- dest.writeString(privateKeyPasswd);
+
+ for (EnterpriseField field : enterpriseFields) {
+ dest.writeString(field.value());
+ }
}
/** Implement the Parcelable interface {@hide} */
@@ -528,15 +476,10 @@
config.allowedAuthAlgorithms = readBitSet(in);
config.allowedPairwiseCiphers = readBitSet(in);
config.allowedGroupCiphers = readBitSet(in);
- config.eap = in.readString();
- config.phase2 = in.readString();
- config.identity = in.readString();
- config.anonymousIdentity = in.readString();
- config.password = in.readString();
- config.clientCert = in.readString();
- config.caCert = in.readString();
- config.privateKey = in.readString();
- config.privateKeyPasswd = in.readString();
+
+ for (EnterpriseField field : config.enterpriseFields) {
+ field.setValue(in.readString());
+ }
return config;
}
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 9a11404..e3d8bf4 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -1350,7 +1350,7 @@
*/
private synchronized void requestPolledInfo(WifiInfo info, boolean polling)
{
- int newRssi = WifiNative.getRssiCommand();
+ int newRssi = (polling ? WifiNative.getRssiApproxCommand() : WifiNative.getRssiCommand());
if (newRssi != -1 && -200 < newRssi && newRssi < 256) { // screen out invalid values
/* some implementations avoid negative values by adding 256
* so we need to adjust for that here.