Merge change 25158 into eclair
* changes:
Another software color conversion implementation, this time OMX_QCOM_COLOR_FormatYVU420SemiPlanar => rgb565.
diff --git a/api/current.xml b/api/current.xml
index 7562f2e..e438f6e 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -10659,6 +10659,17 @@
visibility="public"
>
</field>
+<field name="screen_background_light_transparent"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17301674"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="spinner_background"
type="int"
transient="false"
@@ -12714,6 +12725,17 @@
visibility="public"
>
</field>
+<field name="Theme_Light_WallpaperSettings"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973922"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="Theme_NoDisplay"
type="int"
transient="false"
@@ -12802,6 +12824,17 @@
visibility="public"
>
</field>
+<field name="Theme_WallpaperSettings"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973921"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="Theme_Wallpaper_NoTitleBar"
type="int"
transient="false"
@@ -43753,6 +43786,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"
@@ -44075,6 +44141,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"
@@ -66923,6 +66999,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"
@@ -77281,6 +77368,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"
@@ -117496,6 +117964,37 @@
</implements>
</interface>
</package>
+<package name="android.service.wallpaper"
+>
+<class name="WallpaperSettingsActivity"
+ extends="android.preference.PreferenceActivity"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="WallpaperSettingsActivity"
+ type="android.service.wallpaper.WallpaperSettingsActivity"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<field name="EXTRA_PREVIEW_MODE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.service.wallpaper.PREVIEW_MODE""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+</package>
<package name="android.speech"
>
<class name="RecognizerIntent"
@@ -159296,6 +159795,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"
@@ -167438,24 +167948,13 @@
</parameter>
</method>
</class>
-<class name="PluginStub"
- extends="java.lang.Object"
+<interface name="PluginStub"
abstract="true"
static="false"
final="false"
deprecated="not deprecated"
visibility="public"
>
-<constructor name="PluginStub"
- type="android.webkit.PluginStub"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="npp" type="int">
-</parameter>
-</constructor>
<method name="getEmbeddedView"
return="android.view.View"
abstract="true"
@@ -167466,6 +167965,8 @@
deprecated="not deprecated"
visibility="public"
>
+<parameter name="NPP" type="int">
+</parameter>
<parameter name="context" type="android.content.Context">
</parameter>
</method>
@@ -167479,10 +167980,12 @@
deprecated="not deprecated"
visibility="public"
>
+<parameter name="NPP" type="int">
+</parameter>
<parameter name="context" type="android.content.Context">
</parameter>
</method>
-</class>
+</interface>
<class name="SslErrorHandler"
extends="android.os.Handler"
abstract="false"
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 8f7e8ca..4f9531e 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -20,14 +20,15 @@
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.ContentResolver.OpenResourceIdResult;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.database.Cursor;
+import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.DrawableContainer;
import android.graphics.drawable.StateListDrawable;
import android.net.Uri;
import android.os.Bundle;
@@ -38,14 +39,15 @@
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.Filter;
import android.widget.ImageView;
import android.widget.ResourceCursorAdapter;
import android.widget.TextView;
-import android.widget.Filter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import java.util.List;
import java.util.WeakHashMap;
/**
@@ -580,14 +582,26 @@
// Not cached, try using it as a plain resource ID in the provider's context.
int resourceId = Integer.parseInt(drawableId);
drawable = mProviderContext.getResources().getDrawable(resourceId);
- if (DBG) Log.d(LOG_TAG, "Found icon by resource ID: " + drawableId);
} catch (NumberFormatException nfe) {
- // The id was not an integer resource id.
- // Let the ContentResolver handle content, android.resource and file URIs.
+ // The id was not an integer resource id, use it as a URI
try {
Uri uri = Uri.parse(drawableId);
- InputStream stream = mProviderContext.getContentResolver().openInputStream(uri);
- if (stream != null) {
+ String scheme = uri.getScheme();
+ if (ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme)) {
+ // Load drawables through Resources, to get the source density information
+ OpenResourceIdResult r =
+ mProviderContext.getContentResolver().getResourceId(uri);
+ try {
+ drawable = r.r.getDrawable(r.id);
+ } catch (Resources.NotFoundException ex) {
+ throw new FileNotFoundException("Resource does not exist: " + uri);
+ }
+ } else {
+ // Let the ContentResolver handle content and file URIs.
+ InputStream stream = mProviderContext.getContentResolver().openInputStream(uri);
+ if (stream == null) {
+ throw new FileNotFoundException("Failed to open " + uri);
+ }
try {
drawable = Drawable.createFromStream(stream, null);
} finally {
@@ -598,22 +612,25 @@
}
}
}
- if (DBG) Log.d(LOG_TAG, "Opened icon input stream: " + drawableId);
} catch (FileNotFoundException fnfe) {
- if (DBG) Log.d(LOG_TAG, "Icon stream not found: " + drawableId);
+ Log.w(LOG_TAG, "Icon not found: " + drawableId + ", " + fnfe.getMessage());
// drawable = null;
}
-
- // If we got a drawable for this resource id, then stick it in the
- // map so we don't do this lookup again.
- if (drawable != null) {
- mOutsideDrawablesCache.put(drawableId, drawable.getConstantState());
- }
} catch (Resources.NotFoundException nfe) {
- if (DBG) Log.d(LOG_TAG, "Icon resource not found: " + drawableId);
+ Log.w(LOG_TAG, "Icon resource not found: " + drawableId);
// drawable = null;
}
+ if (drawable == null) {
+ if (DBG) Log.d(LOG_TAG, "Didn't find icon: " + drawableId);
+ } else {
+ if (DBG) {
+ Log.d(LOG_TAG, "Found icon: " + drawableId);
+ }
+ // Cache it so we don't do this lookup again
+ mOutsideDrawablesCache.put(drawableId, drawable.getConstantState());
+ }
+
return drawable;
}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 88a4d02f..307899a 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -527,12 +527,22 @@
}
}
- class OpenResourceIdResult {
- Resources r;
- int id;
+ /**
+ * A resource identified by the {@link Resources} that contains it, and a resource id.
+ *
+ * @hide
+ */
+ public class OpenResourceIdResult {
+ public Resources r;
+ public int id;
}
-
- OpenResourceIdResult getResourceId(Uri uri) throws FileNotFoundException {
+
+ /**
+ * Resolves an android.resource URI to a {@link Resources} and a resource id.
+ *
+ * @hide
+ */
+ public OpenResourceIdResult getResourceId(Uri uri) throws FileNotFoundException {
String authority = uri.getAuthority();
Resources r;
if (TextUtils.isEmpty(authority)) {
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 1e590f0..7859d5a 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -583,13 +583,8 @@
return;
}
- if (!getConnectivityManager().getBackgroundDataSetting()) {
- if (isLoggable) {
- Log.v(TAG, "not syncing because background data usage isn't allowed");
- }
- setStatusText("Sync is disabled.");
- return;
- }
+ final boolean backgroundDataUsageAllowed =
+ getConnectivityManager().getBackgroundDataSetting();
if (mAccounts == null) setStatusText("The accounts aren't known yet.");
if (!mDataConnectionIsConnected) setStatusText("No data connection");
@@ -686,7 +681,8 @@
} else {
final boolean syncAutomatically = masterSyncAutomatically
&& mSyncStorageEngine.getSyncAutomatically(account, authority);
- boolean syncAllowed = manualSync || syncAutomatically;
+ boolean syncAllowed =
+ manualSync || (backgroundDataUsageAllowed && syncAutomatically);
if (!syncAllowed) {
if (isLoggable) {
Log.d(TAG, "scheduleSync: sync of " + account + ", " + authority
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 27783ef..1ad13c5 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -217,7 +217,9 @@
public static final int CONFIG_KEYBOARD = 0x0010;
/**
* Bit in {@link #configChanges} that indicates that the activity
- * can itself handle changes to the keyboard being hidden/exposed.
+ * can itself handle changes to the keyboard or navigation being hidden/exposed.
+ * Note that inspite of the name, this applies to the changes to any
+ * hidden states: keyboard or navigation.
* Set from the {@link android.R.attr#configChanges} attribute.
*/
public static final int CONFIG_KEYBOARD_HIDDEN = 0x0020;
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index cbf8410..1fe34b5 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -138,6 +138,18 @@
*/
public int navigation;
+ public static final int NAVIGATIONHIDDEN_UNDEFINED = 0;
+ public static final int NAVIGATIONHIDDEN_NO = 1;
+ public static final int NAVIGATIONHIDDEN_YES = 2;
+
+ /**
+ * A flag indicating whether any 5-way or DPAD navigation available.
+ * This will be set on a device with a mechanism to hide the navigation
+ * controls from the user, when that mechanism is closed. One of:
+ * {@link #NAVIGATIONHIDDEN_NO}, {@link #NAVIGATIONHIDDEN_YES}.
+ */
+ public int navigationHidden;
+
public static final int ORIENTATION_UNDEFINED = 0;
public static final int ORIENTATION_PORTRAIT = 1;
public static final int ORIENTATION_LANDSCAPE = 2;
@@ -174,6 +186,7 @@
keyboardHidden = o.keyboardHidden;
hardKeyboardHidden = o.hardKeyboardHidden;
navigation = o.navigation;
+ navigationHidden = o.navigationHidden;
orientation = o.orientation;
screenLayout = o.screenLayout;
}
@@ -198,6 +211,8 @@
sb.append(hardKeyboardHidden);
sb.append(" nav=");
sb.append(navigation);
+ sb.append("/");
+ sb.append(navigationHidden);
sb.append(" orien=");
sb.append(orientation);
sb.append(" layout=");
@@ -219,6 +234,7 @@
keyboardHidden = KEYBOARDHIDDEN_UNDEFINED;
hardKeyboardHidden = HARDKEYBOARDHIDDEN_UNDEFINED;
navigation = NAVIGATION_UNDEFINED;
+ navigationHidden = NAVIGATIONHIDDEN_UNDEFINED;
orientation = ORIENTATION_UNDEFINED;
screenLayout = SCREENLAYOUT_SIZE_UNDEFINED;
}
@@ -286,6 +302,11 @@
changed |= ActivityInfo.CONFIG_NAVIGATION;
navigation = delta.navigation;
}
+ if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
+ && navigationHidden != delta.navigationHidden) {
+ changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
+ navigationHidden = delta.navigationHidden;
+ }
if (delta.orientation != ORIENTATION_UNDEFINED
&& orientation != delta.orientation) {
changed |= ActivityInfo.CONFIG_ORIENTATION;
@@ -360,6 +381,10 @@
&& navigation != delta.navigation) {
changed |= ActivityInfo.CONFIG_NAVIGATION;
}
+ if (delta.navigationHidden != NAVIGATIONHIDDEN_UNDEFINED
+ && navigationHidden != delta.navigationHidden) {
+ changed |= ActivityInfo.CONFIG_KEYBOARD_HIDDEN;
+ }
if (delta.orientation != ORIENTATION_UNDEFINED
&& orientation != delta.orientation) {
changed |= ActivityInfo.CONFIG_ORIENTATION;
@@ -416,6 +441,7 @@
dest.writeInt(keyboardHidden);
dest.writeInt(hardKeyboardHidden);
dest.writeInt(navigation);
+ dest.writeInt(navigationHidden);
dest.writeInt(orientation);
dest.writeInt(screenLayout);
}
@@ -448,6 +474,7 @@
keyboardHidden = source.readInt();
hardKeyboardHidden = source.readInt();
navigation = source.readInt();
+ navigationHidden = source.readInt();
orientation = source.readInt();
screenLayout = source.readInt();
}
@@ -478,6 +505,8 @@
if (n != 0) return n;
n = this.navigation - that.navigation;
if (n != 0) return n;
+ n = this.navigationHidden - that.navigationHidden;
+ if (n != 0) return n;
n = this.orientation - that.orientation;
if (n != 0) return n;
n = this.screenLayout - that.screenLayout;
@@ -503,6 +532,7 @@
return ((int)this.fontScale) + this.mcc + this.mnc
+ this.locale.hashCode() + this.touchscreen
+ this.keyboard + this.keyboardHidden + this.hardKeyboardHidden
- + this.navigation + this.orientation + this.screenLayout;
+ + this.navigation + this.navigationHidden
+ + this.orientation + this.screenLayout;
}
}
diff --git a/core/java/android/database/sqlite/SQLiteDatabase.java b/core/java/android/database/sqlite/SQLiteDatabase.java
index 0cd4036..e425f3a 100644
--- a/core/java/android/database/sqlite/SQLiteDatabase.java
+++ b/core/java/android/database/sqlite/SQLiteDatabase.java
@@ -22,10 +22,11 @@
import android.database.SQLException;
import android.os.Debug;
import android.os.SystemClock;
+import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Config;
-import android.util.Log;
import android.util.EventLog;
+import android.util.Log;
import java.io.File;
import java.util.HashMap;
@@ -221,6 +222,10 @@
// that logging is not enabled.
/* package */ final boolean mLogStats;
+ // System property that enables logging of slow queries. Specify the threshold in ms.
+ private static final String LOG_SLOW_QUERIES_PROPERTY = "db.log.slow_query_threshold";
+ private final int mSlowQueryThreshold;
+
/**
* @param closable
*/
@@ -1202,27 +1207,38 @@
String editTable) {
long timeStart = 0;
- if (Config.LOGV) {
+ if (Config.LOGV || mSlowQueryThreshold != -1) {
timeStart = System.currentTimeMillis();
}
SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(this, sql, editTable);
+ Cursor cursor = null;
try {
- return driver.query(
+ cursor = driver.query(
cursorFactory != null ? cursorFactory : mFactory,
selectionArgs);
} finally {
- if (Config.LOGV) {
+ if (Config.LOGV || mSlowQueryThreshold != -1) {
+
+ // Force query execution
+ if (cursor != null) {
+ cursor.moveToFirst();
+ cursor.moveToPosition(-1);
+ }
+
long duration = System.currentTimeMillis() - timeStart;
- Log.v(SQLiteCursor.TAG,
- "query (" + duration + " ms): " + driver.toString() + ", args are "
- + (selectionArgs != null
- ? TextUtils.join(",", selectionArgs)
- : "<null>"));
+ if (Config.LOGV || duration >= mSlowQueryThreshold) {
+ Log.v(SQLiteCursor.TAG,
+ "query (" + duration + " ms): " + driver.toString() + ", args are "
+ + (selectionArgs != null
+ ? TextUtils.join(",", selectionArgs)
+ : "<null>"));
+ }
}
}
+ return cursor;
}
/**
@@ -1671,6 +1687,7 @@
mFlags = flags;
mPath = path;
mLogStats = "1".equals(android.os.SystemProperties.get("db.logstats"));
+ mSlowQueryThreshold = SystemProperties.getInt(LOG_SLOW_QUERIES_PROPERTY, -1);
mLeakedException = new IllegalStateException(path +
" SQLiteDatabase created and never closed");
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 9991600..13effe0 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -38,12 +38,12 @@
* <p>There is no default constructor for this class. Use {@link #open()} to
* get a Camera object.</p>
*
- * <p>In order to use the device camera, you must declare the
- * {@link android.Manifest.permission#CAMERA} permission in your Android
+ * <p>In order to use the device camera, you must declare the
+ * {@link android.Manifest.permission#CAMERA} permission in your Android
* Manifest. Also be sure to include the
* <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><uses-feature></a>
- * manifest element in order to declare camera features used by your application.
- * For example, if you use the camera and auto-focus feature, your Manifest
+ * manifest element in order to declare camera features used by your application.
+ * For example, if you use the camera and auto-focus feature, your Manifest
* should include the following:</p>
* <pre> <uses-permission android:name="android.permission.CAMERA" />
* <uses-feature android:name="android.hardware.camera" />
@@ -52,7 +52,7 @@
* <p class="caution"><strong>Caution:</strong> Different Android-powered devices
* may have different hardware specifications, such as megapixel ratings and
* auto-focus capabilities. In order for your application to be compatible with
- * more devices, you should not make assumptions about the device camera
+ * more devices, you should not make assumptions about the device camera
* specifications.</p>
*/
public class Camera {
@@ -197,7 +197,7 @@
* The callback that delivers the preview frames.
*
* @param data The contents of the preview frame in the format defined
- * by {@link android.graphics.PixelFormat}, which can be queried
+ * by {@link android.graphics.PixelFormat}, which can be queried
* with {@link android.hardware.Camera.Parameters#getPreviewFormat()}.
* If {@link android.hardware.Camera.Parameters#setPreviewFormat(int)}
* is never called, the default will be the YCbCr_420_SP
@@ -340,11 +340,11 @@
/**
* Handles the callback for the camera auto focus.
- * <p>Devices that do not support auto-focus will receive a "fake"
- * callback to this interface. If your application needs auto-focus and
+ * <p>Devices that do not support auto-focus will receive a "fake"
+ * callback to this interface. If your application needs auto-focus and
* should not be installed on devices <em>without</em> auto-focus, you must
* declare that your app uses the
- * {@code android.hardware.camera.autofocus} feature, in the
+ * {@code android.hardware.camera.autofocus} feature, in the
* <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><uses-feature></a>
* manifest element.</p>
*/
@@ -368,11 +368,11 @@
* AutoFocusCallback#onAutoFocus(boolean, Camera)} callback will be called
* immediately.
* <p>If your application should not be installed
- * on devices without auto-focus, you must declare that your application
- * uses auto-focus with the
+ * on devices without auto-focus, you must declare that your application
+ * uses auto-focus with the
* <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><uses-feature></a>
* manifest element.</p>
- *
+ *
* @param cb the callback to run
*/
public final void autoFocus(AutoFocusCallback cb)
@@ -387,7 +387,6 @@
* this function will cancel it. Whether the auto-focus is in progress
* or not, this function will return the focus position to the default.
* If the camera does not support auto-focus, this is a no-op.
- * @hide
*/
public final void cancelAutoFocus()
{
@@ -917,11 +916,11 @@
}
/**
- * Sets the image format for preview pictures.
+ * Sets the image format for preview pictures.
* <p>If this is never called, the default format will be
* {@link android.graphics.PixelFormat#YCbCr_420_SP}, which
* uses the NV21 encoding format.</p>
- *
+ *
* @param pixel_format the desired preview picture format, defined
* by one of the {@link android.graphics.PixelFormat} constants.
* (E.g., <var>PixelFormat.YCbCr_420_SP</var> (default),
@@ -942,8 +941,8 @@
/**
* Returns the image format for preview pictures got from
* {@link PreviewCallback}.
- *
- * @return the {@link android.graphics.PixelFormat} int representing
+ *
+ * @return the {@link android.graphics.PixelFormat} int representing
* the preview picture format.
*/
public int getPreviewFormat() {
diff --git a/core/java/android/pim/vcard/ContactStruct.java b/core/java/android/pim/vcard/ContactStruct.java
index 0064bf2..06b0636 100644
--- a/core/java/android/pim/vcard/ContactStruct.java
+++ b/core/java/android/pim/vcard/ContactStruct.java
@@ -15,6 +15,7 @@
*/
package android.pim.vcard;
+import android.accounts.Account;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -416,7 +417,8 @@
private List<String> mWebsiteList;
private final int mVCardType;
-
+ private final Account mAccount;
+
// Each Column of four properties has ISPRIMARY field
// (See android.provider.Contacts)
// If false even after the parsing loop, we choose the first entry as a "primary"
@@ -429,9 +431,14 @@
public ContactStruct() {
this(VCardConfig.VCARD_TYPE_V21_GENERIC);
}
-
+
public ContactStruct(int vcardType) {
+ this(vcardType, null);
+ }
+
+ public ContactStruct(int vcardType, Account account) {
mVCardType = vcardType;
+ mAccount = account;
}
/**
@@ -1021,7 +1028,12 @@
new ArrayList<ContentProviderOperation>();
ContentProviderOperation.Builder builder =
ContentProviderOperation.newInsert(RawContacts.CONTENT_URI);
- builder.withValues(new ContentValues());
+ if (mAccount != null) {
+ builder.withValue(RawContacts.ACCOUNT_NAME, mAccount.name);
+ builder.withValue(RawContacts.ACCOUNT_TYPE, mAccount.type);
+ } else {
+ builder.withValues(new ContentValues());
+ }
operationList.add(builder.build());
{
@@ -1183,7 +1195,7 @@
builder.withValue(Miscellaneous.BIRTHDAY, mBirthday);
operationList.add(builder.build());
}
-
+
try {
resolver.applyBatch(ContactsContract.AUTHORITY, operationList);
} catch (RemoteException e) {
diff --git a/core/java/android/pim/vcard/VCardDataBuilder.java b/core/java/android/pim/vcard/VCardDataBuilder.java
index fd165e9..d2026d0 100644
--- a/core/java/android/pim/vcard/VCardDataBuilder.java
+++ b/core/java/android/pim/vcard/VCardDataBuilder.java
@@ -15,6 +15,7 @@
*/
package android.pim.vcard;
+import android.accounts.Account;
import android.util.CharsetUtils;
import android.util.Log;
@@ -59,7 +60,8 @@
private String mTargetCharset;
private boolean mStrictLineBreakParsing;
- private int mVCardType;
+ final private int mVCardType;
+ final private Account mAccount;
// Just for testing.
private long mTimePushIntoContentResolver;
@@ -67,21 +69,22 @@
private List<EntryHandler> mEntryHandlers = new ArrayList<EntryHandler>();
public VCardDataBuilder() {
- this(null, null, false, VCardConfig.VCARD_TYPE_V21_GENERIC);
+ this(null, null, false, VCardConfig.VCARD_TYPE_V21_GENERIC, null);
}
/**
* @hide
*/
public VCardDataBuilder(int vcardType) {
- this(null, null, false, vcardType);
+ this(null, null, false, vcardType, null);
}
/**
* @hide
*/
- public VCardDataBuilder(String charset, boolean strictLineBreakParsing, int vcardType) {
- this(null, charset, strictLineBreakParsing, vcardType);
+ public VCardDataBuilder(String charset,
+ boolean strictLineBreakParsing, int vcardType, Account account) {
+ this(null, charset, strictLineBreakParsing, vcardType, account);
}
/**
@@ -90,7 +93,8 @@
public VCardDataBuilder(String sourceCharset,
String targetCharset,
boolean strictLineBreakParsing,
- int vcardType) {
+ int vcardType,
+ Account account) {
if (sourceCharset != null) {
mSourceCharset = sourceCharset;
} else {
@@ -103,6 +107,7 @@
}
mStrictLineBreakParsing = strictLineBreakParsing;
mVCardType = vcardType;
+ mAccount = account;
}
public void addEntryHandler(EntryHandler entryHandler) {
@@ -136,7 +141,7 @@
Log.e(LOG_TAG, "This is not VCARD!");
}
- mCurrentContactStruct = new ContactStruct(mVCardType);
+ mCurrentContactStruct = new ContactStruct(mVCardType, mAccount);
}
public void endRecord() {
diff --git a/core/java/android/provider/Contacts.java b/core/java/android/provider/Contacts.java
index 181a529..667ec5a 100644
--- a/core/java/android/provider/Contacts.java
+++ b/core/java/android/provider/Contacts.java
@@ -542,7 +542,7 @@
}
return new ByteArrayInputStream(data);
} finally {
- cursor.close();
+ if (cursor != null) cursor.close();
}
}
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index b0ac7f4..afa0a7c 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -1529,7 +1529,7 @@
* called on a raw contact, it is marked for deletion and removed from its
* aggregate contact. The sync adaptor deletes the raw contact on the server and
* then calls ContactResolver.delete once more, this time setting the the
- * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize
+ * {@link ContactsContract#CALLER_IS_SYNCADAPTER} query parameter to finalize
* the data removal.
* <P>Type: INTEGER</P>
*/
@@ -1686,6 +1686,13 @@
public static final String UNGROUPED_VISIBLE = "ungrouped_visible";
/**
+ * Read-only flag indicating if this {@link #SHOULD_SYNC} or any
+ * {@link Groups#SHOULD_SYNC} under this account have been marked as
+ * unsynced.
+ */
+ public static final String ANY_UNSYNCED = "any_unsynced";
+
+ /**
* Read-only count of {@link Contacts} from a specific source that have
* no {@link CommonDataKinds.GroupMembership} entries.
* <p>
diff --git a/core/java/android/service/wallpaper/WallpaperSettingsActivity.java b/core/java/android/service/wallpaper/WallpaperSettingsActivity.java
new file mode 100644
index 0000000..501947d
--- /dev/null
+++ b/core/java/android/service/wallpaper/WallpaperSettingsActivity.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 Google Inc.
+ *
+ * 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.service.wallpaper;
+
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.preference.PreferenceActivity;
+
+/**
+ * Base class for activities that will be used to configure the settings of
+ * a wallpaper. You should derive from this class to allow it to select the
+ * proper theme of the activity depending on how it is being used.
+ */
+public class WallpaperSettingsActivity extends PreferenceActivity {
+ /**
+ * This boolean extra in the launch intent indicates that the settings
+ * are being used while the wallpaper is in preview mode.
+ */
+ final public static String EXTRA_PREVIEW_MODE
+ = "android.service.wallpaper.PREVIEW_MODE";
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ if (false) {
+ Resources.Theme theme = getTheme();
+ if (getIntent().getBooleanExtra(EXTRA_PREVIEW_MODE, false)) {
+ theme.applyStyle(com.android.internal.R.style.PreviewWallpaperSettings, true);
+ } else {
+ theme.applyStyle(com.android.internal.R.style.ActiveWallpaperSettings, true);
+ }
+ }
+ super.onCreate(icicle);
+ }
+}
diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java
index 172e9ac..38881d3 100644
--- a/core/java/android/text/method/QwertyKeyListener.java
+++ b/core/java/android/text/method/QwertyKeyListener.java
@@ -401,16 +401,12 @@
private static SparseArray<String> PICKER_SETS =
new SparseArray<String>();
static {
- PICKER_SETS.put('!', "\u00A1");
- PICKER_SETS.put('<', "\u00AB");
- PICKER_SETS.put('>', "\u00BB");
- PICKER_SETS.put('?', "\u00BF");
PICKER_SETS.put('A', "\u00C0\u00C1\u00C2\u00C4\u00C6\u00C3\u00C5\u0104\u0100");
PICKER_SETS.put('C', "\u00C7\u0106\u010C");
PICKER_SETS.put('D', "\u010E");
PICKER_SETS.put('E', "\u00C8\u00C9\u00CA\u00CB\u0118\u011A\u0112");
PICKER_SETS.put('L', "\u0141");
- PICKER_SETS.put('I', "\u00CC\u00CD\u00CE\u00CF\u012A");
+ PICKER_SETS.put('I', "\u00CC\u00CD\u00CE\u00CF\u012A\u0130");
PICKER_SETS.put('N', "\u00D1\u0143\u0147");
PICKER_SETS.put('O', "\u00D8\u0152\u00D5\u00D2\u00D3\u00D4\u00D6\u014C");
PICKER_SETS.put('R', "\u0158");
@@ -423,7 +419,7 @@
PICKER_SETS.put('c', "\u00E7\u0107\u010D");
PICKER_SETS.put('d', "\u010F");
PICKER_SETS.put('e', "\u00E8\u00E9\u00EA\u00EB\u0119\u011B\u0113");
- PICKER_SETS.put('i', "\u00EC\u00ED\u00EE\u00EF\u012B");
+ PICKER_SETS.put('i', "\u00EC\u00ED\u00EE\u00EF\u012B\u0131");
PICKER_SETS.put('l', "\u0142");
PICKER_SETS.put('n', "\u00F1\u0144\u0148");
PICKER_SETS.put('o', "\u00F8\u0153\u00F5\u00F2\u00F3\u00F4\u00F6\u014D");
@@ -435,6 +431,33 @@
PICKER_SETS.put('z', "\u017A\u017C\u017E");
PICKER_SETS.put(KeyCharacterMap.PICKER_DIALOG_INPUT,
"\u2026\u00A5\u2022\u00AE\u00A9\u00B1[]{}\\");
+
+ // From packages/inputmethods/LatinIME/res/xml/kbd_symbols.xml
+
+ PICKER_SETS.put('1', "\u00b9\u00bd\u2153\u00bc\u215b");
+ PICKER_SETS.put('2', "\u00b2\u2154");
+ PICKER_SETS.put('3', "\u00b3\u00be\u215c");
+ PICKER_SETS.put('4', "\u2074");
+ PICKER_SETS.put('5', "\u215d");
+ PICKER_SETS.put('7', "\u215e");
+ PICKER_SETS.put('0', "\u207f\u2205");
+ PICKER_SETS.put('$', "\u00a2\u00a3\u20ac\u00a5\u20a3\u20a4\u20b1");
+ PICKER_SETS.put('%', "\u2030");
+ PICKER_SETS.put('*', "\u2020\u2021");
+ PICKER_SETS.put('-', "\u2013\u2014");
+ PICKER_SETS.put('+', "\u00b1");
+ PICKER_SETS.put('(', "[{<");
+ PICKER_SETS.put(')', "]}>");
+ PICKER_SETS.put('!', "\u00a1");
+ PICKER_SETS.put('"', "\u201c\u201d\u00ab\u00bb\u02dd");
+ PICKER_SETS.put('?', "\u00bf");
+ PICKER_SETS.put(',', "\u201a\u201e");
+
+ // From packages/inputmethods/LatinIME/res/xml/kbd_symbols_shift.xml
+
+ PICKER_SETS.put('=', "\u2260\u2248\u221e");
+ PICKER_SETS.put('<', "\u2264\u00ab\u2039");
+ PICKER_SETS.put('>', "\u2265\u00bb\u203a");
};
private boolean showCharacterPicker(View view, Editable content, char c,
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 8c12656..f67c4aa 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -500,6 +500,12 @@
*/
public static final int FLAG_SHOW_WALLPAPER = 0x00100000;
+ /** Window flag: when set as a window is being added or made
+ * visible, once the window has been shown then the system will
+ * poke the power manager's user activity (as if the user had woken
+ * up the device) to turn the screen on. */
+ public static final int FLAG_TURN_SCREEN_ON = 0x00200000;
+
/** Window flag: special flag to limit the size of the window to be
* original size ([320x480] x density). Used to create window for applications
* running under compatibility mode.
diff --git a/core/java/android/webkit/PluginActivity.java b/core/java/android/webkit/PluginActivity.java
index f9e3080..cda7b59 100644
--- a/core/java/android/webkit/PluginActivity.java
+++ b/core/java/android/webkit/PluginActivity.java
@@ -49,10 +49,10 @@
final int npp = intent.getIntExtra(INTENT_EXTRA_NPP_INSTANCE, -1);
// Retrieve the PluginStub implemented in packageName.className
PluginStub stub =
- PluginUtil.getPluginStub(this, packageName, className, npp);
+ PluginUtil.getPluginStub(this, packageName, className);
if (stub != null) {
- View pluginView = stub.getFullScreenView(this);
+ View pluginView = stub.getFullScreenView(npp, this);
if (pluginView != null) {
setContentView(pluginView);
} else {
diff --git a/core/java/android/webkit/PluginStub.java b/core/java/android/webkit/PluginStub.java
index c24da8d..3887d44 100644
--- a/core/java/android/webkit/PluginStub.java
+++ b/core/java/android/webkit/PluginStub.java
@@ -19,32 +19,29 @@
import android.view.View;
/**
- * This abstract class is used to implement plugins in a WebView. A plugin
+ * This interface is used to implement plugins in a WebView. A plugin
* package may extend this class and implement the abstract functions to create
* embedded or fullscreeen views displayed in a WebView. The PluginStub
* implementation will be provided the same NPP instance that is created
* through the native interface.
*/
-public abstract class PluginStub {
- /**
- * Construct a new PluginStub implementation for the given NPP instance.
- * @param npp The native NPP instance.
- */
- public PluginStub(int npp) { }
+public interface PluginStub {
/**
* Return a custom embedded view to draw the plugin.
+ * @param NPP The native NPP instance.
* @param context The current application's Context.
* @return A custom View that will be managed by WebView.
*/
- public abstract View getEmbeddedView(Context context);
+ public abstract View getEmbeddedView(int NPP, Context context);
/**
* Return a custom full-screen view to be displayed when the user requests
* a plugin display as full-screen. Note that the application may choose not
* to display this View as completely full-screen.
+ * @param NPP The native NPP instance.
* @param context The current application's Context.
* @return A custom View that will be managed by the application.
*/
- public abstract View getFullScreenView(Context context);
+ public abstract View getFullScreenView(int NPP, Context context);
}
diff --git a/core/java/android/webkit/PluginUtil.java b/core/java/android/webkit/PluginUtil.java
index c0a7375..8fdbd67 100644
--- a/core/java/android/webkit/PluginUtil.java
+++ b/core/java/android/webkit/PluginUtil.java
@@ -32,19 +32,16 @@
* @param className the fully qualified name of a subclass of PluginStub
*/
/* package */
- static PluginStub getPluginStub(Context context, String packageName,
- String className, int NPP) {
+ static PluginStub getPluginStub(Context context, String packageName,
+ String className) {
try {
Context pluginContext = context.createPackageContext(packageName,
Context.CONTEXT_INCLUDE_CODE |
Context.CONTEXT_IGNORE_SECURITY);
ClassLoader pluginCL = pluginContext.getClassLoader();
- Class<?> stubClass =
- pluginCL.loadClass(className);
- Constructor<?> stubConstructor =
- stubClass.getConstructor(int.class);
- Object stubObject = stubConstructor.newInstance(NPP);
+ Class<?> stubClass = pluginCL.loadClass(className);
+ Object stubObject = stubClass.newInstance();
if (stubObject instanceof PluginStub) {
return (PluginStub) stubObject;
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 5f2d65e..ac3334c 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -34,6 +34,7 @@
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
+import android.view.View;
import java.util.ArrayList;
import java.util.Map;
@@ -2060,84 +2061,32 @@
}
}
- // This class looks like a SurfaceView to native code. In java, we can
- // assume the passed in SurfaceView is this class so we can talk to the
- // ViewManager through the ChildView.
- private class SurfaceViewProxy extends SurfaceView
- implements SurfaceHolder.Callback {
- private final ViewManager.ChildView mChildView;
- private int mPointer;
- private final boolean mIsFixedSize;
- SurfaceViewProxy(Context context, ViewManager.ChildView childView,
- int pointer, int pixelFormat, boolean isFixedSize) {
- super(context);
- setWillNotDraw(false); // this prevents the black box artifact
- getHolder().addCallback(this);
- getHolder().setFormat(pixelFormat);
- mChildView = childView;
- mChildView.mView = this;
- mPointer = pointer;
- mIsFixedSize = isFixedSize;
- }
- void destroy() {
- mPointer = 0;
- mChildView.removeView();
- }
- void attach(int x, int y, int width, int height) {
- mChildView.attachView(x, y, width, height);
-
- if (mIsFixedSize) {
- getHolder().setFixedSize(width, height);
- }
- }
-
- // SurfaceHolder.Callback methods
- public void surfaceCreated(SurfaceHolder holder) {
- if (mPointer != 0) {
- nativeSurfaceChanged(mPointer, 0, 0, 0, 0);
- }
- }
- public void surfaceChanged(SurfaceHolder holder, int format, int width,
- int height) {
- if (mPointer != 0) {
- nativeSurfaceChanged(mPointer, 1, format, width, height);
- }
- }
- public void surfaceDestroyed(SurfaceHolder holder) {
- if (mPointer != 0) {
- nativeSurfaceChanged(mPointer, 2, 0, 0, 0);
- }
- }
- }
-
- // PluginWidget functions for mainting SurfaceViews for the Surface drawing
+ // PluginWidget functions for creating SurfaceViews for the Surface drawing
// model.
- private SurfaceView createSurface(int nativePointer, int pixelFormat,
- boolean isFixedSize) {
+ private ViewManager.ChildView createSurface(String packageName, String className,
+ int npp, int x, int y, int width, int height) {
if (mWebView == null) {
return null;
}
- return new SurfaceViewProxy(mContext, mWebView.mViewManager.createView(),
- nativePointer, pixelFormat, isFixedSize);
+ PluginStub stub = PluginUtil.getPluginStub(mWebView.getContext(), packageName, className);
+ if (stub == null) {
+ Log.e(LOGTAG, "Unable to find plugin class (" + className +
+ ") in the apk (" + packageName + ")");
+ return null;
+ }
+
+ View pluginView = stub.getEmbeddedView(npp, mWebView.getContext());
+
+ ViewManager.ChildView view = mWebView.mViewManager.createView();
+ view.mView = pluginView;
+ view.attachView(x, y, width, height);
+ return view;
}
-
- private void destroySurface(SurfaceView surface) {
- SurfaceViewProxy proxy = (SurfaceViewProxy) surface;
- proxy.destroy();
+
+ private void destroySurface(ViewManager.ChildView childView) {
+ childView.removeView();
}
- private void attachSurface(SurfaceView surface, int x, int y,
- int width, int height) {
- SurfaceViewProxy proxy = (SurfaceViewProxy) surface;
- proxy.attach(x, y, width, height);
- }
-
- // Callback for the SurfaceHolder.Callback. Called for all the surface
- // callbacks. The state parameter is one of Created(0), Changed(1),
- // Destroyed(2).
- private native void nativeSurfaceChanged(int pointer, int state, int format,
- int width, int height);
-
private native void nativePause();
private native void nativeResume();
private native void nativeFreeMemory();
diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java
index 760b8ff..e55fbb8 100644
--- a/core/java/android/widget/ZoomButtonsController.java
+++ b/core/java/android/widget/ZoomButtonsController.java
@@ -249,7 +249,7 @@
lp.height = LayoutParams.WRAP_CONTENT;
lp.width = LayoutParams.FILL_PARENT;
lp.type = LayoutParams.TYPE_APPLICATION_PANEL;
- lp.format = PixelFormat.TRANSPARENT;
+ lp.format = PixelFormat.TRANSLUCENT;
lp.windowAnimations = com.android.internal.R.style.Animation_ZoomButtons;
mContainerLayoutParams = lp;
diff --git a/core/java/com/android/internal/widget/RotarySelector.java b/core/java/com/android/internal/widget/RotarySelector.java
new file mode 100644
index 0000000..7b940c9
--- /dev/null
+++ b/core/java/com/android/internal/widget/RotarySelector.java
@@ -0,0 +1,542 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.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;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.animation.AccelerateInterpolator;
+
+import com.android.internal.R;
+
+
+/**
+ * Custom view that presents up to two items that are selectable by rotating a semi-circle from
+ * left to right, or right to left. Used by incoming call screen, and the lock screen when no
+ * security pattern is set.
+ */
+public class RotarySelector extends View {
+ private static final String LOG_TAG = "RotarySelector";
+ private static final boolean DBG = false;
+
+ // Listener for onDialTrigger() callbacks.
+ private OnDialTriggerListener mOnDialTriggerListener;
+
+ private float mDensity;
+
+ // UI elements
+ private Drawable mBackground;
+ private Drawable mDimple;
+
+ private Drawable mLeftHandleIcon;
+ private Drawable mRightHandleIcon;
+
+ private Drawable mArrowShortLeftAndRight;
+ private Drawable mArrowLongLeft; // Long arrow starting on the left, pointing clockwise
+ private Drawable mArrowLongRight; // Long arrow starting on the right, pointing CCW
+
+ // positions of the left and right handle
+ private int mLeftHandleX;
+ private int mRightHandleX;
+
+ // current offset of user's dragging
+ private int mTouchDragOffset = 0;
+
+ // state of the animation used to bring the handle back to its start position when
+ // the user lets go before triggering an action
+ private boolean mAnimating = false;
+ private long mAnimationEndTime;
+ private int mAnimatingDelta;
+ AccelerateInterpolator mInterpolator;
+
+ /**
+ * True after triggering an action if the user of {@link OnDialTriggerListener} wants to
+ * freeze the UI (until they transition to another screen).
+ */
+ private boolean mFrozen = false;
+
+ /**
+ * If the user is currently dragging something.
+ */
+ private int mGrabbedState = NOTHING_GRABBED;
+ private static final int NOTHING_GRABBED = 0;
+ private static final int LEFT_HANDLE_GRABBED = 1;
+ private static final int RIGHT_HANDLE_GRABBED = 2;
+
+ /**
+ * Whether the user has triggered something (e.g dragging the left handle all the way over to
+ * the right).
+ */
+ private boolean mTriggered = false;
+
+ // Vibration (haptic feedback)
+ private Vibrator mVibrator;
+ 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.
+ */
+ private static final int ARROW_SCRUNCH_DIP = 6;
+
+ /**
+ * How far inset the left and right circles should be
+ */
+ private static final int EDGE_PADDING_DIP = 9;
+
+ /**
+ * Dimensions of arc in background drawable.
+ */
+ static final int OUTER_ROTARY_RADIUS_DIP = 390;
+ static final int ROTARY_STROKE_WIDTH_DIP = 83;
+ private static final int ANIMATION_DURATION_MILLIS = 300;
+
+ private static final boolean DRAW_CENTER_DIMPLE = false;
+
+ /**
+ * Constructor used when this widget is created from a layout file.
+ */
+ public RotarySelector(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ if (DBG) log("IncomingCallDialWidget constructor...");
+
+ 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);
+ mDimple = r.getDrawable(R.drawable.jog_dial_dimple);
+
+ mArrowLongLeft = r.getDrawable(R.drawable.jog_dial_arrow_long_left_green);
+ mArrowLongRight = r.getDrawable(R.drawable.jog_dial_arrow_long_right_red);
+ mArrowShortLeftAndRight = r.getDrawable(R.drawable.jog_dial_arrow_short_left_and_right);
+
+ mInterpolator = new AccelerateInterpolator();
+ }
+
+ /**
+ * Sets the left handle icon to a given resource.
+ *
+ * The resource should refer to a Drawable object, or use 0 to remove
+ * the icon.
+ *
+ * @param resId the resource ID.
+ */
+ public void setLeftHandleResource(int resId) {
+ Drawable d = null;
+ if (resId != 0) {
+ d = getResources().getDrawable(resId);
+ }
+ setLeftHandleDrawable(d);
+ }
+
+ /**
+ * Sets the left handle icon to a given Drawable.
+ *
+ * @param d the Drawable to use as the icon, or null to remove the icon.
+ */
+ public void setLeftHandleDrawable(Drawable d) {
+ mLeftHandleIcon = d;
+ invalidate();
+ }
+
+ /**
+ * Sets the right handle icon to a given resource.
+ *
+ * The resource should refer to a Drawable object, or use 0 to remove
+ * the icon.
+ *
+ * @param resId the resource ID.
+ */
+ public void setRightHandleResource(int resId) {
+ Drawable d = null;
+ if (resId != 0) {
+ d = getResources().getDrawable(resId);
+ }
+ setRightHandleDrawable(d);
+ }
+
+ /**
+ * Sets the right handle icon to a given Drawable.
+ *
+ * @param d the Drawable to use as the icon, or null to remove the icon.
+ */
+ public void setRightHandleDrawable(Drawable d) {
+ mRightHandleIcon = d;
+ invalidate();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ final int width = MeasureSpec.getSize(widthMeasureSpec); // screen width
+
+ final int arrowH = mArrowShortLeftAndRight.getIntrinsicHeight();
+ final int backgroundH = mBackground.getIntrinsicHeight();
+
+ // by making the height less than arrow + bg, arrow and bg will be scrunched together,
+ // overlaying somewhat (though on transparent portions of the drawable).
+ // this works because the arrows are drawn from the top, and the rotary bg is drawn
+ // from the bottom.
+ final int arrowScrunch = (int) (ARROW_SCRUNCH_DIP * mDensity);
+ setMeasuredDimension(width, backgroundH + arrowH - arrowScrunch);
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+
+ mLeftHandleX = (int) (EDGE_PADDING_DIP * mDensity) + mDimple.getIntrinsicWidth() / 2;
+ mRightHandleX =
+ getWidth() - (int) (EDGE_PADDING_DIP * mDensity) - mDimple.getIntrinsicWidth() / 2;
+ }
+
+// private Paint mPaint = new Paint();
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ if (DBG) {
+ log(String.format("onDraw: mAnimating=%s, mTouchDragOffset=%d, mGrabbedState=%d," +
+ "mFrozen=%s",
+ mAnimating, mTouchDragOffset, mGrabbedState, mFrozen));
+ }
+
+ final int height = getHeight();
+
+ // update animating state before we draw anything
+ if (mAnimating && !mFrozen) {
+ long millisLeft = mAnimationEndTime - System.currentTimeMillis();
+ if (DBG) log("millisleft for animating: " + millisLeft);
+ if (millisLeft <= 0) {
+ reset();
+ } else {
+ float interpolation = mInterpolator.getInterpolation(
+ (float) millisLeft / ANIMATION_DURATION_MILLIS);
+ mTouchDragOffset = (int) (mAnimatingDelta * interpolation);
+ }
+ }
+
+
+ // Background:
+ final int backgroundW = mBackground.getIntrinsicWidth();
+ final int backgroundH = mBackground.getIntrinsicHeight();
+ final int backgroundY = height - backgroundH;
+ if (DBG) log("- Background INTRINSIC: " + backgroundW + " x " + backgroundH);
+ mBackground.setBounds(0, backgroundY,
+ backgroundW, backgroundY + backgroundH);
+ 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;
+ switch (mGrabbedState) {
+ case NOTHING_GRABBED:
+ currentArrow = mArrowShortLeftAndRight;
+ break;
+ case LEFT_HANDLE_GRABBED:
+ currentArrow = mArrowLongLeft;
+ break;
+ case RIGHT_HANDLE_GRABBED:
+ currentArrow = mArrowLongRight;
+ break;
+ 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)
+// mPaint.setColor(Color.RED);
+// mPaint.setStyle(Paint.Style.STROKE);
+// float or = OUTER_ROTARY_RADIUS_DIP * mDensity;
+// canvas.drawCircle(getWidth() / 2, or + mBackground.getBounds().top, or, mPaint);
+
+ final int outerRadius = (int) (mDensity * OUTER_ROTARY_RADIUS_DIP);
+ final int innerRadius =
+ (int) ((OUTER_ROTARY_RADIUS_DIP - ROTARY_STROKE_WIDTH_DIP) * mDensity);
+ final int bgTop = mBackground.getBounds().top;
+ {
+ final int xOffset = mLeftHandleX + mTouchDragOffset;
+ final int drawableY = getYOnArc(
+ mBackground,
+ innerRadius,
+ outerRadius,
+ xOffset);
+
+ drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
+ drawCentered(mLeftHandleIcon, canvas, xOffset, drawableY + bgTop);
+ }
+
+ if (DRAW_CENTER_DIMPLE) {
+ final int xOffset = getWidth() / 2 + mTouchDragOffset;
+ final int drawableY = getYOnArc(
+ mBackground,
+ innerRadius,
+ outerRadius,
+ xOffset);
+
+ drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
+ }
+
+ {
+ final int xOffset = mRightHandleX + mTouchDragOffset;
+ final int drawableY = getYOnArc(
+ mBackground,
+ innerRadius,
+ outerRadius,
+ xOffset);
+
+ drawCentered(mDimple, canvas, xOffset, drawableY + bgTop);
+ drawCentered(mRightHandleIcon, canvas, xOffset, drawableY + bgTop);
+ }
+
+ if (mAnimating) invalidate();
+ }
+
+ /**
+ * Assuming drawable is a bounding box around a piece of an arc drawn by two concentric circles
+ * (as the background drawable for the rotary widget is), and given an x coordinate along the
+ * drawable, return the y coordinate of a point on the arc that is between the two concentric
+ * circles. The resulting y combined with the incoming x is a point along the circle in
+ * between the two concentric circles.
+ *
+ * @param drawable The drawable.
+ * @param innerRadius The radius of the circle that intersects the drawable at the bottom two
+ * corders of the drawable (top two corners in terms of drawing coordinates).
+ * @param outerRadius The radius of the circle who's top most point is the top center of the
+ * drawable (bottom center in terms of drawing coordinates).
+ * @param x The distance along the x axis of the desired point.
+ * @return The y coordinate, in drawing coordinates, that will place (x, y) along the circle
+ * in between the two concentric circles.
+ */
+ private int getYOnArc(Drawable drawable, int innerRadius, int outerRadius, int x) {
+
+ // the hypotenuse
+ final int halfWidth = (outerRadius - innerRadius) / 2;
+ final int middleRadius = innerRadius + halfWidth;
+
+ // the bottom leg of the triangle
+ final int triangleBottom = (drawable.getIntrinsicWidth() / 2) - x;
+
+ // "Our offense is like the pythagorean theorem: There is no answer!" - Shaquille O'Neal
+ final int triangleY =
+ (int) Math.sqrt(middleRadius * middleRadius - triangleBottom * triangleBottom);
+
+ // convert to drawing coordinates:
+ // middleRadius - triangleY =
+ // the vertical distance from the outer edge of the circle to the desired point
+ // from there we add the distance from the top of the drawable to the middle circle
+ return middleRadius - triangleY + halfWidth;
+ }
+
+ /**
+ * Handle touch screen events.
+ *
+ * @param event The motion event.
+ * @return True if the event was handled, false otherwise.
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (mAnimating || mFrozen) {
+ return true;
+ }
+
+ 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);
+ }
+ } else if (mGrabbedState == RotarySelector.RIGHT_HANDLE_GRABBED) {
+ mTouchDragOffset = eventX - mRightHandleX;
+ invalidate();
+ if (eventX <= mLeftHandleX + EDGE_PADDING_DIP && !mTriggered) {
+ mTriggered = true;
+ mFrozen = dispatchTriggerEvent(OnDialTriggerListener.RIGHT_HANDLE);
+ }
+ }
+ } else if ((event.getAction() == MotionEvent.ACTION_UP)) {
+ if (DBG) log("touch-up");
+ // handle animating back to start if they didn't trigger
+ if (mGrabbedState == RotarySelector.LEFT_HANDLE_GRABBED
+ && Math.abs(eventX - mLeftHandleX) > 5) {
+ mAnimating = true;
+ mAnimationEndTime = System.currentTimeMillis() + ANIMATION_DURATION_MILLIS;
+ mAnimatingDelta = eventX - mLeftHandleX;
+ } else if (mGrabbedState == RotarySelector.RIGHT_HANDLE_GRABBED
+ && Math.abs(eventX - mRightHandleX) > 5) {
+ mAnimating = true;
+ mAnimationEndTime = System.currentTimeMillis() + ANIMATION_DURATION_MILLIS;
+ mAnimatingDelta = eventX - mRightHandleX;
+ }
+
+ mTouchDragOffset = 0;
+ mGrabbedState = RotarySelector.NOTHING_GRABBED;
+ invalidate();
+ } else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
+ if (DBG) log("touch-cancel");
+ reset();
+ invalidate();
+ }
+ return true;
+ }
+
+ private void reset() {
+ mAnimating = false;
+ mTouchDragOffset = 0;
+ mGrabbedState = RotarySelector.NOTHING_GRABBED;
+ mTriggered = false;
+ }
+
+ /**
+ * Triggers haptic feedback.
+ */
+ private synchronized void vibrate(long duration) {
+ if (mVibrator == null) {
+ mVibrator = (android.os.Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
+ }
+ mVibrator.vibrate(duration);
+ }
+
+ /**
+ * Sets the bounds of the specified Drawable so that it's centered
+ * on the point (x,y), then draws it onto the specified canvas.
+ * TODO: is there already a utility method somewhere for this?
+ */
+ private static void drawCentered(Drawable d, Canvas c, int x, int y) {
+ int w = d.getIntrinsicWidth();
+ int h = d.getIntrinsicHeight();
+
+ // if (DBG) log("--> drawCentered: " + x + " , " + y + "; intrinsic " + w + " x " + h);
+ d.setBounds(x - (w / 2), y - (h / 2),
+ x + (w / 2), y + (h / 2));
+ d.draw(c);
+ }
+
+
+ /**
+ * Registers a callback to be invoked when the dial
+ * is "triggered" by rotating it one way or the other.
+ *
+ * @param l the OnDialTriggerListener to attach to this view
+ */
+ public void setOnDialTriggerListener(OnDialTriggerListener l) {
+ mOnDialTriggerListener = l;
+ }
+
+ /**
+ * Dispatches a trigger event to our listener.
+ */
+ private boolean dispatchTriggerEvent(int whichHandle) {
+ vibrate(VIBRATE_LONG);
+ if (mOnDialTriggerListener != null) {
+ return mOnDialTriggerListener.onDialTrigger(this, whichHandle);
+ }
+ return false;
+ }
+
+ /**
+ * Interface definition for a callback to be invoked when the dial
+ * is "triggered" by rotating it one way or the other.
+ */
+ public interface OnDialTriggerListener {
+ /**
+ * The dial was triggered because the user grabbed the left handle,
+ * and rotated the dial clockwise.
+ */
+ public static final int LEFT_HANDLE = 1;
+
+ /**
+ * The dial was triggered because the user grabbed the right handle,
+ * and rotated the dial counterclockwise.
+ */
+ public static final int RIGHT_HANDLE = 2;
+
+ /**
+ * @hide
+ * The center handle is currently unused.
+ */
+ public static final int CENTER_HANDLE = 3;
+
+ /**
+ * Called when the dial is triggered.
+ *
+ * @param v The view that was triggered
+ * @param whichHandle Which "dial handle" the user grabbed,
+ * either {@link #LEFT_HANDLE}, {@link #RIGHT_HANDLE}, or
+ * {@link #CENTER_HANDLE}.
+ * @return Whether the widget should freeze (e.g when the action goes to another screen,
+ * you want the UI to stay put until the transition occurs).
+ */
+ boolean onDialTrigger(View v, int whichHandle);
+ }
+
+
+ // Debugging / testing code
+
+ private void log(String msg) {
+ Log.d(LOG_TAG, msg);
+ }
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 53e0125..c4536be 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -52,6 +52,23 @@
<protected-broadcast android:name="android.intent.action.NEW_OUTGOING_CALL" />
<protected-broadcast android:name="android.intent.action.REBOOT" />
+ <protected-broadcast android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.adapter.action.SCAN_MODE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.adapter.action.DISCOVERY_STARTED" />
+ <protected-broadcast android:name="android.bluetooth.adapter.action.DISCOVERY_FINISHED" />
+ <protected-broadcast android:name="android.bluetooth.adapter.action.LOCAL_NAME_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.FOUND" />
+ <protected-broadcast android:name="android.bluetooth.device.action.DISAPPEARED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.CLASS_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.ACL_CONNECTED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.NAME_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.BOND_STATE_CHANGED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.NAME_FAILED" />
+ <protected-broadcast android:name="android.bluetooth.device.action.PAIRING_REQUEST" />
+ <protected-broadcast android:name="android.bluetooth.device.action.PAIRING_CANCEL" />
+
<!-- ====================================== -->
<!-- Permissions for things that cost money -->
<!-- ====================================== -->
diff --git a/core/res/res/drawable/ic_jog_dial_answer.png b/core/res/res/drawable/ic_jog_dial_answer.png
new file mode 100644
index 0000000..e2bc483
--- /dev/null
+++ b/core/res/res/drawable/ic_jog_dial_answer.png
Binary files differ
diff --git a/core/res/res/drawable/ic_jog_dial_decline.png b/core/res/res/drawable/ic_jog_dial_decline.png
new file mode 100644
index 0000000..81c76b5
--- /dev/null
+++ b/core/res/res/drawable/ic_jog_dial_decline.png
Binary files differ
diff --git a/core/res/res/drawable/ic_jog_dial_silence_ringer.png b/core/res/res/drawable/ic_jog_dial_silence_ringer.png
new file mode 100644
index 0000000..6d573e6
--- /dev/null
+++ b/core/res/res/drawable/ic_jog_dial_silence_ringer.png
Binary files differ
diff --git a/core/res/res/drawable/ic_jog_dial_turn_ring_vol_off.png b/core/res/res/drawable/ic_jog_dial_turn_ring_vol_off.png
new file mode 100644
index 0000000..3804c25
--- /dev/null
+++ b/core/res/res/drawable/ic_jog_dial_turn_ring_vol_off.png
Binary files differ
diff --git a/core/res/res/drawable/ic_jog_dial_turn_ring_vol_on.png b/core/res/res/drawable/ic_jog_dial_turn_ring_vol_on.png
new file mode 100644
index 0000000..62f8e15
--- /dev/null
+++ b/core/res/res/drawable/ic_jog_dial_turn_ring_vol_on.png
Binary files differ
diff --git a/core/res/res/drawable/ic_jog_dial_unlock.png b/core/res/res/drawable/ic_jog_dial_unlock.png
new file mode 100644
index 0000000..e697d91
--- /dev/null
+++ b/core/res/res/drawable/ic_jog_dial_unlock.png
Binary files differ
diff --git a/core/res/res/drawable/jog_dial_arrow_long_left_green.png b/core/res/res/drawable/jog_dial_arrow_long_left_green.png
new file mode 100644
index 0000000..334a8e0
--- /dev/null
+++ b/core/res/res/drawable/jog_dial_arrow_long_left_green.png
Binary files differ
diff --git a/core/res/res/drawable/jog_dial_arrow_long_left_yellow.png b/core/res/res/drawable/jog_dial_arrow_long_left_yellow.png
new file mode 100644
index 0000000..2e011ca3
--- /dev/null
+++ b/core/res/res/drawable/jog_dial_arrow_long_left_yellow.png
Binary files differ
diff --git a/core/res/res/drawable/jog_dial_arrow_long_middle_yellow.png b/core/res/res/drawable/jog_dial_arrow_long_middle_yellow.png
new file mode 100644
index 0000000..323745e
--- /dev/null
+++ b/core/res/res/drawable/jog_dial_arrow_long_middle_yellow.png
Binary files differ
diff --git a/core/res/res/drawable/jog_dial_arrow_long_right_red.png b/core/res/res/drawable/jog_dial_arrow_long_right_red.png
new file mode 100644
index 0000000..1e97c9a
--- /dev/null
+++ b/core/res/res/drawable/jog_dial_arrow_long_right_red.png
Binary files differ
diff --git a/core/res/res/drawable/jog_dial_arrow_long_right_yellow.png b/core/res/res/drawable/jog_dial_arrow_long_right_yellow.png
new file mode 100644
index 0000000..3536e58
--- /dev/null
+++ b/core/res/res/drawable/jog_dial_arrow_long_right_yellow.png
Binary files differ
diff --git a/core/res/res/drawable/jog_dial_arrow_short_left.png b/core/res/res/drawable/jog_dial_arrow_short_left.png
new file mode 100644
index 0000000..4a4ab3ae
--- /dev/null
+++ b/core/res/res/drawable/jog_dial_arrow_short_left.png
Binary files differ
diff --git a/core/res/res/drawable/jog_dial_arrow_short_left_and_right.png b/core/res/res/drawable/jog_dial_arrow_short_left_and_right.png
new file mode 100644
index 0000000..987cfa7
--- /dev/null
+++ b/core/res/res/drawable/jog_dial_arrow_short_left_and_right.png
Binary files differ
diff --git a/core/res/res/drawable/jog_dial_arrow_short_right.png b/core/res/res/drawable/jog_dial_arrow_short_right.png
new file mode 100644
index 0000000..ee79875
--- /dev/null
+++ b/core/res/res/drawable/jog_dial_arrow_short_right.png
Binary files differ
diff --git a/core/res/res/drawable/jog_dial_bg_cropped.png b/core/res/res/drawable/jog_dial_bg_cropped.png
new file mode 100644
index 0000000..60d93d2
--- /dev/null
+++ b/core/res/res/drawable/jog_dial_bg_cropped.png
Binary files differ
diff --git a/core/res/res/drawable/jog_dial_dimple.png b/core/res/res/drawable/jog_dial_dimple.png
new file mode 100644
index 0000000..85d3a43
--- /dev/null
+++ b/core/res/res/drawable/jog_dial_dimple.png
Binary files differ
diff --git a/core/res/res/layout/keyguard_screen_rotary_unlock.xml b/core/res/res/layout/keyguard_screen_rotary_unlock.xml
new file mode 100644
index 0000000..cf97d04
--- /dev/null
+++ b/core/res/res/layout/keyguard_screen_rotary_unlock.xml
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** 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.
+*/
+-->
+
+<!-- This is the general lock screen which shows information about the
+ state of the device, as well as instructions on how to get past it
+ depending on the state of the device. It is the same for landscape
+ and portrait.-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:id="@+id/root"
+ >
+
+<RelativeLayout
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="#A0000000"
+ >
+
+ <TextView
+ android:id="@+id/carrier"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="20dip"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorSecondary"
+ />
+
+ <TextView
+ android:id="@+id/time"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/carrier"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="25dip"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:textSize="55sp"
+ />
+
+ <TextView
+ android:id="@+id/date"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/time"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="-12dip"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ />
+
+ <View
+ android:id="@+id/divider"
+ android:layout_width="fill_parent"
+ android:layout_height="1dip"
+ android:layout_marginTop="10dip"
+ android:layout_below="@id/date"
+ android:background="@android:drawable/divider_horizontal_dark"
+ />
+
+ <TextView
+ android:id="@+id/status1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/divider"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="6dip"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorSecondary"
+ />
+
+ <TextView
+ android:id="@+id/status2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/status1"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="6dip"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorSecondary"
+ />
+
+ <TextView
+ android:id="@+id/screenLocked"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/status2"
+ android:layout_centerHorizontal="true"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorSecondary"
+ android:gravity="center"
+ android:layout_marginTop="12dip"
+ />
+
+ <!-- By having the rotary selector hang below "screen locked" text, we get a layout more
+ robust for different screen sizes. On wvga, the widget should be flush with the bottom.-->
+ <com.android.internal.widget.RotarySelector
+ android:id="@+id/rotary"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/screenLocked"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="24dip"
+ />
+
+ <!-- emergency call button shown when sim is missing or PUKd -->
+ <Button
+ android:id="@+id/emergencyCallButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/screenLocked"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="24dip"
+ android:drawableLeft="@drawable/ic_emergency"
+ android:drawablePadding="8dip"
+ />
+
+</RelativeLayout>
+
+</FrameLayout>
\ No newline at end of file
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 560796a..62a230c 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -24,7 +24,14 @@
<drawable name="status_bar_opened_default_background">#ff000000</drawable>
<drawable name="search_bar_default_color">#ff000000</drawable>
<drawable name="safe_mode_background">#60000000</drawable>
+ <!-- Background drawable that can be used for a transparent activity to
+ be able to display a dark UI: this darkens its background to make
+ a dark (default theme) UI more visible. -->
<drawable name="screen_background_dark_transparent">#80000000</drawable>
+ <!-- Background drawable that can be used for a transparent activity to
+ be able to display a light UI: this lightens its background to make
+ a light UI more visible. -->
+ <drawable name="screen_background_light_transparent">#80ffffff</drawable>
<color name="safe_mode_text">#80ffffff</color>
<color name="white">#ffffffff</color>
<color name="black">#ff000000</color>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 117e139..b84a0d9 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,6 +56,16 @@
<item>"wifi,1,1"</item>
<item>"mobile,0,1"</item>
</string-array>
+
+ <!-- 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>
@@ -60,11 +73,18 @@
<!-- 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>
-
+ <!-- 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 +101,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/public.xml b/core/res/res/values/public.xml
index c4636f3..2bc2a0f 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1168,10 +1168,13 @@
<public type="style" name="Theme.Wallpaper" />
<public type="style" name="Theme.Wallpaper.NoTitleBar" />
<public type="style" name="Theme.Wallpaper.NoTitleBar.Fullscreen" />
+ <public type="style" name="Theme.WallpaperSettings" />
+ <public type="style" name="Theme.Light.WallpaperSettings" />
<!-- Semi-transparent background that can be used when placing a dark
themed UI on top of some arbitrary background (such as the
wallpaper). This darkens the background sufficiently that the UI
can be seen. -->
<public type="drawable" name="screen_background_dark_transparent" />
+ <public type="drawable" name="screen_background_light_transparent" />
</resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index fae612c..69612e9 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -458,7 +458,6 @@
<style name="Widget.ListView.White" parent="Widget.AbsListView">
<item name="android:listSelector">@android:drawable/list_selector_background</item>
- <item name="android:background">@android:color/white</item>
<item name="android:divider">@android:drawable/divider_horizontal_bright_opaque</item>
</style>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 4f76c56..1aa48ee 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -303,6 +303,32 @@
<item name="android:windowContentOverlay">@null</item>
</style>
+ <!-- Theme for a wallpaper's setting activity that is designed to be on
+ top of a dark background. -->
+ <style name="Theme.WallpaperSettings">
+ <item name="android:windowBackground">@android:drawable/screen_background_dark_transparent</item>
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item>
+ </style>
+
+ <!-- Theme for a wallpaper's setting activity that is designed to be on
+ top of a light background. -->
+ <style name="Theme.Light.WallpaperSettings">
+ <item name="android:windowBackground">@android:drawable/screen_background_light_transparent</item>
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item>
+ </style>
+
+ <!-- Style to apply on top of a wallpaper settings theme when it is being
+ shown on top of the real wallpaper -->
+ <style name="ActiveWallpaperSettings">
+ </style>
+
+ <!-- Style to apply on top of a wallpaper settings theme when it is being
+ shown on top of the real wallpaper -->
+ <style name="PreviewWallpaperSettings">
+ </style>
+
<!-- Default theme for translucent activities, that is windows that allow you
to see through them to the windows behind. This sets up the translucent
flag and appropriate animations for your windows. -->
diff --git a/docs/html/guide/topics/resources/resources-i18n.jd b/docs/html/guide/topics/resources/resources-i18n.jd
index 85b89d1..ff9579f 100755
--- a/docs/html/guide/topics/resources/resources-i18n.jd
+++ b/docs/html/guide/topics/resources/resources-i18n.jd
@@ -441,7 +441,7 @@
<pre>
MyApp/
res/
- drawable-en-rUS-large-long-port-mdpi-finger-keysexposed-qwerty-dpad-480x320/
+ drawable-en-rUS-large-long-port-mdpi-finger-keysexposed-qwerty-navexposed-dpad-480x320/
</pre>
<p>More typically, you will only specify a few specific configuration options. You may drop any of the values from the
@@ -575,6 +575,14 @@
<td><code>nokeys</code>, <code>qwerty</code>, <code>12key</code> </td>
</tr>
<tr>
+ <td>Whether the navigation keys are available to the user</td>
+ <td><p><code>navexposed</code>, <code>navhidden</code>
+ </p><p>
+ If the hardware's navigation keys are currently available to
+ the user, the navexposed resources will be used; if they are not
+ available (such as behind a closed lid), navhidden will be used.</p></td>
+ </tr>
+ <tr>
<td>Primary non-touchscreen<br />
navigation method</td>
<td><code>nonav</code>, <code>dpad</code>, <code>trackball</code>, <code>wheel</code> </td>
diff --git a/docs/html/sdk/1.0_r1/requirements.jd b/docs/html/sdk/1.0_r1/requirements.jd
index af06675..4163513 100644
--- a/docs/html/sdk/1.0_r1/requirements.jd
+++ b/docs/html/sdk/1.0_r1/requirements.jd
@@ -14,7 +14,13 @@
<ul>
<li>Windows XP or Vista</li>
<li>Mac OS X 10.4.8 or later (x86 only)</li>
- <li>Linux (tested on Linux Ubuntu Dapper Drake)</li>
+ <li>Linux (tested on Linux Ubuntu Dapper Drake)
+ <ul>
+ <li>64-bit distributions must be capable of running 32-bit applications.
+ For information about how to add support for 32-bit applications, see
+ the <a href="installing.html#installnotes">Installation Notes</a>.</li>
+ </ul>
+ </li>
</ul>
<h4>Supported Development Environments:</h4>
diff --git a/docs/html/sdk/1.0_r2/requirements.jd b/docs/html/sdk/1.0_r2/requirements.jd
index 74d90ef..4f7c093 100644
--- a/docs/html/sdk/1.0_r2/requirements.jd
+++ b/docs/html/sdk/1.0_r2/requirements.jd
@@ -13,7 +13,13 @@
<ul>
<li>Windows XP or Vista</li>
<li>Mac OS X 10.4.8 or later (x86 only)</li>
- <li>Linux (tested on Linux Ubuntu Dapper Drake)</li>
+ <li>Linux (tested on Linux Ubuntu Dapper Drake)
+ <ul>
+ <li>64-bit distributions must be capable of running 32-bit applications.
+ For information about how to add support for 32-bit applications, see
+ the <a href="installing.html#installnotes">Installation Notes</a>.</li>
+ </ul>
+ </li>
</ul>
<h4>Supported Development Environments:</h4>
diff --git a/docs/html/sdk/1.1_r1/requirements.jd b/docs/html/sdk/1.1_r1/requirements.jd
index 95b658b..9d8f9eb 100644
--- a/docs/html/sdk/1.1_r1/requirements.jd
+++ b/docs/html/sdk/1.1_r1/requirements.jd
@@ -11,7 +11,13 @@
<ul>
<li>Windows XP (32-bit) or Vista (32- or 64-bit)</li>
<li>Mac OS X 10.4.8 or later (x86 only)</li>
- <li>Linux (tested on Linux Ubuntu Dapper Drake)</li>
+ <li>Linux (tested on Linux Ubuntu Dapper Drake)
+ <ul>
+ <li>64-bit distributions must be capable of running 32-bit applications.
+ For information about how to add support for 32-bit applications, see
+ the <a href="installing.html#installnotes">Installation Notes</a>.</li>
+ </ul>
+ </li>
</ul>
<h3>Supported Development Environments</h3>
diff --git a/docs/html/sdk/1.5_r1/requirements.jd b/docs/html/sdk/1.5_r1/requirements.jd
index 4ed38a7..c10ccac 100644
--- a/docs/html/sdk/1.5_r1/requirements.jd
+++ b/docs/html/sdk/1.5_r1/requirements.jd
@@ -7,7 +7,13 @@
<ul>
<li>Windows XP (32-bit) or Vista (32- or 64-bit)</li>
<li>Mac OS X 10.4.8 or later (x86 only)</li>
- <li>Linux (tested on Linux Ubuntu Dapper Drake)</li>
+ <li>Linux (tested on Linux Ubuntu Dapper Drake)
+ <ul>
+ <li>64-bit distributions must be capable of running 32-bit applications.
+ For information about how to add support for 32-bit applications, see
+ the <a href="installing.html#InstallationNotes">Installation Notes</a>.</li>
+ </ul>
+ </li>
</ul>
<h3>Supported Development Environments</h3>
diff --git a/docs/html/sdk/1.5_r2/requirements.jd b/docs/html/sdk/1.5_r2/requirements.jd
index 4ed38a7..c10ccac 100644
--- a/docs/html/sdk/1.5_r2/requirements.jd
+++ b/docs/html/sdk/1.5_r2/requirements.jd
@@ -7,7 +7,13 @@
<ul>
<li>Windows XP (32-bit) or Vista (32- or 64-bit)</li>
<li>Mac OS X 10.4.8 or later (x86 only)</li>
- <li>Linux (tested on Linux Ubuntu Dapper Drake)</li>
+ <li>Linux (tested on Linux Ubuntu Dapper Drake)
+ <ul>
+ <li>64-bit distributions must be capable of running 32-bit applications.
+ For information about how to add support for 32-bit applications, see
+ the <a href="installing.html#InstallationNotes">Installation Notes</a>.</li>
+ </ul>
+ </li>
</ul>
<h3>Supported Development Environments</h3>
diff --git a/docs/html/sdk/1.5_r3/requirements.jd b/docs/html/sdk/1.5_r3/requirements.jd
index 5f20cf1..5bcee27 100644
--- a/docs/html/sdk/1.5_r3/requirements.jd
+++ b/docs/html/sdk/1.5_r3/requirements.jd
@@ -10,7 +10,13 @@
<ul>
<li>Windows XP (32-bit) or Vista (32- or 64-bit)</li>
<li>Mac OS X 10.4.8 or later (x86 only)</li>
- <li>Linux (tested on Linux Ubuntu Dapper Drake)</li>
+ <li>Linux (tested on Linux Ubuntu Dapper Drake)
+ <ul>
+ <li>64-bit distributions must be capable of running 32-bit applications.
+ For information about how to add support for 32-bit applications, see
+ the <a href="installing.html#InstallationNotes">Installation Notes</a>.</li>
+ </ul>
+ </li>
</ul>
<h3>Supported Development Environments</h3>
diff --git a/docs/html/sdk/1.6_r1/requirements.jd b/docs/html/sdk/1.6_r1/requirements.jd
index 8e698fa..8cfc049 100644
--- a/docs/html/sdk/1.6_r1/requirements.jd
+++ b/docs/html/sdk/1.6_r1/requirements.jd
@@ -11,7 +11,13 @@
<ul>
<li>Windows XP (32-bit) or Vista (32- or 64-bit)</li>
<li>Mac OS X 10.4.8 or later (x86 only)</li>
- <li>Linux (tested on Linux Ubuntu Hardy Heron)</li>
+ <li>Linux (tested on Linux Ubuntu Hardy Heron)
+ <ul>
+ <li>64-bit distributions must be capable of running 32-bit applications.
+ For information about how to add support for 32-bit applications, see
+ the <a href="installing.html#InstallationNotes">Installation Notes</a>.</li>
+ </ul>
+ </li>
</ul>
<h3>Supported Development Environments</h3>
diff --git a/docs/html/sdk/RELEASENOTES.jd b/docs/html/sdk/RELEASENOTES.jd
index 130a92c..0dcafd3 100644
--- a/docs/html/sdk/RELEASENOTES.jd
+++ b/docs/html/sdk/RELEASENOTES.jd
@@ -24,6 +24,11 @@
Devices</a> and download new SDK packages (such as platform versions and
add-ons) into your environment.</li>
<li>Improved support for test packages in New Project Wizard</li>
+ <li>The reference documentation now offers a "Filter by API Level"
+capability that lets you display only the parts of the API that are actually
+available to your application, based on the <code>android:minSdkVersion</code>
+value the application declares in its manifest. For more information, see
+<a href="{@docRoot}guide/appendix/api-levels.html">Android API Levels</a></li>
</ul>
<p>For details about the Android platforms included in the SDK — including
@@ -71,8 +76,8 @@
<h3>Android SDK and AVD Manager</h3>
-<p>The SDK offers a new tool called Android AVD Manager that lets you manage
-your SDK and AVD environments more efficiently. </p>
+<p>The SDK offers a new tool called Android SDK and AVD Manager that lets you
+manage your SDK and AVD environments more efficiently. </p>
<p>Using the tool, you can quickly check what Android platforms, add-ons,
extras, and documentation packages are available in your SDK environment, what
@@ -181,7 +186,7 @@
<p>Besides these defaults, You can also create an AVD that overrides the default
density for each skin, to create any combination of resolution/density (WVGA
with medium density, for instance). To do so, use the <code>android</code> tool
-command line to create a new AVD that uses a custom hardare configuration. See
+command line to create a new AVD that uses a custom hardware configuration. See
<a href="{@docRoot}guide/developing/tools/avd.html#createavd">Creating an
AVD</a> for more information.</p>
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index e82f297..f42788e 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -271,7 +271,8 @@
public void setTileModeXY(Shader.TileMode xmode, Shader.TileMode ymode) {
final BitmapState state = mBitmapState;
- if (state.mTileModeX != xmode || state.mTileModeY != ymode) {
+ if (state.mPaint.getShader() == null ||
+ state.mTileModeX != xmode || state.mTileModeY != ymode) {
state.mTileModeX = xmode;
state.mTileModeY = ymode;
mRebuildShader = true;
diff --git a/include/ui/Surface.h b/include/ui/Surface.h
index 118fb83..2cedeb6 100644
--- a/include/ui/Surface.h
+++ b/include/ui/Surface.h
@@ -212,7 +212,7 @@
void setUsage(uint32_t reqUsage);
- bool getUsage(uint32_t* usage);
+ uint32_t getUsage() const;
// constants
sp<SurfaceComposerClient> mClient;
@@ -227,7 +227,6 @@
// protected by mSurfaceLock
Rect mSwapRectangle;
uint32_t mUsage;
- int32_t mUsageChanged;
// protected by mSurfaceLock. These are also used from lock/unlock
// but in that case, they must be called form the same thread.
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index e524e2a..17ccad6 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -864,6 +864,13 @@
KEYSHIDDEN_SOFT = 0x0003,
};
+ enum {
+ MASK_NAVHIDDEN = 0x000c,
+ NAVHIDDEN_ANY = 0x0000,
+ NAVHIDDEN_NO = 0x0004,
+ NAVHIDDEN_YES = 0x0008,
+ };
+
union {
struct {
uint8_t keyboard;
@@ -1011,7 +1018,8 @@
if (orientation != o.orientation) diffs |= CONFIG_ORIENTATION;
if (density != o.density) diffs |= CONFIG_DENSITY;
if (touchscreen != o.touchscreen) diffs |= CONFIG_TOUCHSCREEN;
- if (((inputFlags^o.inputFlags)&MASK_KEYSHIDDEN) != 0) diffs |= CONFIG_KEYBOARD_HIDDEN;
+ if (((inputFlags^o.inputFlags)&(MASK_KEYSHIDDEN|MASK_NAVHIDDEN)) != 0)
+ diffs |= CONFIG_KEYBOARD_HIDDEN;
if (keyboard != o.keyboard) diffs |= CONFIG_KEYBOARD;
if (navigation != o.navigation) diffs |= CONFIG_NAVIGATION;
if (screenSize != o.screenSize) diffs |= CONFIG_SCREEN_SIZE;
@@ -1082,6 +1090,11 @@
if (!(o.inputFlags & MASK_KEYSHIDDEN)) return true;
}
+ if (((inputFlags^o.inputFlags) & MASK_NAVHIDDEN) != 0) {
+ if (!(inputFlags & MASK_NAVHIDDEN)) return false;
+ if (!(o.inputFlags & MASK_NAVHIDDEN)) return true;
+ }
+
if (keyboard != o.keyboard) {
if (!keyboard) return false;
if (!o.keyboard) return true;
@@ -1225,6 +1238,18 @@
}
}
+ const int navHidden = inputFlags & MASK_NAVHIDDEN;
+ const int oNavHidden = o.inputFlags & MASK_NAVHIDDEN;
+ if (navHidden != oNavHidden) {
+ const int reqNavHidden =
+ requested->inputFlags & MASK_NAVHIDDEN;
+ if (reqNavHidden) {
+
+ if (!navHidden) return false;
+ if (!oNavHidden) return true;
+ }
+ }
+
if ((keyboard != o.keyboard) && requested->keyboard) {
return (keyboard);
}
@@ -1332,6 +1357,12 @@
return false;
}
}
+ const int navHidden = inputFlags&MASK_NAVHIDDEN;
+ const int setNavHidden = settings.inputFlags&MASK_NAVHIDDEN;
+ if (setNavHidden != 0 && navHidden != 0
+ && navHidden != setNavHidden) {
+ return false;
+ }
if (settings.keyboard != 0 && keyboard != 0
&& keyboard != settings.keyboard) {
return false;
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index bbfc54b..38a897d 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -607,9 +607,10 @@
void LayerBuffer::OverlaySource::onDraw(const Region& clip) const
{
+ // this would be where the color-key would be set, should we need it.
GLclampx red = 0;
GLclampx green = 0;
- GLclampx blue = 0x1818;
+ GLclampx blue = 0;
mLayer.clearWithOpenGL(clip, red, green, blue, 0);
}
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index c3fbea2..64522fb 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -361,7 +361,6 @@
const_cast<uint32_t&>(android_native_window_t::flags) = 0;
// be default we request a hardware surface
mUsage = GRALLOC_USAGE_HW_RENDER;
- mUsageChanged = true;
mNeedFullUpdate = false;
}
@@ -498,14 +497,14 @@
LOGE("error dequeuing a buffer (%s)", strerror(bufIdx));
return bufIdx;
}
-
- // FIXME: in case of failure below, we need to undo the dequeue
-
- uint32_t usage;
- const bool usageChanged = getUsage(&usage);
+
+ // below we make sure we AT LEAST have the usage flags we want
+ const uint32_t usage(getUsage());
const sp<SurfaceBuffer>& backBuffer(mBuffers[bufIdx]);
- if ((backBuffer == 0) || usageChanged ||
- mSharedBufferClient->needNewBuffer(bufIdx)) {
+ if (backBuffer == 0 ||
+ ((uint32_t(backBuffer->usage) & usage) != usage) ||
+ mSharedBufferClient->needNewBuffer(bufIdx))
+ {
err = getBufferLocked(bufIdx, usage);
LOGE_IF(err, "getBufferLocked(%ld, %08x) failed (%s)",
bufIdx, usage, strerror(-err));
@@ -600,21 +599,13 @@
void Surface::setUsage(uint32_t reqUsage)
{
Mutex::Autolock _l(mSurfaceLock);
- if (mUsage != reqUsage) {
- mUsageChanged = true;
- mUsage = reqUsage;
- }
+ mUsage = reqUsage;
}
-bool Surface::getUsage(uint32_t* usage)
+uint32_t Surface::getUsage() const
{
Mutex::Autolock _l(mSurfaceLock);
- *usage = mUsage;
- if (mUsageChanged) {
- mUsageChanged = false;
- return true;
- }
- return false;
+ return mUsage;
}
// ----------------------------------------------------------------------------
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 1dd644b..d6463a1 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -345,6 +345,9 @@
/**
* Adjusts the volume of a particular stream by one step in a direction.
+ * <p>
+ * This method should only be used by applications that replace the platform-wide
+ * management of audio settings or the main telephony application.
*
* @param streamType The stream type to adjust. One of {@link #STREAM_VOICE_CALL},
* {@link #STREAM_SYSTEM}, {@link #STREAM_RING}, {@link #STREAM_MUSIC} or
@@ -370,6 +373,9 @@
* active, it will have the highest priority regardless of if the in-call
* screen is showing. Another example, if music is playing in the background
* and a call is not active, the music stream will be adjusted.
+ * <p>
+ * This method should only be used by applications that replace the platform-wide
+ * management of audio settings or the main telephony application.
*
* @param direction The direction to adjust the volume. One of
* {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
@@ -391,6 +397,9 @@
/**
* Adjusts the volume of the most relevant stream, or the given fallback
* stream.
+ * <p>
+ * This method should only be used by applications that replace the platform-wide
+ * management of audio settings or the main telephony application.
*
* @param direction The direction to adjust the volume. One of
* {@link #ADJUST_LOWER}, {@link #ADJUST_RAISE}, or
@@ -541,6 +550,9 @@
* <p>
* For a better user experience, applications MUST unmute a muted stream
* in onPause() and mute is again in onResume() if appropriate.
+ * <p>
+ * This method should only be used by applications that replace the platform-wide
+ * management of audio settings or the main telephony application.
*
* @param streamType The stream to be muted/unmuted.
* @param state The required mute state: true for mute ON, false for mute OFF
@@ -608,6 +620,9 @@
/**
* Sets the setting for when the vibrate type should vibrate.
+ * <p>
+ * This method should only be used by applications that replace the platform-wide
+ * management of audio settings or the main telephony application.
*
* @param vibrateType The type of vibrate. One of
* {@link #VIBRATE_TYPE_NOTIFICATION} or
@@ -630,6 +645,9 @@
/**
* Sets the speakerphone on or off.
+ * <p>
+ * This method should only be used by applications that replace the platform-wide
+ * management of audio settings or the main telephony application.
*
* @param on set <var>true</var> to turn on speakerphone;
* <var>false</var> to turn it off
@@ -660,6 +678,9 @@
/**
* Request use of Bluetooth SCO headset for communications.
+ * <p>
+ * This method should only be used by applications that replace the platform-wide
+ * management of audio settings or the main telephony application.
*
* @param on set <var>true</var> to use bluetooth SCO for communications;
* <var>false</var> to not use bluetooth SCO for communications
@@ -739,6 +760,9 @@
/**
* Sets the microphone mute on or off.
+ * <p>
+ * This method should only be used by applications that replace the platform-wide
+ * management of audio settings or the main telephony application.
*
* @param on set <var>true</var> to mute the microphone;
* <var>false</var> to turn mute off
@@ -758,6 +782,13 @@
/**
* Sets the audio mode.
+ * <p>
+ * The audio mode encompasses audio routing AND the behavior of
+ * the telephony layer. Therefore this method should only be used by applications that
+ * replace the platform-wide management of audio settings or the main telephony application.
+ * In particular, the {@link #MODE_IN_CALL} mode should only be used by the telephony
+ * application when it places a phone call, as it will cause signals from the radio layer
+ * to feed the platform mixer.
*
* @param mode the requested audio mode (NORMAL, RINGTONE, or IN_CALL).
* Informs the HAL about the current audio state so that
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index aba40b3..c3a09f6 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -16,8 +16,7 @@
package android.media;
-import android.util.Log;
-
+import java.io.IOException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -25,171 +24,102 @@
import java.util.Map;
/**
- * Wrapper for native Exif library
- * {@hide}
+ * This is a class for reading and writing Exif tags in a JPEG file.
*/
public class ExifInterface {
- private static final String TAG = "ExifInterface";
- private String mFilename;
-
- // Constants used for the Orientation Exif tag.
- public static final int ORIENTATION_UNDEFINED = 0;
- public static final int ORIENTATION_NORMAL = 1;
-
- // Constants used for white balance
- public static final int WHITEBALANCE_AUTO = 0;
- public static final int WHITEBALANCE_MANUAL = 1;
-
- // left right reversed mirror
- public static final int ORIENTATION_FLIP_HORIZONTAL = 2;
- public static final int ORIENTATION_ROTATE_180 = 3;
-
- // upside down mirror
- public static final int ORIENTATION_FLIP_VERTICAL = 4;
-
- // flipped about top-left <--> bottom-right axis
- public static final int ORIENTATION_TRANSPOSE = 5;
-
- // rotate 90 cw to right it
- public static final int ORIENTATION_ROTATE_90 = 6;
-
- // flipped about top-right <--> bottom-left axis
- public static final int ORIENTATION_TRANSVERSE = 7;
-
- // rotate 270 to right it
- public static final int ORIENTATION_ROTATE_270 = 8;
// The Exif tag names
public static final String TAG_ORIENTATION = "Orientation";
-
public static final String TAG_DATETIME = "DateTime";
public static final String TAG_MAKE = "Make";
public static final String TAG_MODEL = "Model";
public static final String TAG_FLASH = "Flash";
public static final String TAG_IMAGE_WIDTH = "ImageWidth";
public static final String TAG_IMAGE_LENGTH = "ImageLength";
-
public static final String TAG_GPS_LATITUDE = "GPSLatitude";
public static final String TAG_GPS_LONGITUDE = "GPSLongitude";
-
public static final String TAG_GPS_LATITUDE_REF = "GPSLatitudeRef";
public static final String TAG_GPS_LONGITUDE_REF = "GPSLongitudeRef";
public static final String TAG_WHITE_BALANCE = "WhiteBalance";
- private boolean mSavedAttributes = false;
- private boolean mHasThumbnail = false;
- private HashMap<String, String> mCachedAttributes = null;
+ // Constants used for the Orientation Exif tag.
+ public static final int ORIENTATION_UNDEFINED = 0;
+ public static final int ORIENTATION_NORMAL = 1;
+ public static final int ORIENTATION_FLIP_HORIZONTAL = 2; // left right reversed mirror
+ public static final int ORIENTATION_ROTATE_180 = 3;
+ public static final int ORIENTATION_FLIP_VERTICAL = 4; // upside down mirror
+ public static final int ORIENTATION_TRANSPOSE = 5; // flipped about top-left <--> bottom-right axis
+ public static final int ORIENTATION_ROTATE_90 = 6; // rotate 90 cw to right it
+ public static final int ORIENTATION_TRANSVERSE = 7; // flipped about top-right <--> bottom-left axis
+ public static final int ORIENTATION_ROTATE_270 = 8; // rotate 270 to right it
+
+ // Constants used for white balance
+ public static final int WHITEBALANCE_AUTO = 0;
+ public static final int WHITEBALANCE_MANUAL = 1;
static {
System.loadLibrary("exif");
}
- private static ExifInterface sExifObj = null;
- /**
- * Since the underlying jhead native code is not thread-safe,
- * ExifInterface should use singleton interface instead of public
- * constructor.
- */
- private static synchronized ExifInterface instance() {
- if (sExifObj == null) {
- sExifObj = new ExifInterface();
- }
+ private String mFilename;
+ private HashMap<String, String> mAttributes;
+ private boolean mHasThumbnail = false;
- return sExifObj;
+ // Because the underlying implementation (jhead) uses static variables,
+ // there can only be one user at a time for the native functions (and
+ // they cannot keep state in the native code across function calls). We
+ // use sLock the serialize the accesses.
+ private static Object sLock = new Object();
+
+ /**
+ * Reads Exif tags from the specified JPEG file.
+ */
+ public ExifInterface(String filename) throws IOException {
+ mFilename = filename;
+ loadAttributes();
}
/**
- * The following 3 static methods are handy routines for atomic operation
- * of underlying jhead library. It retrieves EXIF data and then release
- * ExifInterface immediately.
+ * Returns the value of the specified tag or {@code null} if there
+ * is no such tag in the file.
+ *
+ * @param tag the name of the tag.
*/
- public static synchronized HashMap<String, String> loadExifData(String filename) {
- ExifInterface exif = instance();
- HashMap<String, String> exifData = null;
- if (exif != null) {
- exif.setFilename(filename);
- exifData = exif.getAttributes();
- }
- return exifData;
- }
-
- public static synchronized void saveExifData(String filename, HashMap<String, String> exifData) {
- ExifInterface exif = instance();
- if (exif != null) {
- exif.setFilename(filename);
- exif.saveAttributes(exifData);
- }
- }
-
- public static synchronized byte[] getExifThumbnail(String filename) {
- ExifInterface exif = instance();
- if (exif != null) {
- exif.setFilename(filename);
- return exif.getThumbnail();
- }
- return null;
- }
-
- public void setFilename(String filename) {
- if (mFilename == null || !mFilename.equals(filename)) {
- mFilename = filename;
- mCachedAttributes = null;
- }
+ public String getAttribute(String tag) {
+ return mAttributes.get(tag);
}
/**
- * Given a HashMap of Exif tags and associated values, an Exif section in
- * the JPG file is created and loaded with the tag data. saveAttributes()
- * is expensive because it involves copying all the JPG data from one file
- * to another and deleting the old file and renaming the other. It's best
- * to collect all the attributes to write and make a single call rather
- * than multiple calls for each attribute. You must call "commitChanges()"
- * at some point to commit the changes.
+ * Set the value of the specified tag.
+ *
+ * @param tag the name of the tag.
+ * @param value the value of the tag.
*/
- public void saveAttributes(HashMap<String, String> attributes) {
- // format of string passed to native C code:
- // "attrCnt attr1=valueLen value1attr2=value2Len value2..."
- // example:
- // "4 attrPtr ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO"
- StringBuilder sb = new StringBuilder();
- int size = attributes.size();
- if (attributes.containsKey("hasThumbnail")) {
- --size;
- }
- sb.append(size + " ");
- for (Map.Entry<String, String> iter : attributes.entrySet()) {
- String key = iter.getKey();
- if (key.equals("hasThumbnail")) {
- // this is a fake attribute not saved as an exif tag
- continue;
- }
- String val = iter.getValue();
- sb.append(key + "=");
- sb.append(val.length() + " ");
- sb.append(val);
- }
- String s = sb.toString();
- saveAttributesNative(mFilename, s);
- commitChangesNative(mFilename);
- mSavedAttributes = true;
+ public void setAttribute(String tag, String value) {
+ mAttributes.put(tag, value);
}
/**
- * Returns a HashMap loaded with the Exif attributes of the file. The key
- * is the standard tag name and the value is the tag's value: e.g.
- * Model -> Nikon. Numeric values are returned as strings.
+ * Initialize mAttributes with the attributes from the file mFilename.
+ *
+ * mAttributes is a HashMap which stores the Exif attributes of the file.
+ * The key is the standard tag name and the value is the tag's value: e.g.
+ * Model -> Nikon. Numeric values are stored as strings.
+ *
+ * This function also initialize mHasThumbnail to indicate whether the
+ * file has a thumbnail inside.
*/
- public HashMap<String, String> getAttributes() {
- if (mCachedAttributes != null) {
- return mCachedAttributes;
- }
+ private void loadAttributes() {
// format of string passed from native C code:
// "attrCnt attr1=valueLen value1attr2=value2Len value2..."
// example:
// "4 attrPtr ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO"
- mCachedAttributes = new HashMap<String, String>();
+ mAttributes = new HashMap<String, String>();
- String attrStr = getAttributesNative(mFilename);
+ String attrStr;
+ synchronized (sLock) {
+ attrStr = getAttributesNative(mFilename);
+ }
// get count
int ptr = attrStr.indexOf(' ');
@@ -215,17 +145,78 @@
if (attrName.equals("hasThumbnail")) {
mHasThumbnail = attrValue.equalsIgnoreCase("true");
} else {
- mCachedAttributes.put(attrName, attrValue);
+ mAttributes.put(attrName, attrValue);
}
}
- return mCachedAttributes;
}
/**
- * Given a numerical white balance value, return a
- * human-readable string describing it.
+ * Save the tag data into the JPEG file. This is expensive because it involves
+ * copying all the JPG data from one file to another and deleting the old file
+ * and renaming the other. It's best to use {@link setAttribute()} to set all
+ * attributes to write and make a single call rather than multiple calls for
+ * each attribute.
*/
- public static String whiteBalanceToString(int whitebalance) {
+ public void saveAttributes() throws IOException {
+ // format of string passed to native C code:
+ // "attrCnt attr1=valueLen value1attr2=value2Len value2..."
+ // example:
+ // "4 attrPtr ImageLength=4 1024Model=6 FooImageWidth=4 1280Make=3 FOO"
+ StringBuilder sb = new StringBuilder();
+ int size = mAttributes.size();
+ if (mAttributes.containsKey("hasThumbnail")) {
+ --size;
+ }
+ sb.append(size + " ");
+ for (Map.Entry<String, String> iter : mAttributes.entrySet()) {
+ String key = iter.getKey();
+ if (key.equals("hasThumbnail")) {
+ // this is a fake attribute not saved as an exif tag
+ continue;
+ }
+ String val = iter.getValue();
+ sb.append(key + "=");
+ sb.append(val.length() + " ");
+ sb.append(val);
+ }
+ String s = sb.toString();
+ synchronized (sLock) {
+ saveAttributesNative(mFilename, s);
+ commitChangesNative(mFilename);
+ }
+ }
+
+ /**
+ * Returns true if the JPEG file has a thumbnail.
+ */
+ public boolean hasThumbnail() {
+ return mHasThumbnail;
+ }
+
+ /**
+ * Returns the thumbnail inside the JPEG file, or {@code null} if there is no thumbnail.
+ */
+ public byte[] getThumbnail() {
+ synchronized (sLock) {
+ return getThumbnailNative(mFilename);
+ }
+ }
+
+ /**
+ * Returns a human-readable string describing the white balance value. Returns empty
+ * string if there is no white balance value or it is not recognized.
+ */
+ public String getWhiteBalanceString() {
+ String value = getAttribute(TAG_WHITE_BALANCE);
+ if (value == null) return "";
+
+ int whitebalance;
+ try {
+ whitebalance = Integer.parseInt(value);
+ } catch (NumberFormatException ex) {
+ return "";
+ }
+
switch (whitebalance) {
case WHITEBALANCE_AUTO:
return "Auto";
@@ -237,12 +228,21 @@
}
/**
- * Given a numerical orientation, return a human-readable string describing
- * the orientation.
+ * Returns a human-readable string describing the orientation value. Returns empty
+ * string if there is no orientation value or it it not recognized.
*/
- public static String orientationToString(int orientation) {
- // TODO: this function needs to be localized and use string resource ids
- // rather than strings
+ public String getOrientationString() {
+ // TODO: this function needs to be localized.
+ String value = getAttribute(TAG_ORIENTATION);
+ if (value == null) return "";
+
+ int orientation;
+ try {
+ orientation = Integer.parseInt(value);
+ } catch (NumberFormatException ex) {
+ return "";
+ }
+
String orientationString;
switch (orientation) {
case ORIENTATION_NORMAL:
@@ -277,48 +277,21 @@
}
/**
- * Copies the thumbnail data out of the filename and puts it in the Exif
- * data associated with the file used to create this object. You must call
- * "commitChanges()" at some point to commit the changes.
+ * Returns the latitude and longitude value in a float array. The first element is
+ * the latitude, and the second element is the longitude.
*/
- public boolean appendThumbnail(String thumbnailFileName) {
- if (!mSavedAttributes) {
- throw new RuntimeException("Must call saveAttributes "
- + "before calling appendThumbnail");
- }
- mHasThumbnail = appendThumbnailNative(mFilename, thumbnailFileName);
- return mHasThumbnail;
- }
-
- public boolean hasThumbnail() {
- if (!mSavedAttributes) {
- getAttributes();
- }
- return mHasThumbnail;
- }
-
- public byte[] getThumbnail() {
- return getThumbnailNative(mFilename);
- }
-
- public static float[] getLatLng(HashMap<String, String> exifData) {
- if (exifData == null) {
- return null;
- }
-
- String latValue = exifData.get(ExifInterface.TAG_GPS_LATITUDE);
- String latRef = exifData.get(ExifInterface.TAG_GPS_LATITUDE_REF);
- String lngValue = exifData.get(ExifInterface.TAG_GPS_LONGITUDE);
- String lngRef = exifData.get(ExifInterface.TAG_GPS_LONGITUDE_REF);
+ public float[] getLatLong() {
+ String latValue = mAttributes.get(ExifInterface.TAG_GPS_LATITUDE);
+ String latRef = mAttributes.get(ExifInterface.TAG_GPS_LATITUDE_REF);
+ String lngValue = mAttributes.get(ExifInterface.TAG_GPS_LONGITUDE);
+ String lngRef = mAttributes.get(ExifInterface.TAG_GPS_LONGITUDE_REF);
float[] latlng = null;
if (latValue != null && latRef != null
&& lngValue != null && lngRef != null) {
latlng = new float[2];
- latlng[0] = ExifInterface.convertRationalLatLonToFloat(
- latValue, latRef);
- latlng[1] = ExifInterface.convertRationalLatLonToFloat(
- lngValue, lngRef);
+ latlng[0] = convertRationalLatLonToFloat(latValue, latRef);
+ latlng[1] = convertRationalLatLonToFloat(lngValue, lngRef);
}
return latlng;
@@ -327,14 +300,12 @@
private static SimpleDateFormat sFormatter =
new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
- // Returns number of milliseconds since Jan. 1, 1970, midnight GMT.
- // Returns -1 if the date time information if not available.
- public static long getDateTime(HashMap<String, String> exifData) {
- if (exifData == null) {
- return -1;
- }
-
- String dateTimeString = exifData.get(ExifInterface.TAG_DATETIME);
+ /**
+ * Returns number of milliseconds since Jan. 1, 1970, midnight GMT.
+ * Returns -1 if the date time information if not available.
+ */
+ public long getDateTime() {
+ String dateTimeString = mAttributes.get(TAG_DATETIME);
if (dateTimeString == null) return -1;
ParsePosition pos = new ParsePosition(0);
@@ -347,7 +318,7 @@
}
}
- public static float convertRationalLatLonToFloat(
+ private static float convertRationalLatLonToFloat(
String rationalString, String ref) {
try {
String [] parts = rationalString.split(",");
@@ -377,42 +348,6 @@
}
}
- public static String convertRationalLatLonToDecimalString(
- String rationalString, String ref, boolean usePositiveNegative) {
- float result = convertRationalLatLonToFloat(rationalString, ref);
-
- String preliminaryResult = String.valueOf(result);
- if (usePositiveNegative) {
- String neg = (ref.equals("S") || ref.equals("E")) ? "-" : "";
- return neg + preliminaryResult;
- } else {
- return preliminaryResult + String.valueOf((char) 186) + " "
- + ref;
- }
- }
-
- public static String makeLatLongString(double d) {
- d = Math.abs(d);
-
- int degrees = (int) d;
-
- double remainder = d - degrees;
- int minutes = (int) (remainder * 60D);
- // really seconds * 1000
- int seconds = (int) (((remainder * 60D) - minutes) * 60D * 1000D);
-
- String retVal = degrees + "/1," + minutes + "/1," + seconds + "/1000";
- return retVal;
- }
-
- public static String makeLatStringRef(double lat) {
- return lat >= 0D ? "N" : "S";
- }
-
- public static String makeLonStringRef(double lon) {
- return lon >= 0D ? "W" : "E";
- }
-
private native boolean appendThumbnailNative(String fileName,
String thumbnailFileName);
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index f6d30e0..d9127e7 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -719,16 +719,20 @@
values.put(Audio.Media.IS_MUSIC, music);
values.put(Audio.Media.IS_PODCAST, podcasts);
} else if (mFileType == MediaFile.FILE_TYPE_JPEG) {
- HashMap<String, String> exifData =
- ExifInterface.loadExifData(entry.mPath);
- if (exifData != null) {
- float[] latlng = ExifInterface.getLatLng(exifData);
+ ExifInterface exif = null;
+ try {
+ exif = new ExifInterface(entry.mPath);
+ } catch (IOException ex) {
+ // exif is null
+ }
+ if (exif != null) {
+ float[] latlng = exif.getLatLong();
if (latlng != null) {
values.put(Images.Media.LATITUDE, latlng[0]);
values.put(Images.Media.LONGITUDE, latlng[1]);
}
- long time = ExifInterface.getDateTime(exifData);
+ long time = exif.getDateTime();
if (time != -1) {
values.put(Images.Media.DATE_TAKEN, time);
}
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 22c2f39..ba4c4c7 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -229,6 +229,7 @@
}
if (!strncmp(componentName, "OMX.qcom.video.decoder.", 23)) {
// XXX Required on P....on only.
+ quirks |= kRequiresAllocateBufferOnInputPorts;
quirks |= kRequiresAllocateBufferOnOutputPorts;
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
index a86ef8f9..ef211b3 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaNames.java
@@ -406,7 +406,7 @@
public static final String META_DATA_OTHERS [][] = {
{"/sdcard/media_api/metaDataTestMedias/3GP/cat.3gp", null, null, null,
null, null, "20080309T002415.000Z", null,
- null, null, "1404928", "2", null},
+ null, null, "63916", "2", null},
{"/sdcard/media_api/metaDataTestMedias/AMR/AMR_NB.amr", null, null, null,
null, null, null, null,
null, null, "126540", "1", null},
@@ -424,7 +424,7 @@
null, null, "2005", "231180", "1", null},
{"/sdcard/media_api/metaDataTestMedias/MP4/kung_fu_panda_h264.mp4", "2/0", "mp4 album Kung Fu Panda",
"mp4 artist Kung Fu Panda", null, null, "20080517T091451.000Z",
- "41", "Kung Fu Panda", "2008", "77113", "2", "mp4 composer"},
+ "41", "Kung Fu Panda", "2008", "128521", "2", "mp4 composer"},
{"/sdcard/media_api/metaDataTestMedias/OGG/Ring_Classic_02.ogg", null, "Suspended Animation",
"John Petrucci", null, null, "20070510T125223.000Z",
null, null, "2005", "231180", "1", null},
diff --git a/preloaded-classes b/preloaded-classes
index 3da4797..8c5e835 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -724,6 +724,7 @@
com.ibm.icu4jni.text.NativeDecimalFormat$UNumberFormatAttribute
com.ibm.icu4jni.text.NativeDecimalFormat$UNumberFormatSymbol
com.ibm.icu4jni.text.RuleBasedCollator
+com.ibm.icu4jni.util.Resources$DefaultTimeZones
dalvik.system.DexFile
dalvik.system.PathClassLoader
java.beans.PropertyChangeEvent
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 82cf1bc..45e0ceb 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -3611,9 +3611,18 @@
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
- PackageInstalledInfo res;
- synchronized (mInstallLock) {
- res = installPackageLI(packageURI, flags, true, installerPackageName);
+ // Result object to be returned
+ PackageInstalledInfo res = new PackageInstalledInfo();
+ res.returnCode = PackageManager.INSTALL_SUCCEEDED;
+ res.uid = -1;
+ res.pkg = null;
+ res.removedInfo = new PackageRemovedInfo();
+ // Make a temporary copy of file from given packageURI
+ File tmpPackageFile = copyTempInstallFile(packageURI, res);
+ if (tmpPackageFile != null) {
+ synchronized (mInstallLock) {
+ installPackageLI(packageURI, flags, true, installerPackageName, tmpPackageFile, res);
+ }
}
if (observer != null) {
try {
@@ -3828,11 +3837,30 @@
// Since we failed to install the new package we need to restore the old
// package that we deleted.
if(deletedPkg) {
+ File restoreFile = new File(deletedPackage.mPath);
+ if (restoreFile == null) {
+ Log.e(TAG, "Failed allocating storage when restoring pkg : " + pkgName);
+ return;
+ }
+ File restoreTmpFile = createTempPackageFile();
+ if (restoreTmpFile == null) {
+ Log.e(TAG, "Failed creating temp file when restoring pkg : " + pkgName);
+ return;
+ }
+ if (!FileUtils.copyFile(restoreFile, restoreTmpFile)) {
+ Log.e(TAG, "Failed copying temp file when restoring pkg : " + pkgName);
+ return;
+ }
+ PackageInstalledInfo restoreRes = new PackageInstalledInfo();
+ restoreRes.removedInfo = new PackageRemovedInfo();
installPackageLI(
- Uri.fromFile(new File(deletedPackage.mPath)),
+ Uri.fromFile(restoreFile),
isForwardLocked(deletedPackage)
? PackageManager.INSTALL_FORWARD_LOCK
- : 0, false, oldInstallerPackageName);
+ : 0, false, oldInstallerPackageName, restoreTmpFile, restoreRes);
+ if (restoreRes.returnCode != PackageManager.INSTALL_SUCCEEDED) {
+ Log.e(TAG, "Failed restoring pkg : " + pkgName + " after failed upgrade");
+ }
}
}
}
@@ -3995,50 +4023,36 @@
return new File(mAppInstallDir, publicZipFileName);
}
- private PackageInstalledInfo installPackageLI(Uri pPackageURI,
- int pFlags, boolean newInstall, String installerPackageName) {
- File tmpPackageFile = null;
- String pkgName = null;
- boolean forwardLocked = false;
- boolean replacingExistingPackage = false;
- // Result object to be returned
- PackageInstalledInfo res = new PackageInstalledInfo();
- res.returnCode = PackageManager.INSTALL_SUCCEEDED;
- res.uid = -1;
- res.pkg = null;
- res.removedInfo = new PackageRemovedInfo();
+ private File copyTempInstallFile(Uri pPackageURI,
+ PackageInstalledInfo res) {
+ File tmpPackageFile = createTempPackageFile();
+ int retCode = PackageManager.INSTALL_SUCCEEDED;
+ if (tmpPackageFile == null) {
+ res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ return null;
+ }
- main_flow: try {
- tmpPackageFile = createTempPackageFile();
- if (tmpPackageFile == null) {
- res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- break main_flow;
+ if (pPackageURI.getScheme().equals("file")) {
+ final File srcPackageFile = new File(pPackageURI.getPath());
+ // We copy the source package file to a temp file and then rename it to the
+ // destination file in order to eliminate a window where the package directory
+ // scanner notices the new package file but it's not completely copied yet.
+ if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
+ Log.e(TAG, "Couldn't copy package file to temp file.");
+ retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
}
- tmpPackageFile.deleteOnExit(); // paranoia
- if (pPackageURI.getScheme().equals("file")) {
- final File srcPackageFile = new File(pPackageURI.getPath());
- // We copy the source package file to a temp file and then rename it to the
- // destination file in order to eliminate a window where the package directory
- // scanner notices the new package file but it's not completely copied yet.
- if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {
- Log.e(TAG, "Couldn't copy package file to temp file.");
- res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- break main_flow;
- }
- } else if (pPackageURI.getScheme().equals("content")) {
- ParcelFileDescriptor fd;
- try {
- fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
- } catch (FileNotFoundException e) {
- Log.e(TAG, "Couldn't open file descriptor from download service.");
- res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- break main_flow;
- }
- if (fd == null) {
- Log.e(TAG, "Couldn't open file descriptor from download service (null).");
- res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- break main_flow;
- }
+ } else if (pPackageURI.getScheme().equals("content")) {
+ ParcelFileDescriptor fd = null;
+ try {
+ fd = mContext.getContentResolver().openFileDescriptor(pPackageURI, "r");
+ } catch (FileNotFoundException e) {
+ Log.e(TAG, "Couldn't open file descriptor from download service. Failed with exception " + e);
+ retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ }
+ if (fd == null) {
+ Log.e(TAG, "Couldn't open file descriptor from download service (null).");
+ retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ } else {
if (Config.LOGV) {
Log.v(TAG, "Opened file descriptor from download service.");
}
@@ -4049,14 +4063,34 @@
// scanner notices the new package file but it's not completely copied yet.
if (!FileUtils.copyToFile(dlStream, tmpPackageFile)) {
Log.e(TAG, "Couldn't copy package stream to temp file.");
- res.returnCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
- break main_flow;
+ retCode = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
}
- } else {
- Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
- res.returnCode = PackageManager.INSTALL_FAILED_INVALID_URI;
- break main_flow;
}
+ } else {
+ Log.e(TAG, "Package URI is not 'file:' or 'content:' - " + pPackageURI);
+ retCode = PackageManager.INSTALL_FAILED_INVALID_URI;
+ }
+
+ res.returnCode = retCode;
+ if (retCode != PackageManager.INSTALL_SUCCEEDED) {
+ if (tmpPackageFile != null && tmpPackageFile.exists()) {
+ tmpPackageFile.delete();
+ }
+ return null;
+ }
+ return tmpPackageFile;
+ }
+
+ private void installPackageLI(Uri pPackageURI,
+ int pFlags, boolean newInstall, String installerPackageName,
+ File tmpPackageFile, PackageInstalledInfo res) {
+ String pkgName = null;
+ boolean forwardLocked = false;
+ boolean replacingExistingPackage = false;
+ // Result object to be returned
+ res.returnCode = PackageManager.INSTALL_SUCCEEDED;
+
+ main_flow: try {
pkgName = PackageParser.parsePackageName(
tmpPackageFile.getAbsolutePath(), 0);
if (pkgName == null) {
@@ -4128,7 +4162,6 @@
tmpPackageFile.delete();
}
}
- return res;
}
private int setPermissionsLI(String pkgName,
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 53ff78e..63bef54 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -665,6 +665,15 @@
}
}
}
+
+ for (WifiConfiguration.EnterpriseField field :
+ config.enterpriseFields) {
+ value = WifiNative.getNetworkVariableCommand(netId,
+ field.varName());
+ if (!TextUtils.isEmpty(value)) {
+ field.setValue(value);
+ }
+ }
}
/**
@@ -877,103 +886,20 @@
break setVariables;
}
- if ((config.eap != null) && !WifiNative.setNetworkVariableCommand(
+ for (WifiConfiguration.EnterpriseField field
+ : config.enterpriseFields) {
+ String varName = field.varName();
+ String value = field.value();
+ if ((value != null) && !WifiNative.setNetworkVariableCommand(
netId,
- WifiConfiguration.eapVarName,
- config.eap)) {
- if (DBG) {
- Log.d(TAG, config.SSID + ": failed to set eap: "+
- config.eap);
+ varName,
+ value)) {
+ if (DBG) {
+ Log.d(TAG, config.SSID + ": failed to set " + varName +
+ ": " + value);
+ }
+ break setVariables;
}
- break setVariables;
- }
-
- if ((config.phase2 != null) && !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.phase2VarName,
- config.phase2)) {
- if (DBG) {
- Log.d(TAG, config.SSID + ": failed to set phase2: "+
- config.phase2);
- }
- break setVariables;
- }
-
- if ((config.identity != null) && !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.identityVarName,
- config.identity)) {
- if (DBG) {
- Log.d(TAG, config.SSID + ": failed to set identity: "+
- config.identity);
- }
- break setVariables;
- }
-
- if ((config.anonymousIdentity != null) && !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.anonymousIdentityVarName,
- config.anonymousIdentity)) {
- if (DBG) {
- Log.d(TAG, config.SSID + ": failed to set anonymousIdentity: "+
- config.anonymousIdentity);
- }
- break setVariables;
- }
-
- if ((config.password != null) && !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.passwordVarName,
- config.password)) {
- if (DBG) {
- Log.d(TAG, config.SSID + ": failed to set password: "+
- config.password);
- }
- break setVariables;
- }
-
- if ((config.clientCert != null) && !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.clientCertVarName,
- config.clientCert)) {
- if (DBG) {
- Log.d(TAG, config.SSID + ": failed to set clientCert: "+
- config.clientCert);
- }
- break setVariables;
- }
-
- if ((config.caCert != null) && !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.caCertVarName,
- config.caCert)) {
- if (DBG) {
- Log.d(TAG, config.SSID + ": failed to set caCert: "+
- config.caCert);
- }
- break setVariables;
- }
-
- if ((config.privateKey != null) && !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.privateKeyVarName,
- config.privateKey)) {
- if (DBG) {
- Log.d(TAG, config.SSID + ": failed to set privateKey: "+
- config.privateKey);
- }
- break setVariables;
- }
-
- if ((config.privateKeyPasswd != null) && !WifiNative.setNetworkVariableCommand(
- netId,
- WifiConfiguration.privateKeyPasswdVarName,
- config.privateKeyPasswd)) {
- if (DBG) {
- Log.d(TAG, config.SSID + ": failed to set privateKeyPasswd: "+
- config.privateKeyPasswd);
- }
- break setVariables;
}
return netId;
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 8e85a6a..60496d6 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -442,6 +442,8 @@
// Who is holding the screen on.
Session mHoldingScreenOn;
+ boolean mTurnOnScreen;
+
/**
* Whether the UI is currently running in touch mode (not showing
* navigational focus because the user is directly pressing the screen).
@@ -1244,12 +1246,6 @@
"Skipping hidden or animating token: " + w);
continue;
}
- // If this window's app token is ot fullscreen, also irrelevant.
- if (!w.mAppToken.appFullscreen) {
- if (DEBUG_WALLPAPER) Log.v(TAG,
- "Skipping non-fullscreen token: " + w);
- continue;
- }
}
if (DEBUG_WALLPAPER) Log.v(TAG, "Win " + w + ": readyfordisplay="
+ w.isReadyForDisplay() + " drawpending=" + w.mDrawPending
@@ -2214,6 +2210,10 @@
&& !win.mCommitDrawPending && !mDisplayFrozen) {
applyEnterAnimationLocked(win);
}
+ if (displayed && (win.mAttrs.flags
+ & WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
+ win.mTurnOnScreen = true;
+ }
if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
// To change the format, we need to re-build the surface.
win.destroySurfaceLocked();
@@ -6485,6 +6485,7 @@
int mLastLayer;
boolean mHaveFrame;
boolean mObscured;
+ boolean mTurnOnScreen;
WindowState mNextOutsideTouch;
@@ -7716,10 +7717,11 @@
pw.print(" mDestroying="); pw.print(mDestroying);
pw.print(" mRemoved="); pw.println(mRemoved);
}
- if (mOrientationChanging || mAppFreezing) {
+ if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
pw.print(prefix); pw.print("mOrientationChanging=");
pw.print(mOrientationChanging);
- pw.print(" mAppFreezing="); pw.println(mAppFreezing);
+ pw.print(" mAppFreezing="); pw.print(mAppFreezing);
+ pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
}
if (mHScale != 1 || mVScale != 1) {
pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
@@ -9788,6 +9790,12 @@
Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen);
mH.sendMessage(m);
}
+
+ if (mTurnOnScreen) {
+ mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
+ LocalPowerManager.BUTTON_EVENT, true);
+ mTurnOnScreen = false;
+ }
}
void requestAnimationLocked(long delay) {
@@ -9809,6 +9817,10 @@
try {
if (win.mSurface != null) {
win.mSurface.show();
+ if (win.mTurnOnScreen) {
+ win.mTurnOnScreen = false;
+ mTurnOnScreen = true;
+ }
}
return true;
} catch (RuntimeException e) {
diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java
index d680b8a..83552dd 100644
--- a/services/java/com/android/server/status/StatusBarService.java
+++ b/services/java/com/android/server/status/StatusBarService.java
@@ -1490,10 +1490,13 @@
/// ---------- Expanded View --------------
pixelFormat = PixelFormat.TRANSLUCENT;
- if (false) {
- bg = mExpandedView.getBackground();
- if (bg != null) {
- pixelFormat = bg.getOpacity();
+ bg = mExpandedView.getBackground();
+ if (bg != null) {
+ pixelFormat = bg.getOpacity();
+ if (pixelFormat != PixelFormat.TRANSLUCENT) {
+ // we want good-looking gradients, so we force a 8-bits per
+ // pixel format.
+ pixelFormat = PixelFormat.RGBX_8888;
}
}
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index e1bd1db..c8490e9 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -100,10 +100,14 @@
public Drawable cachedPhoto;
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;
public CallerInfo() {
+ // TODO: Move all the basic initialization here?
+ mIsEmergency = false;
}
/**
@@ -221,13 +225,7 @@
// or if it is the voicemail number. If it is either, take a
// shortcut and skip the query.
if (PhoneNumberUtils.isEmergencyNumber(number)) {
- CallerInfo ci = new CallerInfo();
-
- // Note we're setting the phone number here (refer to javadoc
- // comments at the top of CallerInfo class).
- ci.phoneNumber = context.getString(
- com.android.internal.R.string.emergency_call_dialog_number_for_display);
- return ci;
+ return new CallerInfo().markAsEmergency(context);
} else {
try {
if (!sSkipVmCheck && PhoneNumberUtils.compare(number,
@@ -296,6 +294,35 @@
return callerID;
}
+ // Accessors
+
+ /**
+ * @return true if the caller info is an emergency number.
+ */
+ public boolean isEmergencyNumber() {
+ return mIsEmergency;
+ }
+
+ /**
+ * Mark this CallerInfo as an emergency call.
+ * @param context To lookup the localized 'Emergency Number' string.
+ * @return this instance.
+ */
+ // TODO: Note we're setting the phone number here (refer to
+ // javadoc comments at the top of CallerInfo class) to a localized
+ // string 'Emergency Number'. This is pretty bad because we are
+ // making UI work here instead of just packaging the data. We
+ // should set the phone number to the dialed number and name to
+ // 'Emergency Number' and let the UI make the decision about what
+ // should be displayed.
+ /* package */ CallerInfo markAsEmergency(Context context) {
+ phoneNumber = context.getString(
+ com.android.internal.R.string.emergency_call_dialog_number_for_display);
+ photoResource = com.android.internal.R.drawable.picture_emergency;
+ mIsEmergency = true;
+ return this;
+ }
+
private static String normalize(String s) {
if (s == null || s.length() > 0) {
return s;
diff --git a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
index 3d4f78c..4227a84 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfoAsyncQuery.java
@@ -37,7 +37,7 @@
public class CallerInfoAsyncQuery {
private static final boolean DBG = false;
- private static final String LOG_TAG = "PHONE";
+ private static final String LOG_TAG = "CallerInfoAsyncQuery";
private static final int EVENT_NEW_QUERY = 1;
private static final int EVENT_ADD_LISTENER = 2;
@@ -223,13 +223,9 @@
// voicemail number, and adjust other data (including photoResource)
// accordingly.
if (cw.event == EVENT_EMERGENCY_NUMBER) {
- mCallerInfo = new CallerInfo();
// Note we're setting the phone number here (refer to javadoc
// comments at the top of CallerInfo class).
- mCallerInfo.phoneNumber = mQueryContext.getString(com.android.internal
- .R.string.emergency_call_dialog_number_for_display);
- mCallerInfo.photoResource = com.android.internal.R.drawable.picture_emergency;
-
+ mCallerInfo = new CallerInfo().markAsEmergency(mQueryContext);
} else if (cw.event == EVENT_VOICEMAIL_NUMBER) {
mCallerInfo = new CallerInfo();
try {
@@ -390,4 +386,3 @@
Log.d(LOG_TAG, msg);
}
}
-
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
index 806c31d..5bf1a0f 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java
@@ -436,7 +436,9 @@
voiceCallStartedRegistrants.notifyRegistrants (
new AsyncResult(null, null, null));
}
-
+ if (Phone.DEBUG_PHONE) {
+ log("update phone state, old= , new= , " + oldState + state);
+ }
if (state != oldState) {
phone.notifyPhoneStateChanged();
}
@@ -519,27 +521,12 @@
return;
}
} else {
- connections[i] = new CdmaConnection(phone.getContext(), dc, this, i);
-
- // it's a ringing call
- if (connections[i].getCall() == ringingCall) {
- newRinging = connections[i];
- } else {
- // Something strange happened: a call appeared
- // which is neither a ringing call or one we created.
- // Either we've crashed and re-attached to an existing
- // call, or something else (eg, SIM) initiated the call.
-
- Log.i(LOG_TAG,"Phantom call appeared " + dc);
-
- // If it's a connected call, set the connect time so that
- // it's non-zero. It may not be accurate, but at least
- // it won't appear as a Missed Call.
- if (dc.state != DriverCall.State.ALERTING
- && dc.state != DriverCall.State.DIALING) {
- connections[i].connectTime = System.currentTimeMillis();
- }
-
+ if (Phone.DEBUG_PHONE) {
+ log("pending Mo= , dc= " + pendingMO + dc);
+ }
+ // find if the MT call is a new ring or unknown connection
+ newRinging = checkMtFindNewRinging(dc,i);
+ if (newRinging == null) {
unknownConnectionAppeared = true;
}
}
@@ -571,9 +558,28 @@
// list but kept in the Call list
connections[i] = null;
} else if (conn != null && dc != null) { /* implicit conn.compareTo(dc) */
- boolean changed;
- changed = conn.update(dc);
- hasNonHangupStateChanged = hasNonHangupStateChanged || changed;
+ // Call collision case
+ if (conn.isIncoming != dc.isMT) {
+ if (dc.isMT == true){
+ // Mt call takes precedence than Mo,drops Mo
+ droppedDuringPoll.add(conn);
+ // find if the MT call is a new ring or unknown connection
+ newRinging = checkMtFindNewRinging(dc,i);
+ if (newRinging == null) {
+ unknownConnectionAppeared = true;
+ }
+ } else {
+ // Call info stored in conn is not consistent with the call info from dc.
+ // We should follow the rule of MT calls taking precedence over MO calls
+ // when there is conflict, so here we drop the call info from dc and
+ // continue to use the call info from conn, and only take a log.
+ Log.e(LOG_TAG,"Error in RIL, Phantom call appeared " + dc);
+ }
+ } else {
+ boolean changed;
+ changed = conn.update(dc);
+ hasNonHangupStateChanged = hasNonHangupStateChanged || changed;
+ }
}
if (REPEAT_POLLING) {
@@ -1028,6 +1034,34 @@
mIsInEmergencyCall = true;
}
}
+ /**
+ * Check the MT call to see if it's a new ring or
+ * a unknown connection.
+ */
+ private Connection checkMtFindNewRinging(DriverCall dc, int i) {
+
+ Connection newRinging = null;
+
+ connections[i] = new CdmaConnection(phone.getContext(), dc, this, i);
+ // it's a ringing call
+ if (connections[i].getCall() == ringingCall) {
+ newRinging = connections[i];
+ if (Phone.DEBUG_PHONE) log("Notify new ring " + dc);
+ } else {
+ // Something strange happened: a call which is neither
+ // a ringing call nor the one we created. It could be the
+ // call collision result from RIL
+ Log.e(LOG_TAG,"Phantom call appeared " + dc);
+ // If it's a connected call, set the connect time so that
+ // it's non-zero. It may not be accurate, but at least
+ // it won't appear as a Missed Call.
+ if (dc.state != DriverCall.State.ALERTING
+ && dc.state != DriverCall.State.DIALING) {
+ connections[i].connectTime = System.currentTimeMillis();
+ }
+ }
+ return newRinging;
+ }
/**
* Check if current call is in emergency call
diff --git a/telephony/tests/TelephonyTest/Android.mk b/telephony/tests/TelephonyTest/Android.mk
new file mode 100644
index 0000000..1ef8448
--- /dev/null
+++ b/telephony/tests/TelephonyTest/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_PACKAGE_NAME := telephonytest
+
+include $(BUILD_PACKAGE)
diff --git a/telephony/tests/TelephonyTest/AndroidManifest.xml b/telephony/tests/TelephonyTest/AndroidManifest.xml
new file mode 100644
index 0000000..c0cc0d5
--- /dev/null
+++ b/telephony/tests/TelephonyTest/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.telephonytest">
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ <activity android:label="TelephonyTest"
+ android:name="TelephonyTest">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ </application>
+ <instrumentation android:name=".TelephonyUnitTestRunner"
+ android:targetPackage="com.android.telephonytest"
+ android:label="Telephony unit tests InstrumentationRunner">
+ </instrumentation>
+</manifest>
diff --git a/telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java b/telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java
new file mode 100644
index 0000000..5da940d
--- /dev/null
+++ b/telephony/tests/TelephonyTest/src/com/android/telephonytest/TelephonyUnitTestRunner.java
@@ -0,0 +1,47 @@
+/*
+ * 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;
+
+import junit.framework.TestSuite;
+
+import android.test.InstrumentationTestRunner;
+import android.test.InstrumentationTestSuite;
+
+/**
+ * Instrumentation Test Runner for all Telephony unit tests.
+ *
+ * Running all tests:
+ *
+ * runtest telephony-unit
+ * or
+ * adb shell am instrument -w com.android.telephonytest/.TelephonyUnitTestRunner
+ */
+
+public class TelephonyUnitTestRunner extends InstrumentationTestRunner {
+
+ @Override
+ public TestSuite getAllTests() {
+ TestSuite suite = new InstrumentationTestSuite(this);
+ suite.addTestSuite(com.android.telephonytest.unit.CallerInfoUnitTest.class);
+ return suite;
+ }
+
+ @Override
+ public ClassLoader getLoader() {
+ return TelephonyUnitTestRunner.class.getClassLoader();
+ }
+}
diff --git a/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/CallerInfoUnitTest.java b/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/CallerInfoUnitTest.java
new file mode 100644
index 0000000..4cd0266
--- /dev/null
+++ b/telephony/tests/TelephonyTest/src/com/android/telephonytest/unit/CallerInfoUnitTest.java
@@ -0,0 +1,230 @@
+/*
+ * 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.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
+import com.android.internal.telephony.CallerInfo;
+import com.android.internal.telephony.CallerInfoAsyncQuery;
+import android.util.Log;
+import android.os.Looper;
+import android.test.ActivityInstrumentationTestCase;
+import android.util.StringBuilderPrinter;
+
+/*
+ * Check the CallerInfo utility class works as expected.
+ *
+ */
+
+public class CallerInfoUnitTest extends AndroidTestCase {
+ private CallerInfo mInfo;
+ private Context mContext;
+
+ private static final String kEmergencyNumber = "Emergency Number";
+ private static final int kToken = 0xdeadbeef;
+ private static final String TAG = "CallerInfoUnitTest";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mContext = new MockContext();
+ mInfo = new CallerInfo();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Checks the caller info instance is flagged as an emergency if
+ * the number is an emergency one. There is no test for the
+ * contact based constructors because emergency number are not in
+ * the contact DB.
+ */
+ @SmallTest
+ public void testEmergencyIsProperlySet() throws Exception {
+ assertFalse(mInfo.isEmergencyNumber());
+
+ mInfo = CallerInfo.getCallerInfo(mContext, "911");
+ assertIsValidEmergencyCallerInfo();
+
+ mInfo = CallerInfo.getCallerInfo(mContext, "tel:911");
+ assertIsValidEmergencyCallerInfo();
+
+
+ // This one hits the content resolver.
+ mInfo = CallerInfo.getCallerInfo(mContext, "18001234567");
+ assertFalse(mInfo.isEmergencyNumber());
+ }
+
+ /**
+ * Same as testEmergencyIsProperlySet but uses the async query api.
+ */
+ @SmallTest
+ public void testEmergencyIsProperlySetUsingAsyncQuery() throws Exception {
+ QueryRunner query;
+
+ query = new QueryRunner("911");
+ query.runAndCheckCompletion();
+ assertIsValidEmergencyCallerInfo();
+
+ query = new QueryRunner("tel:911");
+ query.runAndCheckCompletion();
+ assertIsValidEmergencyCallerInfo();
+
+ query = new QueryRunner("18001234567");
+ query.runAndCheckCompletion();
+ assertFalse(mInfo.isEmergencyNumber());
+ }
+
+ /**
+ * For emergency caller info, phoneNumber should be set to the
+ * string emergency_call_dialog_number_for_display and the
+ * photoResource should be set to the picture_emergency drawable.
+ */
+ @SmallTest
+ public void testEmergencyNumberAndPhotoAreSet() throws Exception {
+ mInfo = CallerInfo.getCallerInfo(mContext, "911");
+
+ assertIsValidEmergencyCallerInfo();
+ }
+
+ //
+ // Helpers
+ //
+
+ // Partial implementation of MockResources.
+ public class MockResources extends android.test.mock.MockResources
+ {
+ @Override
+ public String getString(int resId) throws Resources.NotFoundException {
+ switch (resId) {
+ case com.android.internal.R.string.emergency_call_dialog_number_for_display:
+ return kEmergencyNumber;
+ default:
+ throw new UnsupportedOperationException("Missing handling for resid " + resId);
+ }
+ }
+ }
+
+ // Partial implementation of MockContext.
+ public class MockContext extends android.test.mock.MockContext {
+ private ContentResolver mResolver;
+ private Resources mResources;
+
+ public MockContext() {
+ mResolver = new android.test.mock.MockContentResolver();
+ mResources = new MockResources();
+ }
+
+ @Override
+ public ContentResolver getContentResolver() {
+ return mResolver;
+ }
+
+ @Override
+ public Resources getResources() {
+ return mResources;
+ }
+ }
+
+ /**
+ * Class to run a CallerInfoAsyncQuery in a separate thread, with
+ * its own Looper. We cannot use the main Looper because on the
+ * 1st quit the thread is maked dead, ie no further test can use
+ * it. Also there is not way to inject a Looper instance in the
+ * query, so we have to use a thread with its own looper.
+ */
+ private class QueryRunner extends Thread
+ implements CallerInfoAsyncQuery.OnQueryCompleteListener {
+ private Looper mLooper;
+ private String mNumber;
+ private boolean mAsyncCompleted;
+
+ public QueryRunner(String number) {
+ super();
+ mNumber = number;
+ }
+
+ // Run the query in the thread, wait for completion.
+ public void runAndCheckCompletion() throws InterruptedException {
+ start();
+ join();
+ assertTrue(mAsyncCompleted);
+ }
+
+ @Override
+ public void run() {
+ Looper.prepare();
+ mLooper = Looper.myLooper();
+ mAsyncCompleted = false;
+ // The query will pick the thread local looper we've just prepared.
+ CallerInfoAsyncQuery.startQuery(kToken, mContext, mNumber, this, null);
+ mLooper.loop();
+ }
+
+ // Quit the Looper on the 1st callback
+ // (EVENT_EMERGENCY_NUMBER). There is another message
+ // (EVENT_END_OF_QUEUE) that will never be delivered because
+ // the test has exited. The corresponding stack trace
+ // "Handler{xxxxx} sending message to a Handler on a dead
+ // thread" can be ignored.
+ public void onQueryComplete(int token, Object cookie, CallerInfo info) {
+ mAsyncCompleted = true;
+ mInfo = info;
+ mLooper.quit();
+ }
+ }
+
+ /**
+ * Fail if mInfo does not contain a valid emergency CallerInfo instance.
+ */
+ private void assertIsValidEmergencyCallerInfo() throws Exception {
+ assertTrue(mInfo.isEmergencyNumber());
+
+ // For emergency caller info, phoneNumber should be set to the
+ // string emergency_call_dialog_number_for_display and the
+ // photoResource should be set to the picture_emergency drawable.
+ assertEquals(kEmergencyNumber, mInfo.phoneNumber);
+ assertEquals(com.android.internal.R.drawable.picture_emergency, mInfo.photoResource);
+
+ // The name should be null
+ assertNull(mInfo.name);
+ assertEquals(0, mInfo.namePresentation);
+ assertNull(mInfo.cnapName);
+ assertEquals(0, mInfo.numberPresentation);
+
+ assertFalse(mInfo.contactExists);
+ assertEquals(0, mInfo.person_id);
+ assertFalse(mInfo.needUpdate);
+ assertNull(mInfo.contactRefUri);
+
+ assertNull(mInfo.phoneLabel);
+ assertEquals(0, mInfo.numberType);
+ assertNull(mInfo.numberLabel);
+
+ assertNull(mInfo.contactRingtoneUri);
+ assertFalse(mInfo.shouldSendToVoicemail);
+
+ assertNull(mInfo.cachedPhoto);
+ assertFalse(mInfo.isCachedPhotoCurrent);
+ }
+}
diff --git a/tests/BrowserTestPlugin/jni/event/EventPlugin.cpp b/tests/BrowserTestPlugin/jni/event/EventPlugin.cpp
index 1263204..706c27e 100644
--- a/tests/BrowserTestPlugin/jni/event/EventPlugin.cpp
+++ b/tests/BrowserTestPlugin/jni/event/EventPlugin.cpp
@@ -36,27 +36,18 @@
extern ANPCanvasInterfaceV0 gCanvasI;
extern ANPLogInterfaceV0 gLogI;
extern ANPPaintInterfaceV0 gPaintI;
-extern ANPSurfaceInterfaceV0 gSurfaceI;
extern ANPTypefaceInterfaceV0 gTypefaceI;
///////////////////////////////////////////////////////////////////////////////
-EventPlugin::EventPlugin(NPP inst) : SubPlugin(inst) {
+EventPlugin::EventPlugin(NPP inst) : SubPlugin(inst) { }
- // initialize the drawing surface
- m_surfaceReady = false;
- m_surface = gSurfaceI.newRasterSurface(inst, kRGB_565_ANPBitmapFormat, false);
- if(!m_surface)
- gLogI.log(inst, kError_ANPLogType, "----%p Unable to create Raster surface", inst);
-}
+EventPlugin::~EventPlugin() { }
-EventPlugin::~EventPlugin() {
- gSurfaceI.deleteSurface(m_surface);
-}
+void EventPlugin::drawPlugin(const ANPBitmap& bitmap, const ANPRectI& clip) {
-void EventPlugin::drawPlugin(int surfaceWidth, int surfaceHeight) {
-
- gLogI.log(inst(), kDebug_ANPLogType, " ------ %p drawing the plugin (%d,%d)", inst(), surfaceWidth, surfaceHeight);
+ gLogI.log(inst(), kDebug_ANPLogType, " ------ %p drawing the plugin (%d,%d)",
+ inst(), bitmap.width, bitmap.height);
// get the plugin's dimensions according to the DOM
PluginObject *obj = (PluginObject*) inst()->pdata;
@@ -64,8 +55,8 @@
const int H = obj->window->height;
// compute the current zoom level
- const float zoomFactorW = static_cast<float>(surfaceWidth) / W;
- const float zoomFactorH = static_cast<float>(surfaceHeight) / H;
+ const float zoomFactorW = static_cast<float>(bitmap.width) / W;
+ const float zoomFactorH = static_cast<float>(bitmap.height) / H;
// check to make sure the zoom level is uniform
if (zoomFactorW + .01 < zoomFactorH && zoomFactorW - .01 > zoomFactorH)
@@ -76,15 +67,16 @@
const int fontSize = (int)(zoomFactorW * 16);
const int leftMargin = (int)(zoomFactorW * 10);
- // lock the surface
- ANPBitmap bitmap;
- if (!m_surfaceReady || !gSurfaceI.lock(m_surface, &bitmap, NULL)) {
- gLogI.log(inst(), kError_ANPLogType, " ------ %p unable to lock the plugin", inst());
- return;
- }
-
- // create a canvas
+ // create and clip a canvas
ANPCanvas* canvas = gCanvasI.newCanvas(&bitmap);
+
+ ANPRectF clipR;
+ clipR.left = clip.left;
+ clipR.top = clip.top;
+ clipR.right = clip.right;
+ clipR.bottom = clip.bottom;
+ gCanvasI.clipRect(canvas, &clipR);
+
gCanvasI.drawColor(canvas, 0xFFFFFFFF);
// configure the paint
@@ -106,10 +98,9 @@
const char c[] = "Browser Test Plugin";
gCanvasI.drawText(canvas, c, sizeof(c)-1, leftMargin, -fm.fTop, paint);
- // clean up variables and unlock the surface
+ // clean up variables
gPaintI.deletePaint(paint);
gCanvasI.deleteCanvas(canvas);
- gSurfaceI.unlock(m_surface);
}
void EventPlugin::printToDiv(const char* text, int length) {
@@ -149,23 +140,16 @@
int16 EventPlugin::handleEvent(const ANPEvent* evt) {
switch (evt->eventType) {
- case kDraw_ANPEventType:
- gLogI.log(inst(), kError_ANPLogType, " ------ %p the plugin did not request draw events", inst());
- break;
- case kSurface_ANPEventType:
- switch (evt->data.surface.action) {
- case kCreated_ANPSurfaceAction:
- m_surfaceReady = true;
+
+ case kDraw_ANPEventType: {
+ switch (evt->data.draw.model) {
+ case kBitmap_ANPDrawingModel:
+ drawPlugin(evt->data.draw.data.bitmap, evt->data.draw.clip);
return 1;
- case kDestroyed_ANPSurfaceAction:
- m_surfaceReady = false;
- return 1;
- case kChanged_ANPSurfaceAction:
- drawPlugin(evt->data.surface.data.changed.width,
- evt->data.surface.data.changed.height);
- return 1;
+ default:
+ break; // unknown drawing model
}
- break;
+ }
case kLifecycle_ANPEventType:
switch (evt->data.lifecycle.action) {
case kOnLoad_ANPLifecycleAction: {
diff --git a/tests/BrowserTestPlugin/jni/event/EventPlugin.h b/tests/BrowserTestPlugin/jni/event/EventPlugin.h
index 73dd6ea..88b7c9d 100644
--- a/tests/BrowserTestPlugin/jni/event/EventPlugin.h
+++ b/tests/BrowserTestPlugin/jni/event/EventPlugin.h
@@ -35,11 +35,8 @@
virtual int16 handleEvent(const ANPEvent* evt);
private:
- void drawPlugin(int surfaceWidth, int surfaceHeight);
+ void drawPlugin(const ANPBitmap& bitmap, const ANPRectI& clip);
void printToDiv(const char* text, int length);
-
- bool m_surfaceReady;
- ANPSurface* m_surface;
};
#endif // eventPlugin__DEFINED
diff --git a/tests/BrowserTestPlugin/jni/main.cpp b/tests/BrowserTestPlugin/jni/main.cpp
index 056ec4d..e3ad4a7 100644
--- a/tests/BrowserTestPlugin/jni/main.cpp
+++ b/tests/BrowserTestPlugin/jni/main.cpp
@@ -65,7 +65,6 @@
ANPLogInterfaceV0 gLogI;
ANPPaintInterfaceV0 gPaintI;
ANPPathInterfaceV0 gPathI;
-ANPSurfaceInterfaceV0 gSurfaceI;
ANPSystemInterfaceV0 gSystemI;
ANPTypefaceInterfaceV0 gTypefaceI;
ANPWindowInterfaceV0 gWindowI;
@@ -105,16 +104,10 @@
uint32_t size;
ANPInterface* i;
} gPairs[] = {
- { kAudioTrackInterfaceV0_ANPGetValue, sizeof(gSoundI), &gSoundI },
- { kBitmapInterfaceV0_ANPGetValue, sizeof(gBitmapI), &gBitmapI },
{ kCanvasInterfaceV0_ANPGetValue, sizeof(gCanvasI), &gCanvasI },
{ kLogInterfaceV0_ANPGetValue, sizeof(gLogI), &gLogI },
{ kPaintInterfaceV0_ANPGetValue, sizeof(gPaintI), &gPaintI },
- { kPathInterfaceV0_ANPGetValue, sizeof(gPathI), &gPathI },
- { kSurfaceInterfaceV0_ANPGetValue, sizeof(gSurfaceI), &gSurfaceI },
- { kSystemInterfaceV0_ANPGetValue, sizeof(gSystemI), &gSystemI },
{ kTypefaceInterfaceV0_ANPGetValue, sizeof(gTypefaceI), &gTypefaceI },
- { kWindowInterfaceV0_ANPGetValue, sizeof(gWindowI), &gWindowI },
};
for (size_t i = 0; i < ARRAY_COUNT(gPairs); i++) {
gPairs[i].i->inSize = gPairs[i].size;
@@ -156,7 +149,7 @@
}
// select the drawing model
- ANPDrawingModel model = kSurface_ANPDrawingModel;
+ ANPDrawingModel model = kBitmap_ANPDrawingModel;
// notify the plugin API of the drawing model we wish to use. This must be
// done prior to creating certain subPlugin objects (e.g. surfaceViews)
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index b00d8b0..b6b0e63 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -187,6 +187,13 @@
return 0;
}
+ // navigation hidden
+ if (getNavHiddenName(part.string(), &config)) {
+ *axis = AXIS_NAVHIDDEN;
+ *value = config.inputFlags;
+ return 0;
+ }
+
// navigation
if (getNavigationName(part.string(), &config)) {
*axis = AXIS_NAVIGATION;
@@ -217,7 +224,7 @@
Vector<String8> parts;
String8 mcc, mnc, loc, layoutsize, layoutlong, orient, den;
- String8 touch, key, keysHidden, nav, size, vers;
+ String8 touch, key, keysHidden, nav, navHidden, size, vers;
const char *p = dir;
const char *q;
@@ -393,6 +400,19 @@
//printf("not keyboard: %s\n", part.string());
}
+ // navigation hidden
+ if (getNavHiddenName(part.string())) {
+ navHidden = part;
+
+ index++;
+ if (index == N) {
+ goto success;
+ }
+ part = parts[index];
+ } else {
+ //printf("not navHidden: %s\n", part.string());
+ }
+
if (getNavigationName(part.string())) {
nav = part;
@@ -443,6 +463,7 @@
this->touchscreen = touch;
this->keysHidden = keysHidden;
this->keyboard = key;
+ this->navHidden = navHidden;
this->navigation = nav;
this->screenSize = size;
this->version = vers;
@@ -476,6 +497,8 @@
s += ",";
s += keyboard;
s += ",";
+ s += navHidden;
+ s += ",";
s += navigation;
s += ",";
s += screenSize;
@@ -528,6 +551,10 @@
s += "-";
s += keyboard;
}
+ if (this->navHidden != "") {
+ s += "-";
+ s += navHidden;
+ }
if (this->navigation != "") {
s += "-";
s += navigation;
@@ -852,6 +879,30 @@
return false;
}
+bool AaptGroupEntry::getNavHiddenName(const char* name,
+ ResTable_config* out)
+{
+ uint8_t mask = 0;
+ uint8_t value = 0;
+ if (strcmp(name, kWildcardName) == 0) {
+ mask = out->MASK_NAVHIDDEN;
+ value = out->NAVHIDDEN_ANY;
+ } else if (strcmp(name, "navexposed") == 0) {
+ mask = out->MASK_NAVHIDDEN;
+ value = out->NAVHIDDEN_NO;
+ } else if (strcmp(name, "navhidden") == 0) {
+ mask = out->MASK_NAVHIDDEN;
+ value = out->NAVHIDDEN_YES;
+ }
+
+ if (mask != 0) {
+ if (out) out->inputFlags = (out->inputFlags&~mask) | value;
+ return true;
+ }
+
+ return false;
+}
+
bool AaptGroupEntry::getNavigationName(const char* name,
ResTable_config* out)
{
@@ -953,6 +1004,7 @@
if (v == 0) v = touchscreen.compare(o.touchscreen);
if (v == 0) v = keysHidden.compare(o.keysHidden);
if (v == 0) v = keyboard.compare(o.keyboard);
+ if (v == 0) v = navHidden.compare(o.navHidden);
if (v == 0) v = navigation.compare(o.navigation);
if (v == 0) v = screenSize.compare(o.screenSize);
if (v == 0) v = version.compare(o.version);
@@ -973,6 +1025,7 @@
getTouchscreenName(touchscreen.string(), ¶ms);
getKeysHiddenName(keysHidden.string(), ¶ms);
getKeyboardName(keyboard.string(), ¶ms);
+ getNavHiddenName(navHidden.string(), ¶ms);
getNavigationName(navigation.string(), ¶ms);
getScreenSizeName(screenSize.string(), ¶ms);
getVersionName(version.string(), ¶ms);
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index 865efd1..26500a3 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -37,6 +37,7 @@
AXIS_TOUCHSCREEN,
AXIS_KEYSHIDDEN,
AXIS_KEYBOARD,
+ AXIS_NAVHIDDEN,
AXIS_NAVIGATION,
AXIS_SCREENSIZE,
AXIS_VERSION
@@ -64,6 +65,7 @@
String8 touchscreen;
String8 keysHidden;
String8 keyboard;
+ String8 navHidden;
String8 navigation;
String8 screenSize;
String8 version;
@@ -83,6 +85,7 @@
static bool getKeysHiddenName(const char* name, ResTable_config* out = NULL);
static bool getKeyboardName(const char* name, ResTable_config* out = NULL);
static bool getNavigationName(const char* name, ResTable_config* out = NULL);
+ static bool getNavHiddenName(const char* name, ResTable_config* out = NULL);
static bool getScreenSizeName(const char* name, ResTable_config* out = NULL);
static bool getVersionName(const char* name, ResTable_config* out = NULL);
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index f85aadd..954930e 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -42,24 +42,51 @@
public static final String priorityVarName = "priority";
/** {@hide} */
public static final String hiddenSSIDVarName = "scan_ssid";
+
/** {@hide} */
- public static final String eapVarName = "eap";
+ public class EnterpriseField {
+ private String varName;
+ private String value;
+
+ private EnterpriseField(String varName) {
+ this.varName = varName;
+ this.value = null;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public String varName() {
+ return varName;
+ }
+
+ public String value() {
+ return value;
+ }
+ }
+
/** {@hide} */
- public static final String phase2VarName = "phase2";
+ public EnterpriseField eap = new EnterpriseField("eap");
/** {@hide} */
- public static final String identityVarName = "identity";
+ public EnterpriseField phase2 = new EnterpriseField("phase2");
/** {@hide} */
- public static final String anonymousIdentityVarName = "anonymous_identity";
+ public EnterpriseField identity = new EnterpriseField("anonymous_identity");
/** {@hide} */
- public static final String passwordVarName = "password";
+ public EnterpriseField anonymous_identity = new EnterpriseField("anonymous_identity");
/** {@hide} */
- public static final String clientCertVarName = "client_cert";
+ public EnterpriseField password = new EnterpriseField("password");
/** {@hide} */
- public static final String caCertVarName = "ca_cert";
+ public EnterpriseField client_cert = new EnterpriseField("client_cert");
/** {@hide} */
- public static final String privateKeyVarName = "private_key";
+ public EnterpriseField private_key = new EnterpriseField("private_key");
/** {@hide} */
- public static final String privateKeyPasswdVarName = "private_key_passwd";
+ public EnterpriseField ca_cert = new EnterpriseField("ca_cert");
+
+ /** {@hide} */
+ public EnterpriseField[] enterpriseFields = {
+ eap, phase2, identity, anonymous_identity, password, client_cert,
+ private_key, ca_cert };
/**
* Recognized key management schemes.
@@ -267,44 +294,6 @@
*/
public BitSet allowedGroupCiphers;
- /* The following fields are used for EAP/IEEE8021X authentication */
-
- /**
- * The eap mode should be PEAP, TLS or TTLS.
- * {@hide}
- */
- public String eap;
- /**
- * The phase2 authenication could be PAP, MSCHAP, MSCHAP2, GTC.
- * {@hide}
- */
- public String phase2;
- /**
- * The identity of the user in string,
- * which is used for the authentication.
- * {@hide}
- */
- public String identity;
- /** {@hide} */
- public String anonymousIdentity;
- /** {@hide} */
- public String password;
- /** The path of the client certificate file.
- * {@hide}
- */
- public String clientCert;
- /** The path of the CA certificate file.
- * {@hide}
- */
- public String caCert;
- /** The path of the private key file.
- * {@hide}
- */
- public String privateKey;
- /** The password of the private key file if encrypted.
- * {@hide}
- */
- public String privateKeyPasswd;
public WifiConfiguration() {
networkId = -1;
@@ -320,15 +309,9 @@
wepKeys = new String[4];
for (int i = 0; i < wepKeys.length; i++)
wepKeys[i] = null;
- eap = null;
- phase2 = null;
- identity = null;
- anonymousIdentity = null;
- password = null;
- clientCert = null;
- caCert = null;
- privateKey = null;
- privateKeyPasswd = null;
+ for (EnterpriseField field : enterpriseFields) {
+ field.setValue(null);
+ }
}
public String toString() {
@@ -403,41 +386,11 @@
if (this.preSharedKey != null) {
sbuf.append('*');
}
- sbuf.append('\n').append(" eap: ");
- if (this.eap != null) {
- sbuf.append(eap);
- }
- sbuf.append('\n').append(" phase2: ");
- if (this.phase2 != null) {
- sbuf.append(phase2);
- }
- sbuf.append('\n').append(" Identity: ");
- if (this.identity != null) {
- sbuf.append(identity);
- }
- sbuf.append('\n').append(" AnonymousIdentity: ");
- if (this.anonymousIdentity != null) {
- sbuf.append(anonymousIdentity);
- }
- sbuf.append('\n').append(" Password: ");
- if (this.password != null) {
- sbuf.append(password);
- }
- sbuf.append('\n').append(" ClientCert: ");
- if (this.clientCert != null) {
- sbuf.append(clientCert);
- }
- sbuf.append('\n').append(" CaCert: ");
- if (this.caCert != null) {
- sbuf.append(caCert);
- }
- sbuf.append('\n').append(" PrivateKey: ");
- if (this.privateKey != null) {
- sbuf.append(privateKey);
- }
- sbuf.append('\n').append(" PrivateKeyPasswd: ");
- if (this.privateKeyPasswd != null) {
- sbuf.append(privateKeyPasswd);
+
+ for (EnterpriseField field : enterpriseFields) {
+ sbuf.append('\n').append(" " + field.varName() + ": ");
+ String value = field.value();
+ if (value != null) sbuf.append(value);
}
sbuf.append('\n');
return sbuf.toString();
@@ -497,15 +450,10 @@
writeBitSet(dest, allowedAuthAlgorithms);
writeBitSet(dest, allowedPairwiseCiphers);
writeBitSet(dest, allowedGroupCiphers);
- dest.writeString(eap);
- dest.writeString(phase2);
- dest.writeString(identity);
- dest.writeString(anonymousIdentity);
- dest.writeString(password);
- dest.writeString(clientCert);
- dest.writeString(caCert);
- dest.writeString(privateKey);
- dest.writeString(privateKeyPasswd);
+
+ for (EnterpriseField field : enterpriseFields) {
+ dest.writeString(field.value());
+ }
}
/** Implement the Parcelable interface {@hide} */
@@ -528,15 +476,10 @@
config.allowedAuthAlgorithms = readBitSet(in);
config.allowedPairwiseCiphers = readBitSet(in);
config.allowedGroupCiphers = readBitSet(in);
- config.eap = in.readString();
- config.phase2 = in.readString();
- config.identity = in.readString();
- config.anonymousIdentity = in.readString();
- config.password = in.readString();
- config.clientCert = in.readString();
- config.caCert = in.readString();
- config.privateKey = in.readString();
- config.privateKeyPasswd = in.readString();
+
+ for (EnterpriseField field : config.enterpriseFields) {
+ field.setValue(in.readString());
+ }
return config;
}