diff options
100 files changed, 3149 insertions, 1196 deletions
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 parse_strings(char *data, int data_len, int ntokens, ...) 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 @@ static void do_unlock(LPC_MARSHAL *cmd, LPC_MARSHAL *reply) // 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 @@ int server_main(const int argc, const char *argv[]) // 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.util.Pair; 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 @@ public class AccountManagerService extends IAccountManager.Stub { } private boolean saveAuthTokenToDatabase(Account account, String type, String authToken) { + cancelNotification(getSigninRequiredNotificationId(account)); SQLiteDatabase db = mOpenHelper.getWritableDatabase(); db.beginTransaction(); try { @@ -523,7 +523,7 @@ public class AccountManagerService extends IAccountManager.Stub { checkAuthenticateAccountsPermission(account); long identityToken = clearCallingIdentity(); try { - cacheAuthToken(account, authTokenType, authToken); + saveAuthTokenToDatabase(account, authTokenType, authToken); } finally { restoreCallingIdentity(identityToken); } @@ -686,7 +686,8 @@ public class AccountManagerService extends IAccountManager.Stub { "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 @@ public class AccountManagerService extends IAccountManager.Stub { 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 @@ public class AccountManagerService extends IAccountManager.Stub { } } - 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.app.SearchManager.DialogCursorProtocol; 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.Log; 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 @@ class SuggestionsAdapter extends ResourceCursorAdapter { // 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 @@ class SuggestionsAdapter extends ResourceCursorAdapter { } } } - 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 @@ public final class BluetoothDevice implements Parcelable { } /** @hide */ - public String[] getUuids() { + public ParcelUuid[] getUuids() { try { return sService.getRemoteUuids(mAddress); } catch (RemoteException e) {Log.e(TAG, "", e);} @@ -511,7 +511,7 @@ public final class BluetoothDevice implements Parcelable { } /** @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 @@ public final class BluetoothUuid { * 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 boolean isAudioSource(UUID uuid) { + 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(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 @@ interface IBluetooth 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 @@ public class ContentProviderOperation implements Parcelable { } 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 @@ public class ContentProviderOperation implements Parcelable { /** 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 88a4d02..307899a 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -527,12 +527,22 @@ public abstract class ContentResolver { } } - 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 @@ import java.util.Set; * <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 class Intent implements Parcelable { */ 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 @@ public class Intent implements Parcelable { * {@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 class ActivityInfo extends ComponentInfo 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 final class Configuration implements Parcelable, Comparable<Configuration */ 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration keyboardHidden = o.keyboardHidden; hardKeyboardHidden = o.hardKeyboardHidden; navigation = o.navigation; + navigationHidden = o.navigationHidden; orientation = o.orientation; screenLayout = o.screenLayout; } @@ -198,6 +211,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration keyboardHidden = KEYBOARDHIDDEN_UNDEFINED; hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED; navigation = NAVIGATION_UNDEFINED; + navigationHidden = NAVIGATIONHIDDEN_UNDEFINED; orientation = ORIENTATION_UNDEFINED; screenLayout = SCREENLAYOUT_SIZE_UNDEFINED; } @@ -286,6 +302,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration && 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration dest.writeInt(keyboardHidden); dest.writeInt(hardKeyboardHidden); dest.writeInt(navigation); + dest.writeInt(navigationHidden); dest.writeInt(orientation); dest.writeInt(screenLayout); } @@ -448,6 +474,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration keyboardHidden = source.readInt(); hardKeyboardHidden = source.readInt(); navigation = source.readInt(); + navigationHidden = source.readInt(); orientation = source.readInt(); screenLayout = source.readInt(); } @@ -478,6 +505,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 @@ public final class Configuration implements Parcelable, Comparable<Configuration 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 @@ import android.os.Message; * <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 @@ import android.os.Message; * <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 @@ public class Camera { * 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 @@ public class Camera { /** * 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 @@ public class Camera { * 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 @@ public class Camera { * 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 @@ public class Camera { } /** - * 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 @@ public class Camera { /** * 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.text.TextUtils; 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 @@ public abstract class DialogPreference extends Preference implements 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 @@ public class EditTextPreference extends DialogPreference { 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 final class ContactsContract { 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 @@ public final class ContactsContract { * 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 final class ContactsContract { 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 @@ public final class Settings { /** * 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.BluetoothAdapter; 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.io.PrintWriter; 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 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { } 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 @@ public class BluetoothA2dpService extends IBluetoothA2dp.Stub { 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.BluetoothAdapter; 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.os.Message; import android.util.Log; import java.util.HashMap; -import java.util.UUID; /** * TODO: Move this to @@ -501,7 +501,7 @@ class BluetoothEventLoop { } 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.io.UnsupportedEncodingException; 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 @@ public class BluetoothService extends IBluetooth.Stub { /** - * Gets the remote features encoded as bit mask. - * - * Note: This method may be obsoleted soon. + * Gets the UUIDs supported by the remote device * - * @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 @@ public class BluetoothService extends IBluetooth.Stub { * 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 @@ public class BluetoothService extends IBluetooth.Stub { 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 interface InputType { */ 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 @@ public class QwertyKeyListener extends BaseKeyListener { 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 abstract class LayoutInflater { 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 @@ public abstract class LayoutInflater { 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 @@ public abstract class LayoutInflater { } 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 interface WindowManager extends ViewManager { */ 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.KeyCharacterMap; 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 @@ import java.util.ArrayList; @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 @@ import java.util.ArrayList; 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 @@ public class WebView extends AbsoluteLayout 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 @@ public class WebView extends AbsoluteLayout 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 @@ public class WebView extends AbsoluteLayout 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.util.AttributeSet; 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 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList 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 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList 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 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList 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 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList //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 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList 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 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList @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 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList * 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); - /** - * Convenience method for binding {@link Contacts} header details from a - * {@link Contacts#CONTENT_URI} reference. - */ - public void bindContactUri(Uri contactUri) { - mQueryHandler.startQuery(TOKEN_CONTACT_INFO, null, contactUri, HEADER_PROJECTION, - null, null, null); + startContactQuery(contactLookupUri); } /** - * Convenience method for binding {@link Activities} header details from a - * {@link Activities#CONTENT_CONTACT_STATUS_URI}. + * Convenience method for binding all available data from an existing + * contact. + * + * @param conatctUri a {Contacts.CONTENT_URI} style URI. */ - public void bindSocialUri(Uri contactSocial) { - mStatusUri = contactSocial; - mQueryHandler.startQuery(TOKEN_SOCIAL, null, mStatusUri, SOCIAL_PROJECTION, null, null, - null); + public void bindFromContactUri(Uri contactUri) { + mContactUri = contactUri; + long contactId = ContentUris.parseId(contactUri); + + startContactQuery(contactUri); + startSocialQuery(ContentUris.withAppendedId( + Activities.CONTENT_CONTACT_STATUS_URI, contactId)); } /** @@ -338,21 +383,9 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList * 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 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList * 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 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList // 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 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList 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 @@ public class ContactHeaderWidget extends FrameLayout implements View.OnClickList 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 @@ package com.android.internal.widget; 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.util.Log; 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 @@ public class RotarySelector extends View { 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 @@ public class RotarySelector extends View { 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 @@ public class RotarySelector extends View { 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 @@ public class RotarySelector extends View { 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 @@ public class RotarySelector extends View { 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 @@ public class RotarySelector extends View { // 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 @@ public class RotarySelector extends View { 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 @@ public class RotarySelector extends View { 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 @@ public class RotarySelector extends View { 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) { - 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); + final int action = event.getAction(); + switch (action) { + case MotionEvent.ACTION_DOWN: + if (DBG) log("touch-down"); + mTriggered = false; + if (mGrabbedState != NOTHING_GRABBED) { + reset(); + invalidate(); } - } 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); + 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); } - } - } 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; - } + break; - mTouchDragOffset = 0; - mGrabbedState = RotarySelector.NOTHING_GRABBED; - invalidate(); - } else if (event.getAction() == MotionEvent.ACTION_CANCEL) { - if (DBG) log("touch-cancel"); - reset(); - invalidate(); + 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(); + break; } return true; } @@ -446,7 +451,7 @@ public class RotarySelector extends View { 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 @@ static jboolean connectSinkNative(JNIEnv *env, jobject object, jstring path) { 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); - env->ReleaseStringUTFChars(path, c_path); + bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat, + c_path, "org.bluez.AudioSink", "Connect", + DBUS_TYPE_INVALID); - 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; + env->ReleaseStringUTFChars(path, c_path); + return ret ? JNI_TRUE : JNI_FALSE; } #endif return JNI_FALSE; @@ -161,23 +151,13 @@ static jboolean disconnectSinkNative(JNIEnv *env, jobject object, 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); - env->ReleaseStringUTFChars(path, c_path); + bool ret = dbus_func_args_async(env, nat->conn, -1, NULL, NULL, nat, + c_path, "org.bluez.AudioSink", "Disconnect", + DBUS_TYPE_INVALID); - 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; + env->ReleaseStringUTFChars(path, c_path); + 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 Binary files differnew file mode 100644 index 0000000..c13dd26 --- /dev/null +++ b/core/res/res/drawable-hdpi/title_bar_medium.png diff --git a/core/res/res/drawable-mdpi/title_bar_medium.png b/core/res/res/drawable-mdpi/title_bar_medium.png Binary files differnew file mode 100644 index 0000000..9d01f79 --- /dev/null +++ b/core/res/res/drawable-mdpi/title_bar_medium.png 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..b710acb 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_MODULE_PATH := $(TARGET_OUT_ETC)/permissions 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 @@ resources for a fully specified configuration would look like this:</p> <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 @@ MyApp/ <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 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { 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 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { @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 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { 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 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { boolean mCanConstantState; boolean mPaddingChecked = false; + + boolean mDither = DEFAULT_DITHER; DrawableContainerState(DrawableContainerState orig, DrawableContainer owner, Resources res) { @@ -323,6 +324,8 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { 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 @@ public class RenderScript { 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 @@ public class Script extends BaseObj { 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 @@ public class Script extends BaseObj { 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 @@ public class Script extends BaseObj { 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 @@ public class Script extends BaseObj { 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 @@ nScriptSetType(JNIEnv *_env, jobject _this, jint type, jboolean writable, jstrin } 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 @@ static JNINativeMethod methods[] = { {"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 @@ private: 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 @@ struct ResTable_config 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 @@ struct ResTable_config 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 @@ struct ResTable_config 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 @@ struct ResTable_config } } + 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 @@ struct ResTable_config 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 class ServiceCommand { 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 @@ public class ServiceCommand { if (mSocket != null) { return true; } - if (DBG) Log.d(mTag, "connecting..."); try { mSocket = new LocalSocket(); @@ -80,7 +77,6 @@ public class ServiceCommand { } 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::ThreadBase::TrackBase::TrackBase( } } -AudioFlinger::PlaybackThread::TrackBase::~TrackBase() +AudioFlinger::ThreadBase::TrackBase::~TrackBase() { if (mCblk) { mCblk->~audio_track_cblk_t(); // destroy our shared-structure. @@ -2081,7 +2081,7 @@ AudioFlinger::PlaybackThread::TrackBase::~TrackBase() 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 @@ void AudioFlinger::PlaybackThread::TrackBase::releaseBuffer(AudioBufferProvider: 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 @@ bool AudioFlinger::PlaybackThread::TrackBase::step() { 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 @@ void AudioFlinger::PlaybackThread::TrackBase::reset() { 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 @@ ScriptSetType { 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 @@ Script::Script() 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_ScriptSetType(Context * rsc, RsType vt, uint32_t slot, bool writable, c } } +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 ProgramFragmentStore; class Script : public ObjectBase { public: + typedef void (* InvokeFunc_t)(void); Script(); virtual ~Script(); @@ -52,17 +53,22 @@ public: 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 @@ bool ScriptC::run(Context *rsc, uint32_t launchIndex) 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 @@ static ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) 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 @@ void ScriptCState::runCompiler(Context *rsc) 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]); + } + } + + 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]); } } - mEnviroment.mFragment.set(rsc->getDefaultProgramFragment()); - mEnviroment.mVertex.set(rsc->getDefaultProgramVertex()); - mEnviroment.mFragmentStore.set(rsc->getDefaultProgramFragmentStore()); + s->mEnviroment.mFragment.set(rsc->getDefaultProgramFragment()); + s->mEnviroment.mVertex.set(rsc->getDefaultProgramVertex()); + s->mEnviroment.mFragmentStore.set(rsc->getDefaultProgramFragmentStore()); - if (mProgram.mScript) { + 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 @@ void ScriptCState::runCompiler(Context *rsc) 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 @@ void ScriptCState::runCompiler(Context *rsc) 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 @@ void ScriptCState::runCompiler(Context *rsc) 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 @@ void ScriptCState::appendTypes(String8 *str) 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_ScriptCBegin(Context * rsc) 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 @@ RsScript rsi_ScriptCCreate(Context * rsc) { 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 @@ public: 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 @@ struct BlurColor565 } }; +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 @@ status_t blurFilter( 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..cc913cb 100644 --- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp +++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp @@ -174,6 +174,13 @@ void DisplayHardware::init(uint32_t dpy) 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 @@ uint32_t Layer::doTransaction(uint32_t flags) // 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 @@ uint32_t Layer::doTransaction(uint32_t flags) // 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 @@ uint32_t Layer::doTransaction(uint32_t flags) 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 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions) 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 @@ const char* const LayerBlur::typeID = "LayerBlur"; 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 @@ void LayerBlur::onDraw(const Region& clip) const // 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 @@ void LayerBlur::onDraw(const Region& clip) const 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 @@ void LayerBlur::onDraw(const Region& clip) const 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 @@ void LayerBlur::onDraw(const Region& clip) const 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 @@ private: 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 @@ LayerBuffer::OverlaySource::OverlaySource(LayerBuffer& layer, *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 @@ public class AudioManager { /** * 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 @@ public class AudioManager { * 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 @@ public class AudioManager { /** * 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 @@ public class AudioManager { * <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 @@ public class AudioManager { /** * 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 @@ public class AudioManager { /** * 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 @@ public class AudioManager { /** * 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 @@ public class AudioManager { /** * 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 @@ public class AudioManager { /** * 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.HashMap; 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(); /** - * The following 3 static methods are handy routines for atomic operation - * of underlying jhead library. It retrieves EXIF data and then release - * ExifInterface immediately. + * Reads Exif tags from the specified JPEG file. */ - 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 ExifInterface(String filename) throws IOException { + mFilename = filename; + loadAttributes(); } - 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; - } + /** + * 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 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 @@ public class ExifInterface { 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 @@ public class ExifInterface { } /** - * 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 @@ public class ExifInterface { } /** - * 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 @@ public class ExifInterface { 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 class ExifInterface { } } - public static float convertRationalLatLonToFloat( + private static float convertRationalLatLonToFloat( String rationalString, String ref) { try { String [] parts = rationalString.split(","); @@ -377,42 +348,6 @@ public class ExifInterface { } } - 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 @@ public class MediaScanner 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 @@ SoftwareRenderer::~SoftwareRenderer() { 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 @@ void SoftwareRenderer::render( 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 @@ void SoftwareRenderer::renderCbYCrY( 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 java.io.Writer; 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 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me 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 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me 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 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me 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 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me 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 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me 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 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me 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 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me 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 @@ public class MediaRecorderStressTest extends ActivityInstrumentationTestCase2<Me 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 @@ using namespace android; 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 @@ int main(int argc, char** argv) 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); + fprintf(stderr, "Chosen config: 0x%08x\n", (unsigned long) config); + + checkEglError("EGLUtils::selectConfigForNativeWindow"); surface = eglCreateWindowSurface(dpy, config, window, NULL); + checkEglError("eglCreateWindowSurface"); - EGLint gl2_0Attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; + 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 @@ class BackupManagerService extends IBackupManager.Stub { 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 @@ class DockObserver extends UEventObserver { 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 @@ class PackageManagerService extends IPackageManager.Stub { 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 @@ class PackageManagerService extends IPackageManager.Stub { // 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 @@ class PackageManagerService extends IPackageManager.Stub { 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 @@ class PackageManagerService extends IPackageManager.Stub { // 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 @@ class PackageManagerService extends IPackageManager.Stub { 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 @@ public class WifiService extends IWifiManager.Stub { } } } + + for (WifiConfiguration.EnterpriseField field : + config.enterpriseFields) { + value = WifiNative.getNetworkVariableCommand(netId, + field.varName()); + if (!TextUtils.isEmpty(value)) { + field.setValue(value); + } + } } /** @@ -877,103 +886,20 @@ public class WifiService extends IWifiManager.Stub { 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); - } - 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); + varName, + value)) { + if (DBG) { + Log.d(TAG, config.SSID + ": failed to set " + varName + + ": " + value); + } + break setVariables; } - 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 @@ public class WindowManagerService extends IWindowManager.Stub // 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 @@ public class WindowManagerService extends IWindowManager.Stub && !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 @@ public class WindowManagerService extends IWindowManager.Stub int mLastLayer; boolean mHaveFrame; boolean mObscured; + boolean mTurnOnScreen; WindowState mNextOutsideTouch; @@ -7049,7 +7056,7 @@ public class WindowManagerService extends IWindowManager.Stub + " 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class PhoneNumberUtils 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 @@ public class PhoneNumberUtils } /** + * 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 class CallerInfo { 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 class CallerInfo { 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 @@ public class CallerInfo { } /** + * @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 @@ public class CallerInfo { 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 @@ public class CallerInfo { 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 @@ public class CallerInfoAsyncQuery { 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 @@ public class CallerInfoAsyncQuery { // 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 @@ public class CallerInfoAsyncQuery { //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 @@ public class CallerInfoAsyncQuery { // 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 class TelephonyUnitTestRunner extends InstrumentationTestRunner { 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 @@ public class CallerInfoUnitTest extends AndroidTestCase { 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 class HandlerThreadTest extends TestCase { 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 @@ public class HandlerThreadTest extends TestCase { 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 @@ public class FileFilter { // 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 @@ import java.io.IOException; 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 @@ public class FsUtils { 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 @@ package com.android.dumprendertree; 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 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh 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 class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh 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 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh 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 @@ public class LayoutTestsAutoTest extends ActivityInstrumentationTestCase2<TestSh } 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 @@ public class TestShellActivity extends Activity implements LayoutTestController } catch (IOException ioe) { Log.w(LOGTAG, "Failed to close test list file.", ioe); } + ForwardService.getForwardService().stopForwardService(); finished(); } @@ -215,10 +218,9 @@ public class TestShellActivity extends Activity implements LayoutTestController 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 @@ public class AdbUtils { 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.Constructor; 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 class ContentProviderOperationTest extends TestCase { 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 class ContentProviderOperationTest extends TestCase { } } + 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 @@ public class ContentProviderOperationTest extends TestCase { } 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 @@ AaptGroupEntry::parseNamePart(const String8& part, int* axis, uint32_t* value) 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 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType) 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 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType) //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 @@ success: 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 @@ AaptGroupEntry::toString() const s += ","; s += keyboard; s += ","; + s += navHidden; + s += ","; s += navigation; s += ","; s += screenSize; @@ -528,6 +551,10 @@ AaptGroupEntry::toDirName(const String8& resType) const s += "-"; s += keyboard; } + if (this->navHidden != "") { + s += "-"; + s += navHidden; + } if (this->navigation != "") { s += "-"; s += navigation; @@ -852,6 +879,30 @@ bool AaptGroupEntry::getKeyboardName(const char* name, 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 @@ int AaptGroupEntry::compare(const AaptGroupEntry& o) const 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 @@ ResTable_config AaptGroupEntry::toParams() const 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 @@ enum { AXIS_TOUCHSCREEN, AXIS_KEYSHIDDEN, AXIS_KEYBOARD, + AXIS_NAVHIDDEN, AXIS_NAVIGATION, AXIS_SCREENSIZE, AXIS_VERSION @@ -64,6 +65,7 @@ public: String8 touchscreen; String8 keysHidden; String8 keyboard; + String8 navHidden; String8 navigation; String8 screenSize; String8 version; @@ -83,6 +85,7 @@ public: 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 class WifiConfiguration implements Parcelable { public static final String priorityVarName = "priority"; /** {@hide} */ public static final String hiddenSSIDVarName = "scan_ssid"; + + /** {@hide} */ + 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 eapVarName = "eap"; + public EnterpriseField eap = new EnterpriseField("eap"); /** {@hide} */ - public static final String phase2VarName = "phase2"; + public EnterpriseField phase2 = new EnterpriseField("phase2"); /** {@hide} */ - public static final String identityVarName = "identity"; + public EnterpriseField identity = new EnterpriseField("anonymous_identity"); /** {@hide} */ - public static final String anonymousIdentityVarName = "anonymous_identity"; + public EnterpriseField anonymous_identity = new EnterpriseField("anonymous_identity"); /** {@hide} */ - public static final String passwordVarName = "password"; + public EnterpriseField password = new EnterpriseField("password"); /** {@hide} */ - public static final String clientCertVarName = "client_cert"; + public EnterpriseField client_cert = new EnterpriseField("client_cert"); /** {@hide} */ - public static final String caCertVarName = "ca_cert"; + public EnterpriseField private_key = new EnterpriseField("private_key"); /** {@hide} */ - public static final String privateKeyVarName = "private_key"; + public EnterpriseField ca_cert = new EnterpriseField("ca_cert"); + /** {@hide} */ - public static final String privateKeyPasswdVarName = "private_key_passwd"; + public EnterpriseField[] enterpriseFields = { + eap, phase2, identity, anonymous_identity, password, client_cert, + private_key, ca_cert }; /** * Recognized key management schemes. @@ -267,44 +294,6 @@ public class WifiConfiguration implements Parcelable { */ 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 @@ public class WifiConfiguration implements Parcelable { 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 @@ public class WifiConfiguration implements Parcelable { 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 @@ public class WifiConfiguration implements Parcelable { 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 @@ public class WifiConfiguration implements Parcelable { 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 @@ public class WifiStateTracker extends NetworkStateTracker { */ 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. |
