Merge "Make ImageProcessing work." into honeycomb
diff --git a/api/11.xml b/api/11.xml
index 1733652..1ac57a1 100644
--- a/api/11.xml
+++ b/api/11.xml
@@ -4250,6 +4250,17 @@
visibility="public"
>
</field>
+<field name="fastScrollTextColor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843611"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="fastScrollThumbDrawable"
type="int"
transient="false"
@@ -5812,6 +5823,17 @@
visibility="public"
>
</field>
+<field name="largeHeap"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843612"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="largeScreens"
type="int"
transient="false"
@@ -11462,6 +11484,28 @@
visibility="public"
>
</field>
+<field name="notification_large_icon_height"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104902"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="notification_large_icon_width"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="17104901"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="thumbnail_height"
type="int"
transient="false"
@@ -25114,17 +25158,6 @@
visibility="public"
>
</field>
-<field name="TASKS_GET_THUMBNAILS"
- type="int"
- transient="false"
- volatile="false"
- value="4096"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
</class>
<class name="ActivityManager.MemoryInfo"
extends="java.lang.Object"
@@ -25523,16 +25556,6 @@
visibility="public"
>
</field>
-<field name="thumbnail"
- type="android.graphics.Bitmap"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
</class>
<class name="ActivityManager.RunningAppProcessInfo"
extends="java.lang.Object"
@@ -38947,6 +38970,17 @@
visibility="public"
>
</method>
+<method name="clearViews"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
<method name="createView"
return="android.appwidget.AppWidgetHostView"
abstract="false"
@@ -48119,6 +48153,17 @@
visibility="public"
>
</method>
+<method name="getObbDir"
+ return="java.io.File"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getPackageCodePath"
return="java.lang.String"
abstract="true"
@@ -49727,6 +49772,17 @@
visibility="public"
>
</method>
+<method name="getObbDir"
+ return="java.io.File"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getPackageCodePath"
return="java.lang.String"
abstract="false"
@@ -58210,6 +58266,17 @@
visibility="public"
>
</field>
+<field name="FLAG_LARGE_HEAP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1048576"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="FLAG_PERSISTENT"
type="int"
transient="false"
@@ -60220,6 +60287,19 @@
<exception name="PackageManager.NameNotFoundException" type="android.content.pm.PackageManager.NameNotFoundException">
</exception>
</method>
+<method name="getPackageObbPaths"
+ return="java.lang.String[]"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+</method>
<method name="getPackagesForUid"
return="java.lang.String[]"
abstract="true"
@@ -60706,6 +60786,21 @@
<parameter name="installerPackageName" type="java.lang.String">
</parameter>
</method>
+<method name="setPackageObbPaths"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+<parameter name="paths" type="java.lang.String[]">
+</parameter>
+</method>
<field name="COMPONENT_ENABLED_STATE_DEFAULT"
type="int"
transient="false"
@@ -137446,6 +137541,34 @@
<parameter name="params" type="Params...">
</parameter>
</method>
+<method name="execute"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="runnable" type="java.lang.Runnable">
+</parameter>
+</method>
+<method name="executeOnExecutor"
+ return="android.os.AsyncTask<Params, Progress, Result>"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="exec" type="java.util.concurrent.Executor">
+</parameter>
+<parameter name="params" type="Params...">
+</parameter>
+</method>
<method name="get"
return="Result"
abstract="false"
@@ -137578,6 +137701,16 @@
<parameter name="values" type="Progress...">
</parameter>
</method>
+<field name="THREAD_POOL_EXECUTOR"
+ type="java.util.concurrent.ThreadPoolExecutor"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
</class>
<class name="AsyncTask.Status"
extends="java.lang.Enum"
@@ -185171,6 +185304,19 @@
<exception name="PackageManager.NameNotFoundException" type="android.content.pm.PackageManager.NameNotFoundException">
</exception>
</method>
+<method name="getPackageObbPaths"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+</method>
<method name="getPackagesForUid"
return="java.lang.String[]"
abstract="false"
@@ -185670,6 +185816,21 @@
<parameter name="path" type="java.lang.String">
</parameter>
</method>
+<method name="setPackageObbPaths"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+<parameter name="paths" type="java.lang.String[]">
+</parameter>
+</method>
</class>
<class name="MockResources"
extends="android.content.res.Resources"
@@ -238084,6 +238245,34 @@
>
</field>
</class>
+<class name="WebViewFragment"
+ extends="android.app.Fragment"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="WebViewFragment"
+ type="android.webkit.WebViewFragment"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getWebView"
+ return="android.webkit.WebView"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
</package>
<package name="android.widget"
>
diff --git a/api/current.xml b/api/current.xml
index d141409..6b79074 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -25158,17 +25158,6 @@
visibility="public"
>
</field>
-<field name="TASKS_GET_THUMBNAILS"
- type="int"
- transient="false"
- volatile="false"
- value="4096"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
</class>
<class name="ActivityManager.MemoryInfo"
extends="java.lang.Object"
@@ -25567,16 +25556,6 @@
visibility="public"
>
</field>
-<field name="thumbnail"
- type="android.graphics.Bitmap"
- transient="false"
- volatile="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
</class>
<class name="ActivityManager.RunningAppProcessInfo"
extends="java.lang.Object"
@@ -48174,6 +48153,17 @@
visibility="public"
>
</method>
+<method name="getObbDir"
+ return="java.io.File"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getPackageCodePath"
return="java.lang.String"
abstract="true"
@@ -49782,6 +49772,17 @@
visibility="public"
>
</method>
+<method name="getObbDir"
+ return="java.io.File"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="getPackageCodePath"
return="java.lang.String"
abstract="false"
@@ -61561,6 +61562,36 @@
visibility="public"
>
</field>
+<field name="externalCacheSize"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="externalDataSize"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="externalMediaSize"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="packageName"
type="java.lang.String"
transient="false"
@@ -95576,6 +95607,17 @@
visibility="public"
>
</field>
+<field name="TOUCHABLE_INSETS_REGION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="TOUCHABLE_INSETS_VISIBLE"
type="int"
transient="false"
@@ -95607,6 +95649,16 @@
visibility="public"
>
</field>
+<field name="touchableRegion"
+ type="android.graphics.Region"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="visibleTopInsets"
type="int"
transient="false"
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 1590bf4..5705057 100755
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -1192,4 +1192,16 @@
public static int getCurrentAnimationsCount() {
return sAnimations.get().size();
}
+
+ /**
+ * Clear all animations on this thread, without canceling or ending them.
+ * This should be used with caution.
+ *
+ * @hide
+ */
+ public static void clearAllAnimations() {
+ sAnimations.get().clear();
+ sPendingAnimations.get().clear();
+ sDelayedAnims.get().clear();
+ }
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 4eae14b..d5aa961 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -122,6 +122,8 @@
/**
* Thumbnail representation of the task's last state. Must
* use {@link ActivityManager#TASKS_GET_THUMBNAILS} to have this set.
+ * @hide -- this is not scalable, need to have a separate API to get
+ * the bitmap.
*/
public Bitmap thumbnail;
@@ -203,6 +205,7 @@
/**
* Flag for use with {@link #getRecentTasks}: also return the thumbnail
* bitmap (if available) for each recent task.
+ * @hide
*/
public static final int TASKS_GET_THUMBNAILS = 0x0001000;
@@ -214,8 +217,7 @@
* actual number returned may be smaller, depending on how many tasks the
* user has started and the maximum number the system can remember.
* @param flags Information about what to return. May be any combination
- * of {@link #RECENT_WITH_EXCLUDED}, {@link #RECENT_IGNORE_UNAVAILABLE},
- * and {@link #TASKS_GET_THUMBNAILS}.
+ * of {@link #RECENT_WITH_EXCLUDED} and {@link #RECENT_IGNORE_UNAVAILABLE}.
*
* @return Returns a list of RecentTaskInfo records describing each of
* the recent tasks.
@@ -261,8 +263,8 @@
public ComponentName topActivity;
/**
- * Thumbnail representation of the task's current state. Must
- * use {@link ActivityManager#TASKS_GET_THUMBNAILS} to have this set.
+ * Thumbnail representation of the task's current state. Currently
+ * always null.
*/
public Bitmap thumbnail;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index e133ea0..6f63990 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -153,6 +153,7 @@
private File mPreferencesDir;
private File mFilesDir;
private File mCacheDir;
+ private File mObbDir;
private File mExternalFilesDir;
private File mExternalCacheDir;
@@ -647,6 +648,17 @@
}
@Override
+ public File getObbDir() {
+ synchronized (mSync) {
+ if (mObbDir == null) {
+ mObbDir = Environment.getExternalStorageAppObbDirectory(
+ getPackageName());
+ }
+ return mObbDir;
+ }
+ }
+
+ @Override
public File getCacheDir() {
synchronized (mSync) {
if (mCacheDir == null) {
diff --git a/core/java/android/app/NativeActivity.java b/core/java/android/app/NativeActivity.java
index a5c49ec..35cc324 100644
--- a/core/java/android/app/NativeActivity.java
+++ b/core/java/android/app/NativeActivity.java
@@ -84,7 +84,7 @@
private boolean mDestroyed;
private native int loadNativeCode(String path, String funcname, MessageQueue queue,
- String internalDataPath, String externalDataPath, int sdkVersion,
+ String internalDataPath, String obbPath, String externalDataPath, int sdkVersion,
AssetManager assetMgr, byte[] savedState);
private native void unloadNativeCode(int handle);
@@ -191,7 +191,7 @@
? savedInstanceState.getByteArray(KEY_NATIVE_SAVED_STATE) : null;
mNativeHandle = loadNativeCode(path, funcname, Looper.myQueue(),
- getFilesDir().toString(),
+ getFilesDir().toString(), getObbDir().toString(),
Environment.getExternalStorageAppFilesDirectory(ai.packageName).toString(),
Build.VERSION.SDK_INT, getAssets(), nativeSavedState);
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 4f8ee93..d8adc6c 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -94,8 +94,12 @@
public AppWidgetHostView(Context context, int animationIn, int animationOut) {
super(context);
mContext = context;
+
+ // We want to segregate the view ids within AppWidgets to prevent
+ // problems when those ids collide with view ids in the AppWidgetHost.
+ setIsRootNamespace(true);
}
-
+
/**
* Set the AppWidget that will be displayed by this view.
*/
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 227df21..d14cf4d 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -516,6 +516,13 @@
public abstract File getExternalFilesDir(String type);
/**
+ * Return the directory where this application's OBB files (if there
+ * are any) can be found. Note if the application does not have any OBB
+ * files, this directory may not exist.
+ */
+ public abstract File getObbDir();
+
+ /**
* Returns the absolute path to the application specific cache directory
* on the filesystem. These files will be ones that get deleted first when the
* device runs low on storage.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 545144e..3928aaf 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -191,6 +191,11 @@
}
@Override
+ public File getObbDir() {
+ return mBase.getObbDir();
+ }
+
+ @Override
public File getCacheDir() {
return mBase.getCacheDir();
}
diff --git a/core/java/android/content/pm/PackageStats.java b/core/java/android/content/pm/PackageStats.java
index 9464321..28a2886 100755
--- a/core/java/android/content/pm/PackageStats.java
+++ b/core/java/android/content/pm/PackageStats.java
@@ -19,20 +19,44 @@
import android.os.Parcel;
import android.os.Parcelable;
-import java.util.Arrays;
-
/**
* implementation of PackageStats associated with a
* application package.
*/
public class PackageStats implements Parcelable {
+ /** Name of the package to which this stats applies. */
public String packageName;
+
+ /** Size of the code (e.g., APK) */
public long codeSize;
+
+ /**
+ * Size of the internal data size for the application. (e.g.,
+ * /data/data/<app>)
+ */
public long dataSize;
+
+ /** Size of cache used by the application. (e.g., /data/data/<app>/cache) */
public long cacheSize;
-
+
+ /**
+ * Size of the external data used by the application (e.g.,
+ * <sdcard>/Android/data/<app>)
+ */
+ public long externalDataSize;
+
+ /**
+ * Size of the external cache used by the application (i.e., on the SD
+ * card). If this is a subdirectory of the data directory, this size will be
+ * subtracted out of the external data size.
+ */
+ public long externalCacheSize;
+
+ /** Size of the external media size used by the application. */
+ public long externalMediaSize;
+
public static final Parcelable.Creator<PackageStats> CREATOR
- = new Parcelable.Creator<PackageStats>() {
+ = new Parcelable.Creator<PackageStats>() {
public PackageStats createFromParcel(Parcel in) {
return new PackageStats(in);
}
@@ -41,29 +65,49 @@
return new PackageStats[size];
}
};
-
+
public String toString() {
- return "PackageStats{"
- + Integer.toHexString(System.identityHashCode(this))
- + " " + packageName + "}";
+ final StringBuilder sb = new StringBuilder("PackageStats{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(" packageName=");
+ sb.append(packageName);
+ sb.append(",codeSize=");
+ sb.append(codeSize);
+ sb.append(",dataSize=");
+ sb.append(dataSize);
+ sb.append(",cacheSize=");
+ sb.append(cacheSize);
+ sb.append(",externalDataSize=");
+ sb.append(externalDataSize);
+ sb.append(",externalCacheSize=");
+ sb.append(externalCacheSize);
+ sb.append(",externalMediaSize=");
+ sb.append(externalMediaSize);
+ return sb.toString();
}
-
+
public PackageStats(String pkgName) {
packageName = pkgName;
}
-
+
public PackageStats(Parcel source) {
packageName = source.readString();
codeSize = source.readLong();
dataSize = source.readLong();
cacheSize = source.readLong();
+ externalDataSize = source.readLong();
+ externalCacheSize = source.readLong();
+ externalMediaSize = source.readLong();
}
-
+
public PackageStats(PackageStats pStats) {
packageName = pStats.packageName;
codeSize = pStats.codeSize;
dataSize = pStats.dataSize;
cacheSize = pStats.cacheSize;
+ externalDataSize = pStats.externalDataSize;
+ externalCacheSize = pStats.externalCacheSize;
+ externalMediaSize = pStats.externalMediaSize;
}
public int describeContents() {
@@ -75,5 +119,8 @@
dest.writeLong(codeSize);
dest.writeLong(dataSize);
dest.writeLong(cacheSize);
+ dest.writeLong(externalDataSize);
+ dest.writeLong(externalCacheSize);
+ dest.writeLong(externalMediaSize);
}
}
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 406b091..6baf1c2 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -283,6 +283,7 @@
private Rect mContentInsetsBuffer = null;
private Rect mVisibleInsetsBuffer = null;
+ private Region mTouchableAreaBuffer = null;
Translator(float applicationScale, float applicationInvertedScale) {
this.applicationScale = applicationScale;
@@ -395,14 +396,25 @@
/**
* Translate the visible insets in application window to Screen. This uses
- * the internal buffer for content insets to avoid extra object allocation.
+ * the internal buffer for visible insets to avoid extra object allocation.
*/
- public Rect getTranslatedVisbileInsets(Rect visibleInsets) {
+ public Rect getTranslatedVisibleInsets(Rect visibleInsets) {
if (mVisibleInsetsBuffer == null) mVisibleInsetsBuffer = new Rect();
mVisibleInsetsBuffer.set(visibleInsets);
translateRectInAppWindowToScreen(mVisibleInsetsBuffer);
return mVisibleInsetsBuffer;
}
+
+ /**
+ * Translate the touchable area in application window to Screen. This uses
+ * the internal buffer for touchable area to avoid extra object allocation.
+ */
+ public Region getTranslatedTouchableArea(Region touchableArea) {
+ if (mTouchableAreaBuffer == null) mTouchableAreaBuffer = new Region();
+ mTouchableAreaBuffer.set(touchableArea);
+ mTouchableAreaBuffer.scale(applicationScale);
+ return mTouchableAreaBuffer;
+ }
}
/**
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 23b9ad5..4d25bac 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -25,6 +25,7 @@
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Rect;
+import android.graphics.Region;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ResultReceiver;
@@ -283,11 +284,13 @@
View decor = getWindow().getWindow().getDecorView();
info.contentInsets.top = info.visibleInsets.top
= decor.getHeight();
+ info.touchableRegion.setEmpty();
info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
} else {
onComputeInsets(mTmpInsets);
info.contentInsets.top = mTmpInsets.contentTopInsets;
info.visibleInsets.top = mTmpInsets.visibleTopInsets;
+ info.touchableRegion.set(mTmpInsets.touchableRegion);
info.setTouchableInsets(mTmpInsets.touchableInsets);
}
}
@@ -510,7 +513,14 @@
* of the input method window.
*/
public int visibleTopInsets;
-
+
+ /**
+ * This is the region of the UI that is touchable. It is used when
+ * {@link #touchableInsets} is set to {@link #TOUCHABLE_INSETS_REGION}.
+ * The region should be specified relative to the origin of the window frame.
+ */
+ public final Region touchableRegion = new Region();
+
/**
* Option for {@link #touchableInsets}: the entire window frame
* can be touched.
@@ -531,11 +541,19 @@
*/
public static final int TOUCHABLE_INSETS_VISIBLE
= ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE;
-
+
+ /**
+ * Option for {@link #touchableInsets}: the region specified by
+ * {@link #touchableRegion} can be touched.
+ */
+ public static final int TOUCHABLE_INSETS_REGION
+ = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
+
/**
* Determine which area of the window is touchable by the user. May
* be one of: {@link #TOUCHABLE_INSETS_FRAME},
- * {@link #TOUCHABLE_INSETS_CONTENT}, or {@link #TOUCHABLE_INSETS_VISIBLE}.
+ * {@link #TOUCHABLE_INSETS_CONTENT}, {@link #TOUCHABLE_INSETS_VISIBLE},
+ * or {@link #TOUCHABLE_INSETS_REGION}.
*/
public int touchableInsets;
}
@@ -950,6 +968,7 @@
}
outInsets.visibleTopInsets = loc[1];
outInsets.touchableInsets = Insets.TOUCHABLE_INSETS_VISIBLE;
+ outInsets.touchableRegion.setEmpty();
}
/**
@@ -2153,6 +2172,7 @@
p.println("Last computed insets:");
p.println(" contentTopInsets=" + mTmpInsets.contentTopInsets
+ " visibleTopInsets=" + mTmpInsets.visibleTopInsets
- + " touchableInsets=" + mTmpInsets.touchableInsets);
+ + " touchableInsets=" + mTmpInsets.touchableInsets
+ + " touchableRegion=" + mTmpInsets.touchableRegion);
}
}
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 4f188f8..cc95642 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -107,6 +107,10 @@
= new File (new File(getDirectory("EXTERNAL_STORAGE", "/sdcard"),
"Android"), "media");
+ private static final File EXTERNAL_STORAGE_ANDROID_OBB_DIRECTORY
+ = new File (new File(getDirectory("EXTERNAL_STORAGE", "/sdcard"),
+ "Android"), "obb");
+
private static final File DOWNLOAD_CACHE_DIRECTORY
= getDirectory("DOWNLOAD_CACHE", "/cache");
@@ -304,6 +308,14 @@
}
/**
+ * Generates the raw path to an application's OBB files
+ * @hide
+ */
+ public static File getExternalStorageAppObbDirectory(String packageName) {
+ return new File(EXTERNAL_STORAGE_ANDROID_OBB_DIRECTORY, packageName);
+ }
+
+ /**
* Generates the path to an application's files.
* @hide
*/
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index a5f405a..1218e81 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -101,7 +101,7 @@
* {@link android.view.ViewTreeObserver.InternalInsetsInfo}.
*/
void setInsets(IWindow window, int touchableInsets, in Rect contentInsets,
- in Rect visibleInsets);
+ in Rect visibleInsets, in Region touchableRegion);
/**
* Return the current display size in which the window is being laid out,
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index e228537..96f8cdc 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1229,24 +1229,34 @@
}
if (computesInternalInsets) {
- ViewTreeObserver.InternalInsetsInfo insets = attachInfo.mGivenInternalInsets;
- final Rect givenContent = attachInfo.mGivenInternalInsets.contentInsets;
- final Rect givenVisible = attachInfo.mGivenInternalInsets.visibleInsets;
- givenContent.left = givenContent.top = givenContent.right
- = givenContent.bottom = givenVisible.left = givenVisible.top
- = givenVisible.right = givenVisible.bottom = 0;
+ // Clear the original insets.
+ final ViewTreeObserver.InternalInsetsInfo insets = attachInfo.mGivenInternalInsets;
+ insets.reset();
+
+ // Compute new insets in place.
attachInfo.mTreeObserver.dispatchOnComputeInternalInsets(insets);
- Rect contentInsets = insets.contentInsets;
- Rect visibleInsets = insets.visibleInsets;
- if (mTranslator != null) {
- contentInsets = mTranslator.getTranslatedContentInsets(contentInsets);
- visibleInsets = mTranslator.getTranslatedVisbileInsets(visibleInsets);
- }
+
+ // Tell the window manager.
if (insetsPending || !mLastGivenInsets.equals(insets)) {
mLastGivenInsets.set(insets);
+
+ // Translate insets to screen coordinates if needed.
+ final Rect contentInsets;
+ final Rect visibleInsets;
+ final Region touchableRegion;
+ if (mTranslator != null) {
+ contentInsets = mTranslator.getTranslatedContentInsets(insets.contentInsets);
+ visibleInsets = mTranslator.getTranslatedVisibleInsets(insets.visibleInsets);
+ touchableRegion = mTranslator.getTranslatedTouchableArea(insets.touchableRegion);
+ } else {
+ contentInsets = insets.contentInsets;
+ visibleInsets = insets.visibleInsets;
+ touchableRegion = insets.touchableRegion;
+ }
+
try {
sWindowSession.setInsets(mWindow, insets.mTouchableInsets,
- contentInsets, visibleInsets);
+ contentInsets, visibleInsets, touchableRegion);
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
index 06a0fa6..db87175 100644
--- a/core/java/android/view/ViewTreeObserver.java
+++ b/core/java/android/view/ViewTreeObserver.java
@@ -17,6 +17,7 @@
package android.view;
import android.graphics.Rect;
+import android.graphics.Region;
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -126,11 +127,18 @@
public final Rect contentInsets = new Rect();
/**
- * Offsets from the fram of the window at which windows behind it
+ * Offsets from the frame of the window at which windows behind it
* are visible.
*/
public final Rect visibleInsets = new Rect();
-
+
+ /**
+ * Touchable region defined relative to the origin of the frame of the window.
+ * Only used when {@link #setTouchableInsets(int)} is called with
+ * the option {@link #TOUCHABLE_INSETS_REGION}.
+ */
+ public final Region touchableRegion = new Region();
+
/**
* Option for {@link #setTouchableInsets(int)}: the entire window frame
* can be touched.
@@ -148,11 +156,17 @@
* the visible insets can be touched.
*/
public static final int TOUCHABLE_INSETS_VISIBLE = 2;
-
+
+ /**
+ * Option for {@link #setTouchableInsets(int)}: the area inside of
+ * the provided touchable region in {@link #touchableRegion} can be touched.
+ */
+ public static final int TOUCHABLE_INSETS_REGION = 3;
+
/**
* Set which parts of the window can be touched: either
* {@link #TOUCHABLE_INSETS_FRAME}, {@link #TOUCHABLE_INSETS_CONTENT},
- * or {@link #TOUCHABLE_INSETS_VISIBLE}.
+ * {@link #TOUCHABLE_INSETS_VISIBLE}, or {@link #TOUCHABLE_INSETS_REGION}.
*/
public void setTouchableInsets(int val) {
mTouchableInsets = val;
@@ -165,11 +179,9 @@
int mTouchableInsets;
void reset() {
- final Rect givenContent = contentInsets;
- final Rect givenVisible = visibleInsets;
- givenContent.left = givenContent.top = givenContent.right
- = givenContent.bottom = givenVisible.left = givenVisible.top
- = givenVisible.right = givenVisible.bottom = 0;
+ contentInsets.setEmpty();
+ visibleInsets.setEmpty();
+ touchableRegion.setEmpty();
mTouchableInsets = TOUCHABLE_INSETS_FRAME;
}
@@ -179,13 +191,16 @@
return false;
}
InternalInsetsInfo other = (InternalInsetsInfo)o;
+ if (mTouchableInsets != other.mTouchableInsets) {
+ return false;
+ }
if (!contentInsets.equals(other.contentInsets)) {
return false;
}
if (!visibleInsets.equals(other.visibleInsets)) {
return false;
}
- return mTouchableInsets == other.mTouchableInsets;
+ return touchableRegion.equals(other.touchableRegion);
} catch (ClassCastException e) {
return false;
}
@@ -194,6 +209,7 @@
void set(InternalInsetsInfo other) {
contentInsets.set(other.contentInsets);
visibleInsets.set(other.visibleInsets);
+ touchableRegion.set(other.touchableRegion);
mTouchableInsets = other.mTouchableInsets;
}
}
diff --git a/core/java/android/widget/StackView.java b/core/java/android/widget/StackView.java
index 264af71..2c10077 100644
--- a/core/java/android/widget/StackView.java
+++ b/core/java/android/widget/StackView.java
@@ -1,5 +1,4 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
+/* Copyright (C) 2010 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.
@@ -209,22 +208,19 @@
}
}
- if (fromIndex == -1 && toIndex == NUM_ACTIVE_VIEWS -1) {
+ if (fromIndex == -1 && toIndex == getNumActiveViews() -1) {
// Fade item in
if (view.getAlpha() == 1) {
view.setAlpha(0);
}
- view.setScaleX(1 - PERSPECTIVE_SCALE_FACTOR);
- view.setScaleY(1 - PERSPECTIVE_SCALE_FACTOR);
- view.setTranslationX(mPerspectiveShiftX);
- view.setTranslationY(0);
+ transformViewAtIndex(toIndex, view, false);
view.setVisibility(VISIBLE);
alphaOa = ObjectAnimator.ofFloat(view, "alpha", view.getAlpha(), 1.0f);
alphaOa.setDuration(FADE_IN_ANIMATION_DURATION);
if (oldAlphaOa != null) oldAlphaOa.cancel();
alphaOa.start();
- view.setTagInternal(com.android.internal.R.id.viewAlphaAnimation,
+ view.setTagInternal(com.android.internal.R.id.viewAlphaAnimation,
new WeakReference<ObjectAnimator>(alphaOa));
} else if (fromIndex == 0 && toIndex == 1) {
// Slide item in
@@ -270,7 +266,7 @@
alphaOa.setDuration(STACK_RELAYOUT_DURATION);
if (oldAlphaOa != null) oldAlphaOa.cancel();
alphaOa.start();
- view.setTagInternal(com.android.internal.R.id.viewAlphaAnimation,
+ view.setTagInternal(com.android.internal.R.id.viewAlphaAnimation,
new WeakReference<ObjectAnimator>(alphaOa));
}
@@ -284,16 +280,20 @@
final float maxPerspectiveShiftY = mPerspectiveShiftY;
final float maxPerspectiveShiftX = mPerspectiveShiftX;
- index = mMaxNumActiveViews - index - 1;
- if (index == mMaxNumActiveViews - 1) index--;
+ if (mStackMode == ITEMS_SLIDE_DOWN) {
+ index = mMaxNumActiveViews - index - 1;
+ if (index == mMaxNumActiveViews - 1) index--;
+ } else {
+ index--;
+ if (index < 0) index++;
+ }
float r = (index * 1.0f) / (mMaxNumActiveViews - 2);
final float scale = 1 - PERSPECTIVE_SCALE_FACTOR * (1 - r);
- int stackDirection = (mStackMode == ITEMS_SLIDE_UP) ? 1 : -1;
- float perspectiveTranslationY = -stackDirection * r * maxPerspectiveShiftY;
- float scaleShiftCorrectionY = stackDirection * (1 - scale) *
+ float perspectiveTranslationY = r * maxPerspectiveShiftY;
+ float scaleShiftCorrectionY = (scale - 1) *
(getMeasuredHeight() * (1 - PERSPECTIVE_SHIFT_FACTOR_Y) / 2.0f);
final float transY = perspectiveTranslationY + scaleShiftCorrectionY;
@@ -302,7 +302,7 @@
(getMeasuredWidth() * (1 - PERSPECTIVE_SHIFT_FACTOR_X) / 2.0f);
final float transX = perspectiveTranslationX + scaleShiftCorrectionX;
- // If this view is currently being animated for a certain position, we need to cancel
+ // If this view is currently being animated for a certain position, we need to cancel
// this animation so as not to interfere with the new transformation.
Object tag = view.getTag(com.android.internal.R.id.viewAnimation);
if (tag instanceof WeakReference<?>) {
@@ -515,11 +515,12 @@
private void beginGestureIfNeeded(float deltaY) {
if ((int) Math.abs(deltaY) > mTouchSlop && mSwipeGestureType == GESTURE_NONE) {
- int swipeGestureType = deltaY < 0 ? GESTURE_SLIDE_UP : GESTURE_SLIDE_DOWN;
+ final int swipeGestureType = deltaY < 0 ? GESTURE_SLIDE_UP : GESTURE_SLIDE_DOWN;
cancelLongPress();
requestDisallowInterceptTouchEvent(true);
if (mAdapter == null) return;
+ final int adapterCount = mAdapter.getCount();
int activeIndex;
if (mStackMode == ITEMS_SLIDE_UP) {
@@ -528,13 +529,20 @@
activeIndex = (swipeGestureType == GESTURE_SLIDE_DOWN) ? 1 : 0;
}
+ boolean endOfStack = mLoopViews && adapterCount == 1 &&
+ ((mStackMode == ITEMS_SLIDE_UP && swipeGestureType == GESTURE_SLIDE_UP) ||
+ (mStackMode == ITEMS_SLIDE_DOWN && swipeGestureType == GESTURE_SLIDE_DOWN));
+ boolean beginningOfStack = mLoopViews && adapterCount == 1 &&
+ ((mStackMode == ITEMS_SLIDE_DOWN && swipeGestureType == GESTURE_SLIDE_UP) ||
+ (mStackMode == ITEMS_SLIDE_UP && swipeGestureType == GESTURE_SLIDE_DOWN));
+
int stackMode;
- if (mLoopViews) {
+ if (mLoopViews && !beginningOfStack && !endOfStack) {
stackMode = StackSlider.NORMAL_MODE;
- } else if (mCurrentWindowStartUnbounded + activeIndex == -1) {
+ } else if (mCurrentWindowStartUnbounded + activeIndex == -1 || beginningOfStack) {
activeIndex++;
stackMode = StackSlider.BEGINNING_OF_STACK_MODE;
- } else if (mCurrentWindowStartUnbounded + activeIndex == mAdapter.getCount() - 1) {
+ } else if (mCurrentWindowStartUnbounded + activeIndex == adapterCount - 1 || endOfStack) {
stackMode = StackSlider.END_OF_STACK_MODE;
} else {
stackMode = StackSlider.NORMAL_MODE;
@@ -989,6 +997,11 @@
@Override
public void advance() {
long timeSinceLastInteraction = System.currentTimeMillis() - mLastInteractionTime;
+
+ if (mAdapter == null) return;
+ final int adapterCount = mAdapter.getCount();
+ if (adapterCount == 1 && mLoopViews) return;
+
if (mSwipeGestureType == GESTURE_NONE &&
timeSinceLastInteraction > MIN_TIME_BETWEEN_INTERACTION_AND_AUTOADVANCE) {
showNext();
@@ -1266,4 +1279,4 @@
mask.recycle();
}
}
-}
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index 8e491e9..8825c02 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -20,7 +20,6 @@
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
-import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
@@ -44,6 +43,7 @@
private MenuBuilder mMenu;
private int mMaxItems;
+ private int mWidthLimit;
private boolean mReserveOverflow;
private OverflowMenuButton mOverflowButton;
private MenuPopupHelper mOverflowPopup;
@@ -91,6 +91,7 @@
final int screen = res.getConfiguration().screenLayout;
mReserveOverflow = (screen & Configuration.SCREENLAYOUT_SIZE_MASK) ==
Configuration.SCREENLAYOUT_SIZE_XLARGE;
+ mWidthLimit = res.getDisplayMetrics().widthPixels / 2;
TypedArray a = context.obtainStyledAttributes(com.android.internal.R.styleable.Theme);
mDivider = a.getDrawable(com.android.internal.R.styleable.Theme_dividerVertical);
@@ -108,6 +109,7 @@
mReserveOverflow = (screen & Configuration.SCREENLAYOUT_SIZE_MASK) ==
Configuration.SCREENLAYOUT_SIZE_XLARGE;
mMaxItems = getMaxActionButtons();
+ mWidthLimit = getResources().getDisplayMetrics().widthPixels / 2;
if (mMenu != null) {
mMenu.setMaxActionItems(mMaxItems);
updateChildren(false);
@@ -172,6 +174,19 @@
}
public void initialize(MenuBuilder menu, int menuType) {
+ int width = mWidthLimit;
+ if (mReserveOverflow) {
+ if (mOverflowButton == null) {
+ OverflowMenuButton button = new OverflowMenuButton(mContext);
+ mOverflowButton = button;
+ }
+ final int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ mOverflowButton.measure(spec, spec);
+ width -= mOverflowButton.getMeasuredWidth();
+ }
+
+ menu.setActionWidthLimit(width);
+
menu.setMaxActionItems(mMaxItems);
mMenu = menu;
updateChildren(true);
@@ -219,9 +234,11 @@
if (itemCount > 0) {
addView(makeDividerView(), makeDividerLayoutParams());
}
- OverflowMenuButton button = new OverflowMenuButton(mContext);
- addView(button);
- mOverflowButton = button;
+ if (mOverflowButton == null) {
+ OverflowMenuButton button = new OverflowMenuButton(mContext);
+ mOverflowButton = button;
+ }
+ addView(mOverflowButton);
} else {
mOverflowButton = null;
}
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index 830c2c1..588b10c 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -27,9 +27,10 @@
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcelable;
-import android.util.Log;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import android.util.TypedValue;
+import android.view.ContextMenu.ContextMenuInfo;
import android.view.ContextThemeWrapper;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
@@ -38,8 +39,8 @@
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
+import android.view.View.MeasureSpec;
import android.view.ViewGroup;
-import android.view.ContextMenu.ContextMenuInfo;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
@@ -164,6 +165,10 @@
*/
private int mMaxActionItems;
/**
+ * The total width limit in pixels for all action items within a menu
+ */
+ private int mActionWidthLimit;
+ /**
* Whether or not the items (or any one item's action state) has changed since it was
* last fetched.
*/
@@ -208,6 +213,11 @@
private boolean mOptionalIconsVisible = false;
+ private ViewGroup mMeasureActionButtonParent;
+
+ // Group IDs that have been added as actions - used temporarily, allocated here for reuse.
+ private final SparseBooleanArray mActionButtonGroups = new SparseBooleanArray();
+
private static int getAlertDialogTheme(Context context) {
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(com.android.internal.R.attr.alertDialogTheme,
@@ -1035,6 +1045,44 @@
return mVisibleItems;
}
+ /**
+ * @return A fake action button parent view for obtaining child views.
+ */
+ private ViewGroup getMeasureActionButtonParent() {
+ if (mMeasureActionButtonParent == null) {
+ mMeasureActionButtonParent = (ViewGroup) mMenuTypes[TYPE_ACTION_BUTTON].getInflater()
+ .inflate(LAYOUT_RES_FOR_TYPE[TYPE_ACTION_BUTTON], null, false);
+ }
+ return mMeasureActionButtonParent;
+ }
+
+ /**
+ * This method determines which menu items get to be 'action items' that will appear
+ * in an action bar and which items should be 'overflow items' in a secondary menu.
+ * The rules are as follows:
+ *
+ * <p>Items are considered for inclusion in the order specified within the menu.
+ * There is a limit of mMaxActionItems as a total count, optionally including the overflow
+ * menu button itself. This is a soft limit; if an item shares a group ID with an item
+ * previously included as an action item, the new item will stay with its group and become
+ * an action item itself even if it breaks the max item count limit. This is done to
+ * limit the conceptual complexity of the items presented within an action bar. Only a few
+ * unrelated concepts should be presented to the user in this space, and groups are treated
+ * as a single concept.
+ *
+ * <p>There is also a hard limit of consumed measurable space: mActionWidthLimit. This
+ * limit may be broken by a single item that exceeds the remaining space, but no further
+ * items may be added. If an item that is part of a group cannot fit within the remaining
+ * measured width, the entire group will be demoted to overflow. This is done to ensure room
+ * for navigation and other affordances in the action bar as well as reduce general UI clutter.
+ *
+ * <p>The space freed by demoting a full group cannot be consumed by future menu items.
+ * Once items begin to overflow, all future items become overflow items as well. This is
+ * to avoid inadvertent reordering that may break the app's intended design.
+ *
+ * @param reserveActionOverflow true if an overflow button should consume one space
+ * in the available item count
+ */
private void flagActionItems(boolean reserveActionOverflow) {
if (reserveActionOverflow != mReserveActionOverflow) {
mReserveActionOverflow = reserveActionOverflow;
@@ -1048,9 +1096,13 @@
final ArrayList<MenuItemImpl> visibleItems = getVisibleItems();
final int itemsSize = visibleItems.size();
int maxActions = mMaxActionItems;
+ int widthLimit = mActionWidthLimit;
+ final int querySpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ final ViewGroup parent = getMeasureActionButtonParent();
int requiredItems = 0;
int requestedItems = 0;
+ int firstActionWidth = 0;
boolean hasOverflow = false;
for (int i = 0; i < itemsSize; i++) {
MenuItemImpl item = visibleItems.get(i);
@@ -1070,12 +1122,68 @@
}
maxActions -= requiredItems;
+ final SparseBooleanArray seenGroups = mActionButtonGroups;
+ seenGroups.clear();
+
// Flag as many more requested items as will fit.
for (int i = 0; i < itemsSize; i++) {
MenuItemImpl item = visibleItems.get(i);
- if (item.requestsActionButton()) {
- item.setIsActionButton(maxActions > 0);
+
+ if (item.requiresActionButton()) {
+ View v = item.getActionView();
+ if (v == null) {
+ v = item.getItemView(TYPE_ACTION_BUTTON, parent);
+ }
+ v.measure(querySpec, querySpec);
+ final int measuredWidth = v.getMeasuredWidth();
+ widthLimit -= measuredWidth;
+ if (firstActionWidth == 0) {
+ firstActionWidth = measuredWidth;
+ }
+ final int groupId = item.getGroupId();
+ if (groupId != 0) {
+ seenGroups.put(groupId, true);
+ }
+ } else if (item.requestsActionButton()) {
+ // Items in a group with other items that already have an action slot
+ // can break the max actions rule, but not the width limit.
+ final int groupId = item.getGroupId();
+ final boolean inGroup = seenGroups.get(groupId);
+ boolean isAction = (maxActions > 0 || inGroup) && widthLimit > 0;
maxActions--;
+
+ if (isAction) {
+ View v = item.getActionView();
+ if (v == null) {
+ v = item.getItemView(TYPE_ACTION_BUTTON, parent);
+ }
+ v.measure(querySpec, querySpec);
+ final int measuredWidth = v.getMeasuredWidth();
+ widthLimit -= measuredWidth;
+ if (firstActionWidth == 0) {
+ firstActionWidth = measuredWidth;
+ }
+
+ // Did this push the entire first item past halfway?
+ if (widthLimit + firstActionWidth <= 0) {
+ isAction = false;
+ }
+ }
+
+ if (isAction && groupId != 0) {
+ seenGroups.put(groupId, true);
+ } else if (inGroup) {
+ // We broke the width limit. Demote the whole group, they all overflow now.
+ seenGroups.put(groupId, false);
+ for (int j = 0; j < i; j++) {
+ MenuItemImpl areYouMyGroupie = visibleItems.get(j);
+ if (areYouMyGroupie.getGroupId() == groupId) {
+ areYouMyGroupie.setIsActionButton(false);
+ }
+ }
+ }
+
+ item.setIsActionButton(isAction);
}
}
@@ -1108,6 +1216,11 @@
mIsActionItemsStale = true;
}
+ void setActionWidthLimit(int widthLimit) {
+ mActionWidthLimit = widthLimit;
+ mIsActionItemsStale = true;
+ }
+
public void clearHeader() {
mHeaderIcon = null;
mHeaderTitle = null;
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index d28bdc9..f023e94 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -63,7 +63,6 @@
extern int register_android_graphics_Movie(JNIEnv* env);
extern int register_android_graphics_NinePatch(JNIEnv*);
extern int register_android_graphics_PathEffect(JNIEnv* env);
-extern int register_android_graphics_Region(JNIEnv* env);
extern int register_android_graphics_Shader(JNIEnv* env);
extern int register_android_graphics_Typeface(JNIEnv* env);
extern int register_android_graphics_YuvImage(JNIEnv* env);
@@ -111,6 +110,7 @@
extern int register_android_graphics_Picture(JNIEnv*);
extern int register_android_graphics_PorterDuff(JNIEnv* env);
extern int register_android_graphics_Rasterizer(JNIEnv* env);
+extern int register_android_graphics_Region(JNIEnv* env);
extern int register_android_graphics_SurfaceTexture(JNIEnv* env);
extern int register_android_graphics_Xfermode(JNIEnv* env);
extern int register_android_graphics_PixelFormat(JNIEnv* env);
diff --git a/core/jni/android/graphics/Region.cpp b/core/jni/android/graphics/Region.cpp
index 723cd37..c43b5ce 100644
--- a/core/jni/android/graphics/Region.cpp
+++ b/core/jni/android/graphics/Region.cpp
@@ -1,8 +1,30 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
#include "SkRegion.h"
#include "SkPath.h"
#include "GraphicsJNI.h"
+#include <binder/Parcel.h>
+#include "android_util_Binder.h"
+
#include <jni.h>
+#include <android_runtime/AndroidRuntime.h>
+
+namespace android {
static jfieldID gRegion_nativeInstanceFieldID;
@@ -134,9 +156,6 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#include <binder/Parcel.h>
-#include "android_util_Binder.h"
-
static SkRegion* Region_createFromParcel(JNIEnv* env, jobject clazz, jobject parcel)
{
if (parcel == NULL) {
@@ -215,8 +234,6 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////
-#include <android_runtime/AndroidRuntime.h>
-
static JNINativeMethod gRegionIterMethods[] = {
{ "nativeConstructor", "(I)I", (void*)RegionIter_constructor },
{ "nativeDestructor", "(I)V", (void*)RegionIter_destructor },
@@ -268,3 +285,9 @@
return android::AndroidRuntime::registerNativeMethods(env, "android/graphics/RegionIterator",
gRegionIterMethods, SK_ARRAY_COUNT(gRegionIterMethods));
}
+
+SkRegion* android_graphics_Region_getSkRegion(JNIEnv* env, jobject regionObj) {
+ return GetSkRegion(env, regionObj);
+}
+
+} // namespace android
diff --git a/core/jni/android/graphics/Region.h b/core/jni/android/graphics/Region.h
new file mode 100644
index 0000000..c15f06e
--- /dev/null
+++ b/core/jni/android/graphics/Region.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_GRAPHICS_REGION_H
+#define _ANDROID_GRAPHICS_REGION_H
+
+#include "jni.h"
+#include "SkRegion.h"
+
+namespace android {
+
+/* Gets the underlying SkRegion from a Region object. */
+extern SkRegion* android_graphics_Region_getSkRegion(JNIEnv* env, jobject regionObj);
+
+} // namespace android
+
+#endif // _ANDROID_GRAPHICS_REGION_H
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index c1229f3..88de94f 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -25,8 +25,8 @@
#include <utils/Log.h>
#include <utils/misc.h>
-#include "android/graphics/GraphicsJNI.h"
#include "jni.h"
+#include "JNIHelp.h"
// ----------------------------------------------------------------------------
@@ -35,57 +35,127 @@
static const char* const OutOfResourcesException =
"android/graphics/SurfaceTexture$OutOfResourcesException";
-struct st_t {
- jfieldID surfaceTexture;
+struct fields_t {
+ jfieldID surfaceTexture;
+ jmethodID postEvent;
};
-static st_t st;
+static fields_t fields;
// ----------------------------------------------------------------------------
-static void setSurfaceTexture(JNIEnv* env, jobject clazz,
+static void SurfaceTexture_setSurfaceTexture(JNIEnv* env, jobject thiz,
const sp<SurfaceTexture>& surfaceTexture)
{
SurfaceTexture* const p =
- (SurfaceTexture*)env->GetIntField(clazz, st.surfaceTexture);
+ (SurfaceTexture*)env->GetIntField(thiz, fields.surfaceTexture);
if (surfaceTexture.get()) {
- surfaceTexture->incStrong(clazz);
+ surfaceTexture->incStrong(thiz);
}
if (p) {
- p->decStrong(clazz);
+ p->decStrong(thiz);
}
- env->SetIntField(clazz, st.surfaceTexture, (int)surfaceTexture.get());
+ env->SetIntField(thiz, fields.surfaceTexture, (int)surfaceTexture.get());
}
-sp<SurfaceTexture> getSurfaceTexture(JNIEnv* env, jobject clazz)
+sp<SurfaceTexture> SurfaceTexture_getSurfaceTexture(JNIEnv* env, jobject thiz)
{
sp<SurfaceTexture> surfaceTexture(
- (SurfaceTexture*)env->GetIntField(clazz, st.surfaceTexture));
+ (SurfaceTexture*)env->GetIntField(thiz, fields.surfaceTexture));
return surfaceTexture;
}
// ----------------------------------------------------------------------------
-static void SurfaceTexture_init(JNIEnv* env, jobject clazz, jint texName)
+class JNISurfaceTextureContext : public SurfaceTexture::FrameAvailableListener
{
- sp<SurfaceTexture> surfaceTexture(new SurfaceTexture(texName));
+public:
+ JNISurfaceTextureContext(JNIEnv* env, jobject weakThiz, jclass clazz);
+ virtual ~JNISurfaceTextureContext();
+ virtual void onFrameAvailable();
- if (surfaceTexture == 0) {
- doThrow(env, OutOfResourcesException);
- return;
- }
- setSurfaceTexture(env, clazz, surfaceTexture);
+private:
+ jobject mWeakThiz;
+ jclass mClazz;
+};
+
+JNISurfaceTextureContext::JNISurfaceTextureContext(JNIEnv* env,
+ jobject weakThiz, jclass clazz) :
+ mWeakThiz(env->NewGlobalRef(weakThiz)),
+ mClazz((jclass)env->NewGlobalRef(clazz))
+{}
+
+JNISurfaceTextureContext::~JNISurfaceTextureContext()
+{
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ env->DeleteGlobalRef(mWeakThiz);
+ env->DeleteGlobalRef(mClazz);
}
-static void SurfaceTexture_updateTexImage(JNIEnv* env, jobject clazz)
+void JNISurfaceTextureContext::onFrameAvailable()
{
- sp<SurfaceTexture> surfaceTexture(getSurfaceTexture(env, clazz));
+ JNIEnv *env = AndroidRuntime::getJNIEnv();
+ env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz);
+}
+
+// ----------------------------------------------------------------------------
+
+static void SurfaceTexture_classInit(JNIEnv* env, jclass clazz)
+{
+ fields.surfaceTexture = env->GetFieldID(clazz,
+ ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "I");
+ if (fields.surfaceTexture == NULL) {
+ LOGE("can't find android/graphics/SurfaceTexture.%s",
+ ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID);
+ }
+
+ fields.postEvent = env->GetStaticMethodID(clazz, "postEventFromNative",
+ "(Ljava/lang/Object;)V");
+ if (fields.postEvent == NULL) {
+ LOGE("can't find android/graphics/SurfaceTexture.postEventFromNative");
+ }
+
+}
+
+static void SurfaceTexture_init(JNIEnv* env, jobject thiz, jint texName,
+ jobject weakThiz)
+{
+ sp<SurfaceTexture> surfaceTexture(new SurfaceTexture(texName));
+ if (surfaceTexture == 0) {
+ jniThrowException(env, OutOfResourcesException,
+ "Unable to create native SurfaceTexture");
+ return;
+ }
+ SurfaceTexture_setSurfaceTexture(env, thiz, surfaceTexture);
+
+ jclass clazz = env->GetObjectClass(thiz);
+ if (clazz == NULL) {
+ jniThrowRuntimeException(env,
+ "Can't find android/graphics/SurfaceTexture");
+ return;
+ }
+
+ sp<JNISurfaceTextureContext> ctx(new JNISurfaceTextureContext(env, weakThiz,
+ clazz));
+ surfaceTexture->setFrameAvailableListener(ctx);
+}
+
+static void SurfaceTexture_finalize(JNIEnv* env, jobject thiz)
+{
+ sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
+ surfaceTexture->setFrameAvailableListener(0);
+ SurfaceTexture_setSurfaceTexture(env, thiz, 0);
+}
+
+static void SurfaceTexture_updateTexImage(JNIEnv* env, jobject thiz)
+{
+ sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
surfaceTexture->updateTexImage();
}
-static void SurfaceTexture_getTransformMatrix(JNIEnv* env, jobject clazz,
+static void SurfaceTexture_getTransformMatrix(JNIEnv* env, jobject thiz,
jfloatArray jmtx)
{
- sp<SurfaceTexture> surfaceTexture(getSurfaceTexture(env, clazz));
+ sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, thiz));
float* mtx = env->GetFloatArrayElements(jmtx, NULL);
surfaceTexture->getTransformMatrix(mtx);
env->ReleaseFloatArrayElements(jmtx, mtx, 0);
@@ -94,21 +164,15 @@
// ----------------------------------------------------------------------------
const char* const kSurfaceTextureClassPathName = "android/graphics/SurfaceTexture";
-static void nativeClassInit(JNIEnv* env, jclass clazz);
static JNINativeMethod gSurfaceTextureMethods[] = {
- {"nativeClassInit", "()V", (void*)nativeClassInit },
- {"init", "(I)V", (void*)SurfaceTexture_init },
- {"updateTexImage", "()V", (void*)SurfaceTexture_updateTexImage },
- {"getTransformMatrixImpl", "([F)V", (void*)SurfaceTexture_getTransformMatrix },
+ {"nativeClassInit", "()V", (void*)SurfaceTexture_classInit },
+ {"nativeInit", "(ILjava/lang/Object;)V", (void*)SurfaceTexture_init },
+ {"nativeFinalize", "()V", (void*)SurfaceTexture_finalize },
+ {"nativeUpdateTexImage", "()V", (void*)SurfaceTexture_updateTexImage },
+ {"nativeGetTransformMatrix", "([F)V", (void*)SurfaceTexture_getTransformMatrix },
};
-static void nativeClassInit(JNIEnv* env, jclass clazz)
-{
- st.surfaceTexture = env->GetFieldID(clazz,
- ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "I");
-}
-
int register_android_graphics_SurfaceTexture(JNIEnv* env)
{
int err = 0;
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index b033878..0430a81 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -500,8 +500,9 @@
void* dlhandle;
ANativeActivity_createFunc* createActivityFunc;
- String8 internalDataPath;
- String8 externalDataPath;
+ String8 internalDataPathObj;
+ String8 externalDataPathObj;
+ String8 obbPathObj;
sp<ANativeWindow> nativeWindow;
int32_t lastWindowWidth;
@@ -641,8 +642,8 @@
static jint
loadNativeCode_native(JNIEnv* env, jobject clazz, jstring path, jstring funcName,
- jobject messageQueue,
- jstring internalDataDir, jstring externalDataDir, int sdkVersion,
+ jobject messageQueue, jstring internalDataDir, jstring obbDir,
+ jstring externalDataDir, int sdkVersion,
jobject jAssetMgr, jbyteArray savedState)
{
LOG_TRACE("loadNativeCode_native");
@@ -699,19 +700,24 @@
code->clazz = env->NewGlobalRef(clazz);
const char* dirStr = env->GetStringUTFChars(internalDataDir, NULL);
- code->internalDataPath = dirStr;
- code->internalDataPath = code->internalDataPath.string();
- env->ReleaseStringUTFChars(path, dirStr);
+ code->internalDataPathObj = dirStr;
+ code->internalDataPath = code->internalDataPathObj.string();
+ env->ReleaseStringUTFChars(internalDataDir, dirStr);
dirStr = env->GetStringUTFChars(externalDataDir, NULL);
- code->externalDataPath = dirStr;
- code->externalDataPath = code->externalDataPath.string();
- env->ReleaseStringUTFChars(path, dirStr);
+ code->externalDataPathObj = dirStr;
+ code->externalDataPath = code->externalDataPathObj.string();
+ env->ReleaseStringUTFChars(externalDataDir, dirStr);
code->sdkVersion = sdkVersion;
code->assetManager = assetManagerForJavaObject(env, jAssetMgr);
+ dirStr = env->GetStringUTFChars(obbDir, NULL);
+ code->obbPathObj = dirStr;
+ code->obbPath = code->obbPathObj.string();
+ env->ReleaseStringUTFChars(obbDir, dirStr);
+
jbyte* rawSavedState = NULL;
jsize rawSavedSize = 0;
if (savedState != NULL) {
@@ -1022,7 +1028,7 @@
}
static const JNINativeMethod g_methods[] = {
- { "loadNativeCode", "(Ljava/lang/String;Ljava/lang/String;Landroid/os/MessageQueue;Ljava/lang/String;Ljava/lang/String;ILandroid/content/res/AssetManager;[B)I",
+ { "loadNativeCode", "(Ljava/lang/String;Ljava/lang/String;Landroid/os/MessageQueue;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILandroid/content/res/AssetManager;[B)I",
(void*)loadNativeCode_native },
{ "unloadNativeCode", "(I)V", (void*)unloadNativeCode_native },
{ "onStartNative", "(I)V", (void*)onStart_native },
diff --git a/core/res/res/layout/dialog_custom_title_holo.xml b/core/res/res/layout/dialog_custom_title_holo.xml
index 854873f..74b6070 100644
--- a/core/res/res/layout/dialog_custom_title_holo.xml
+++ b/core/res/res/layout/dialog_custom_title_holo.xml
@@ -23,10 +23,19 @@
android:fitsSystemWindows="true">
<FrameLayout android:id="@android:id/title_container"
android:layout_width="match_parent"
- android:layout_height="24dip"
+ android:layout_height="60dip"
android:layout_weight="0"
+ android:gravity="center_vertical|left"
style="?android:attr/windowTitleBackgroundStyle">
</FrameLayout>
+ <ImageView android:id="@+id/titleDivider"
+ android:layout_width="match_parent"
+ android:layout_height="4dip"
+ android:scaleType="fitXY"
+ android:gravity="fill_horizontal"
+ android:paddingLeft="16dip"
+ android:paddingRight="16dip"
+ android:src="@android:drawable/divider_strong_holo" />
<FrameLayout
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_weight="1"
@@ -34,10 +43,6 @@
android:foreground="?android:attr/windowContentOverlay">
<FrameLayout android:id="@android:id/content"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingTop="6dip"
- android:paddingBottom="10dip"
- android:paddingLeft="10dip"
- android:paddingRight="10dip" />
+ android:layout_height="match_parent" />
</FrameLayout>
</LinearLayout>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 1183915..c4e815e 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -2057,7 +2057,7 @@
<!-- Window title -->
<style name="WindowTitleBackground.Holo">
- <item name="android:background">@android:drawable/title_bar</item>
+ <item name="android:background">@null</item>
</style>
<style name="WindowTitle.Holo">
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index 3eb0b03..64c209a 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -16,6 +16,11 @@
package android.graphics;
+import java.lang.ref.WeakReference;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
/**
* Captures frames from an image stream as an OpenGL ES texture.
*
@@ -32,6 +37,9 @@
*/
public class SurfaceTexture {
+ private EventHandler mEventHandler;
+ private OnFrameAvailableListener mOnFrameAvailableListener;
+
@SuppressWarnings("unused")
private int mSurfaceTexture;
@@ -59,7 +67,15 @@
* @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
*/
public SurfaceTexture(int texName) {
- init(texName);
+ Looper looper;
+ if ((looper = Looper.myLooper()) != null) {
+ mEventHandler = new EventHandler(looper);
+ } else if ((looper = Looper.getMainLooper()) != null) {
+ mEventHandler = new EventHandler(looper);
+ } else {
+ mEventHandler = null;
+ }
+ nativeInit(texName, new WeakReference<SurfaceTexture>(this));
}
/**
@@ -69,7 +85,7 @@
* thread invoking the callback.
*/
public void setOnFrameAvailableListener(OnFrameAvailableListener l) {
- // TODO: Implement this!
+ mOnFrameAvailableListener = l;
}
/**
@@ -77,8 +93,9 @@
* called while the OpenGL ES context that owns the texture is bound to the thread. It will
* implicitly bind its texture to the GL_TEXTURE_EXTERNAL_OES texture target.
*/
- public native void updateTexImage();
-
+ public void updateTexImage() {
+ nativeUpdateTexImage();
+ }
/**
* Retrieve the 4x4 texture coordinate transform matrix associated with the texture image set by
@@ -99,12 +116,48 @@
if (mtx.length != 16) {
throw new IllegalArgumentException();
}
- getTransformMatrixImpl(mtx);
+ nativeGetTransformMatrix(mtx);
}
- private native void getTransformMatrixImpl(float[] mtx);
+ protected void finalize() throws Throwable {
+ try {
+ nativeFinalize();
+ } finally {
+ super.finalize();
+ }
+ }
- private native void init(int texName);
+ private class EventHandler extends Handler {
+ public EventHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (mOnFrameAvailableListener != null) {
+ mOnFrameAvailableListener.onFrameAvailable(SurfaceTexture.this);
+ }
+ return;
+ }
+ }
+
+ private static void postEventFromNative(Object selfRef) {
+ WeakReference weakSelf = (WeakReference)selfRef;
+ SurfaceTexture st = (SurfaceTexture)weakSelf.get();
+ if (st == null) {
+ return;
+ }
+
+ if (st.mEventHandler != null) {
+ Message m = st.mEventHandler.obtainMessage();
+ st.mEventHandler.sendMessage(m);
+ }
+ }
+
+ private native void nativeInit(int texName, Object weakSelf);
+ private native void nativeFinalize();
+ private native void nativeGetTransformMatrix(float[] mtx);
+ private native void nativeUpdateTexImage();
/*
* We use a class initializer to allow the native code to cache some
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 002e48b..79c33f5 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -40,6 +40,10 @@
enum { MIN_BUFFER_SLOTS = 3 };
enum { NUM_BUFFER_SLOTS = 32 };
+ struct FrameAvailableListener : public virtual RefBase {
+ virtual void onFrameAvailable() = 0;
+ };
+
// tex indicates the name OpenGL texture to which images are to be streamed.
// This texture name cannot be changed once the SurfaceTexture is created.
SurfaceTexture(GLuint tex);
@@ -93,6 +97,10 @@
// functions.
void getTransformMatrix(float mtx[16]);
+ // setFrameAvailableListener sets the listener object that will be notified
+ // when a new frame becomes available.
+ void setFrameAvailableListener(const sp<FrameAvailableListener>& l);
+
private:
// freeAllBuffers frees the resources (both GraphicBuffer and EGLImage) for
@@ -195,6 +203,11 @@
// to a buffer, but other processes do.
Vector<sp<GraphicBuffer> > mAllocdBuffers;
+ // mFrameAvailableListener is the listener object that will be called when a
+ // new frame becomes available. If it is not NULL it will be called from
+ // queueBuffer.
+ sp<FrameAvailableListener> mFrameAvailableListener;
+
// mMutex is the mutex used to prevent concurrent access to the member
// variables of SurfaceTexture objects. It must be locked whenever the
// member variables are accessed.
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index 447de76..1dadd53 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -166,6 +166,9 @@
mLastQueued = buf;
mLastQueuedCrop = mNextCrop;
mLastQueuedTransform = mNextTransform;
+ if (mFrameAvailableListener != 0) {
+ mFrameAvailableListener->onFrameAvailable();
+ }
return OK;
}
@@ -237,43 +240,68 @@
LOGV("SurfaceTexture::updateTexImage");
Mutex::Autolock lock(mMutex);
- float* xform = mtxIdentity;
- switch (mCurrentTransform) {
- case 0:
- xform = mtxIdentity;
- break;
- case NATIVE_WINDOW_TRANSFORM_FLIP_H:
- xform = mtxFlipH;
- break;
- case NATIVE_WINDOW_TRANSFORM_FLIP_V:
- xform = mtxFlipV;
- break;
- case NATIVE_WINDOW_TRANSFORM_ROT_90:
- xform = mtxRot90;
- break;
- case NATIVE_WINDOW_TRANSFORM_ROT_180:
- xform = mtxRot180;
- break;
- case NATIVE_WINDOW_TRANSFORM_ROT_270:
- xform = mtxRot270;
- break;
- default:
- LOGE("getTransformMatrix: unknown transform: %d", mCurrentTransform);
+ float xform[16];
+ for (int i = 0; i < 16; i++) {
+ xform[i] = mtxIdentity[i];
+ }
+ if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_H) {
+ float result[16];
+ mtxMul(result, xform, mtxFlipH);
+ for (int i = 0; i < 16; i++) {
+ xform[i] = result[i];
+ }
+ }
+ if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_FLIP_V) {
+ float result[16];
+ mtxMul(result, xform, mtxFlipV);
+ for (int i = 0; i < 16; i++) {
+ xform[i] = result[i];
+ }
+ }
+ if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+ float result[16];
+ mtxMul(result, xform, mtxRot90);
+ for (int i = 0; i < 16; i++) {
+ xform[i] = result[i];
+ }
}
sp<GraphicBuffer>& buf(mSlots[mCurrentTexture].mGraphicBuffer);
- float tx = float(mCurrentCrop.left) / float(buf->getWidth());
- float ty = float(mCurrentCrop.bottom) / float(buf->getHeight());
- float sx = float(mCurrentCrop.width()) / float(buf->getWidth());
- float sy = float(mCurrentCrop.height()) / float(buf->getHeight());
+ float tx, ty, sx, sy;
+ if (!mCurrentCrop.isEmpty()) {
+ tx = float(mCurrentCrop.left) / float(buf->getWidth());
+ ty = float(buf->getHeight() - mCurrentCrop.bottom) /
+ float(buf->getHeight());
+ sx = float(mCurrentCrop.width()) / float(buf->getWidth());
+ sy = float(mCurrentCrop.height()) / float(buf->getHeight());
+ } else {
+ tx = 0.0f;
+ ty = 0.0f;
+ sx = 1.0f;
+ sy = 1.0f;
+ }
float crop[16] = {
- sx, 0, 0, sx*tx,
- 0, sy, 0, sy*ty,
+ sx, 0, 0, 0,
+ 0, sy, 0, 0,
0, 0, 1, 0,
- 0, 0, 0, 1,
+ sx*tx, sy*ty, 0, 1,
};
- mtxMul(mtx, crop, xform);
+ float mtxBeforeFlipV[16];
+ mtxMul(mtxBeforeFlipV, crop, xform);
+
+ // SurfaceFlinger expects the top of its window textures to be at a Y
+ // coordinate of 0, so SurfaceTexture must behave the same way. We don't
+ // want to expose this to applications, however, so we must add an
+ // additional vertical flip to the transform after all the other transforms.
+ mtxMul(mtx, mtxFlipV, mtxBeforeFlipV);
+}
+
+void SurfaceTexture::setFrameAvailableListener(
+ const sp<FrameAvailableListener>& l) {
+ LOGV("SurfaceTexture::setFrameAvailableListener");
+ Mutex::Autolock lock(mMutex);
+ mFrameAvailableListener = l;
}
void SurfaceTexture::freeAllBuffers() {
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index 6e4c22e..41c9fe2 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -212,6 +212,7 @@
GLenum type = mType->getElement()->getComponent().getGLType();
GLenum format = mType->getElement()->getComponent().getGLFormat();
GLenum target = (GLenum)getGLTarget();
+ rsAssert(mTextureID);
glBindTexture(target, mTextureID);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
GLenum t = GL_TEXTURE_2D;
diff --git a/libs/rs/rsThreadIO.cpp b/libs/rs/rsThreadIO.cpp
index 1c6c5ac..001ac55 100644
--- a/libs/rs/rsThreadIO.cpp
+++ b/libs/rs/rsThreadIO.cpp
@@ -53,6 +53,10 @@
waitForCommand = false;
//LOGV("playCoreCommands 3 %i %i", cmdID, cmdSize);
+ if (cmdID >= (sizeof(gPlaybackFuncs) / sizeof(void *))) {
+ rsAssert(cmdID < (sizeof(gPlaybackFuncs) / sizeof(void *)));
+ LOGE("playCoreCommands error con %p, cmd %i", con, cmdID);
+ }
gPlaybackFuncs[cmdID](con, data);
mToCore.next();
}
diff --git a/libs/rs/rsg_generator.c b/libs/rs/rsg_generator.c
index 1e468bb..4ac5b7f 100644
--- a/libs/rs/rsg_generator.c
+++ b/libs/rs/rsg_generator.c
@@ -219,7 +219,7 @@
fprintf(f, "};\n\n");
}
- fprintf(f, "RsPlaybackFunc gPlaybackFuncs[] = {\n");
+ fprintf(f, "RsPlaybackFunc gPlaybackFuncs[%i] = {\n", apiCount + 1);
fprintf(f, " NULL,\n");
for (ct=0; ct < apiCount; ct++) {
fprintf(f, " %s%s,\n", "rsp_", apis[ct].name);
@@ -265,7 +265,7 @@
printFuncDecls(f, "rsi_", 1);
printPlaybackFuncs(f, "rsp_");
fprintf(f, "\n\ntypedef void (*RsPlaybackFunc)(Context *, const void *);\n");
- fprintf(f, "extern RsPlaybackFunc gPlaybackFuncs[];\n");
+ fprintf(f, "extern RsPlaybackFunc gPlaybackFuncs[%i];\n", apiCount + 1);
fprintf(f, "}\n");
fprintf(f, "}\n");
diff --git a/native/android/looper.cpp b/native/android/looper.cpp
index 9f5cda9..615493f 100644
--- a/native/android/looper.cpp
+++ b/native/android/looper.cpp
@@ -19,9 +19,11 @@
#include <android/looper.h>
#include <utils/Looper.h>
+#include <binder/IPCThreadState.h>
using android::Looper;
using android::sp;
+using android::IPCThreadState;
ALooper* ALooper_forThread() {
return Looper::getForThread().get();
@@ -46,6 +48,7 @@
return ALOOPER_POLL_ERROR;
}
+ IPCThreadState::self()->flushCommands();
return looper->pollOnce(timeoutMillis, outFd, outEvents, outData);
}
@@ -55,7 +58,8 @@
LOGE("ALooper_pollAll: No looper for this thread!");
return ALOOPER_POLL_ERROR;
}
-
+
+ IPCThreadState::self()->flushCommands();
return looper->pollAll(timeoutMillis, outFd, outEvents, outData);
}
diff --git a/native/include/android/native_activity.h b/native/include/android/native_activity.h
index d89bc8b..a361846 100644
--- a/native/include/android/native_activity.h
+++ b/native/include/android/native_activity.h
@@ -91,6 +91,13 @@
* uses this to access binary assets bundled inside its own .apk file.
*/
AAssetManager* assetManager;
+
+ /**
+ * Available starting with Honeycomb: path to the directory containing
+ * the application's OBB files (if any). If the app doesn't have any
+ * OBB files, this directory may not exist.
+ */
+ const char* obbPath;
} ANativeActivity;
/**
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 386cc5d..ed36171 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -62,6 +62,8 @@
"EGL_KHR_image_base "
"EGL_KHR_image_pixmap "
"EGL_KHR_gl_texture_2D_image "
+ "EGL_KHR_gl_texture_cubemap_image "
+ "EGL_KHR_gl_renderbuffer_image "
"EGL_KHR_fence_sync "
"EGL_ANDROID_image_native_buffer "
"EGL_ANDROID_swap_rectangle "
@@ -1471,6 +1473,29 @@
return result;
}
+// Note: Similar implementations of these functions also exist in
+// gl2.cpp and gl.cpp, and are used by applications that call the
+// exported entry points directly.
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image);
+typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image);
+
+static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES_impl = NULL;
+static PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES_impl = NULL;
+
+static void glEGLImageTargetTexture2DOES_wrapper(GLenum target, GLeglImageOES image)
+{
+ GLeglImageOES implImage =
+ (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
+ glEGLImageTargetTexture2DOES_impl(target, implImage);
+}
+
+static void glEGLImageTargetRenderbufferStorageOES_wrapper(GLenum target, GLeglImageOES image)
+{
+ GLeglImageOES implImage =
+ (GLeglImageOES)egl_get_image_for_current_context((EGLImageKHR)image);
+ glEGLImageTargetRenderbufferStorageOES_impl(target, implImage);
+}
+
__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
{
// eglGetProcAddress() could be the very first function called
@@ -1531,6 +1556,16 @@
}
if (found) {
addr = gExtensionForwarders[slot];
+
+ if (!strcmp(procname, "glEGLImageTargetTexture2DOES")) {
+ glEGLImageTargetTexture2DOES_impl = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)addr;
+ addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetTexture2DOES_wrapper;
+ }
+ if (!strcmp(procname, "glEGLImageTargetRenderbufferStorageOES")) {
+ glEGLImageTargetRenderbufferStorageOES_impl = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)addr;
+ addr = (__eglMustCastToProperFunctionPointerType)glEGLImageTargetRenderbufferStorageOES_wrapper;
+ }
+
gGLExtentionMap.add(name, addr);
gGLExtentionSlot++;
}
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 0c85af8..2ec2226 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -165,8 +165,13 @@
}
@Override
- public long calculateDirectorySize(String directory) throws RemoteException {
- return MeasurementUtils.measureDirectory(directory);
+ public long calculateDirectorySize(String path) throws RemoteException {
+ final File directory = new File(path);
+ if (directory.exists() && directory.isDirectory()) {
+ return MeasurementUtils.measureDirectory(path);
+ } else {
+ return 0L;
+ }
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 73b6723..dfe0262 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -668,7 +668,8 @@
if ((mPhoneState == TelephonyManager.CALL_STATE_IDLE) && isEvdo()){
iconLevel = getEvdoLevel();
if (false) {
- Slog.d(TAG, "use Evdo level=" + iconLevel + " to replace Cdma Level=" + getCdmaLevel());
+ Slog.d(TAG, "use Evdo level=" + iconLevel + " to replace Cdma Level="
+ + getCdmaLevel());
}
} else {
iconLevel = getCdmaLevel();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
index 1b2fcad..0d2538d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AirplaneModeController.java
@@ -55,7 +55,6 @@
}
public void onCheckedChanged(CompoundButton view, boolean checked) {
- Slog.d(TAG, "onCheckedChanged checked=" + checked + " mAirplaneMode=" + mAirplaneMode);
if (checked != mAirplaneMode) {
mAirplaneMode = checked;
unsafe(checked);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 3a7bd90..e80e37d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -47,7 +47,6 @@
int mRepeat;
Runnable mCheckLongPress = new Runnable() {
public void run() {
- Slog.d("KeyButtonView", "longpress");
if (isPressed()) {
mLongPressed = true;
mRepeat++;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java
index 5616159..90c9568 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/HeightReceiver.java
@@ -73,12 +73,10 @@
private void setPlugged(boolean plugged) {
final Resources res = mContext.getResources();
- Slog.d(TAG, "plugged=" + plugged);
int height = -1;
if (plugged) {
final DisplayMetrics metrics = new DisplayMetrics();
mWindowManager.getDefaultDisplay().getMetrics(metrics);
- Slog.d(TAG, "metrics=" + metrics);
height = metrics.heightPixels - 720;
}
@@ -87,7 +85,8 @@
if (height < minHeight) {
height = minHeight;
}
- Slog.d(TAG, "using height=" + height + " old=" + mHeight);
+ Slog.i(TAG, "Resizing status bar plugged=" + plugged + " height="
+ + height + " old=" + mHeight);
mHeight = height;
final int N = mListeners.size();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
index d4ba693..add67b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
@@ -242,6 +242,7 @@
// Turn on the selected radio button at startup
private void updateRadioButtonsByImiAndSubtype(
InputMethodInfo imi, InputMethodSubtype subtype) {
+ if (imi == null) return;
if (DEBUG) {
Log.d(TAG, "Update radio buttons by " + imi.getId() + ", " + subtype);
}
@@ -253,7 +254,7 @@
return;
}
Pair<InputMethodInfo, InputMethodSubtype> imiAndSubtype =
- mRadioViewAndImiMap.get(radioView);
+ mRadioViewAndImiMap.get(radioView);
if (imiAndSubtype.first.getId().equals(imi.getId())
&& (imiAndSubtype.second == null || imiAndSubtype.second.equals(subtype))) {
subtypeRadioButton.setChecked(true);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
index a2f6e3a..45a22b6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -269,7 +269,8 @@
// fully closed, no animation necessary
} else if (mVisible) {
if (DEBUG) {
- Slog.d(TAG, "panelHeight not zero but trying to open; scheduling an anim to open fully");
+ Slog.d(TAG, "panelHeight not zero but trying to open; scheduling an anim"
+ + " to open fully");
}
startAnimation(true);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
index 07af466..9ca83e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/SettingsView.java
@@ -95,7 +95,6 @@
// Network
// ----------------------------
private void onClickNetwork() {
- Slog.d(TAG, "onClickNetwork");
getContext().startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
getStatusBarManager().collapse();
@@ -104,7 +103,6 @@
// Settings
// ----------------------------
private void onClickSettings() {
- Slog.d(TAG, "onClickSettings");
getContext().startActivity(new Intent(Settings.ACTION_SETTINGS)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
getStatusBarManager().collapse();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
index 2ebd067..e864577 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/ShirtPocket.java
@@ -143,7 +143,6 @@
hideWindow();
return true;
} else if (action == MotionEvent.ACTION_DOWN) {
- Slog.d(TAG, "ACTION_DOWN");
final ClipData clip = mClipping;
if (clip != null) {
final Bitmap icon = clip.getIcon();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index d8e3053..825877a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -596,7 +596,7 @@
// TODO: immersive mode popups for tablet
} else if (notification.notification.fullScreenIntent != null) {
// not immersive & a full-screen alert should be shown
- Slog.d(TAG, "Notification has fullScreenIntent and activity is not immersive;"
+ Slog.w(TAG, "Notification has fullScreenIntent and activity is not immersive;"
+ " sending fullScreenIntent");
try {
notification.notification.fullScreenIntent.send();
@@ -732,28 +732,28 @@
// act accordingly
if ((diff & StatusBarManager.DISABLE_CLOCK) != 0) {
boolean show = (state & StatusBarManager.DISABLE_CLOCK) == 0;
- Slog.d(TAG, "DISABLE_CLOCK: " + (show ? "no" : "yes"));
+ Slog.i(TAG, "DISABLE_CLOCK: " + (show ? "no" : "yes"));
showClock(show);
}
if ((diff & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) {
boolean show = (state & StatusBarManager.DISABLE_SYSTEM_INFO) == 0;
- Slog.d(TAG, "DISABLE_SYSTEM_INFO: " + (show ? "no" : "yes"));
+ Slog.i(TAG, "DISABLE_SYSTEM_INFO: " + (show ? "no" : "yes"));
mNotificationTrigger.setVisibility(show ? View.VISIBLE : View.GONE);
}
if ((diff & StatusBarManager.DISABLE_EXPAND) != 0) {
if ((state & StatusBarManager.DISABLE_EXPAND) != 0) {
- Slog.d(TAG, "DISABLE_EXPAND: yes");
+ Slog.i(TAG, "DISABLE_EXPAND: yes");
animateCollapse();
}
}
if ((diff & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
if ((state & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) {
- Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
+ Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: yes");
// synchronize with current shadow state
mNotificationIconArea.setVisibility(View.GONE);
mTicker.halt();
} else {
- Slog.d(TAG, "DISABLE_NOTIFICATION_ICONS: no");
+ Slog.i(TAG, "DISABLE_NOTIFICATION_ICONS: no");
// synchronize with current shadow state
mNotificationIconArea.setVisibility(View.VISIBLE);
}
@@ -764,11 +764,11 @@
}
if ((diff & StatusBarManager.DISABLE_NAVIGATION) != 0) {
if ((state & StatusBarManager.DISABLE_NAVIGATION) != 0) {
- Slog.d(TAG, "DISABLE_NAVIGATION: yes");
+ Slog.i(TAG, "DISABLE_NAVIGATION: yes");
mNavigationArea.setVisibility(View.GONE);
mInputMethodSwitchButton.setScreenLocked(true);
} else {
- Slog.d(TAG, "DISABLE_NAVIGATION: no");
+ Slog.i(TAG, "DISABLE_NAVIGATION: no");
mNavigationArea.setVisibility(View.VISIBLE);
mInputMethodSwitchButton.setScreenLocked(false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
index 4ee985d..98f718b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
@@ -65,7 +65,9 @@
}
}
}
- Slog.d(TabletStatusBar.TAG, "TabletStatusBarView not intercepting event");
+ if (TabletStatusBar.DEBUG) {
+ Slog.d(TabletStatusBar.TAG, "TabletStatusBarView not intercepting event");
+ }
return super.onInterceptTouchEvent(ev);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
index fa732c3..440d680 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletTicker.java
@@ -111,7 +111,6 @@
public void remove(IBinder key, boolean advance) {
if (mCurrentKey == key) {
- Slog.d(TAG, "removed current");
// Showing now
if (advance) {
removeMessages(MSG_ADVANCE);
@@ -121,7 +120,6 @@
// In the queue
for (int i=0; i<QUEUE_LENGTH; i++) {
if (mKeys[i] == key) {
- Slog.d(TAG, "removed from queue: " + i);
for (; i<QUEUE_LENGTH-1; i++) {
mKeys[i] = mKeys[i+1];
mQueue[i] = mQueue[i+1];
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 79fbe0e..1b810d5 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -311,8 +311,8 @@
setFocusableInTouchMode(true);
setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
- updateMonitor.registerInfoCallback(this);
- updateMonitor.registerSimStateCallback(this);
+ mUpdateMonitor.registerInfoCallback(this);
+ mUpdateMonitor.registerSimStateCallback(this);
mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
mSilentMode = isSilentMode();
@@ -414,6 +414,9 @@
public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn,
int batteryLevel) {
if (DBG) Log.d(TAG, "onRefreshBatteryInfo(" + showBatteryInfo + ", " + pluggedIn + ")");
+
+ mStatusView.onRefreshBatteryInfo(showBatteryInfo, pluggedIn, batteryLevel);
+
mShowingBatteryInfo = showBatteryInfo;
mPluggedIn = pluggedIn;
mBatteryLevel = batteryLevel;
diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
index b789288..eb4d930 100644
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -135,9 +135,12 @@
// numeric keys.
if (mIsAlpha) {
mPasswordEntry.setKeyListener(TextKeyListener.getInstance());
+ mStatusView.setHelpMessage(R.string.keyguard_password_enter_password_code,
+ StatusView.LOCK_ICON);
} else {
mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance());
- mStatusView.setInstructionText(R.string.keyguard_password_enter_pin_password_code);
+ mStatusView.setHelpMessage(R.string.keyguard_password_enter_pin_code,
+ StatusView.LOCK_ICON);
}
mKeyboardHelper.setVibratePattern(mLockPatternUtils.isTactileFeedbackEnabled() ?
@@ -151,6 +154,11 @@
mStatusView.setCarrierText(LockScreen.getCarrierString(
mUpdateMonitor.getTelephonyPlmn(),
mUpdateMonitor.getTelephonySpn()));
+
+ mUpdateMonitor.registerInfoCallback(this);
+ //mUpdateMonitor.registerSimStateCallback(this);
+
+ resetStatusInfo();
}
@Override
@@ -204,6 +212,7 @@
if (mLockPatternUtils.checkPassword(entry)) {
mCallback.keyguardDone(true);
mCallback.reportSuccessfulUnlockAttempt();
+ mStatusView.setInstructionText(null);
} else if (entry.length() > MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT ) {
// to avoid accidental lockout, only count attempts that are long enough to be a
// real password. This may require some tweaking.
@@ -316,11 +325,8 @@
}
private void resetStatusInfo() {
- if(mIsAlpha) {
- mStatusView.setInstructionText(R.string.keyguard_password_enter_password_code);
- } else {
- mStatusView.setInstructionText(R.string.keyguard_password_enter_pin_password_code);
- }
+ mStatusView.setInstructionText(null);
+ mStatusView.updateStatusLines(true);
}
}
diff --git a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
index 5d1455e..6815d50 100644
--- a/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PatternUnlockScreen.java
@@ -169,6 +169,9 @@
}
mStatusView = new StatusView(this, mUpdateMonitor, mLockPatternUtils);
+ // This shows up when no other information is required on status1
+ mStatusView.setHelpMessage(R.string.lockscreen_pattern_instructions,
+ StatusView.LOCK_ICON);
mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
@@ -216,8 +219,8 @@
// assume normal footer mode for now
updateFooter(FooterMode.Normal);
- updateMonitor.registerInfoCallback(this);
- updateMonitor.registerSimStateCallback(this);
+ mUpdateMonitor.registerInfoCallback(this);
+ mUpdateMonitor.registerSimStateCallback(this);
setFocusableInTouchMode(true);
// until we get an update...
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index d6b7366..68c1453 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -197,7 +197,8 @@
/* Another feature is enabled and the user is trying to enable the custom title feature */
throw new AndroidRuntimeException("You cannot combine custom titles with other title features");
}
- if (((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) && (featureId != FEATURE_CUSTOM_TITLE)) {
+ if (((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) &&
+ (featureId != FEATURE_CUSTOM_TITLE) && (featureId != FEATURE_ACTION_MODE_OVERLAY)) {
/* Custom title feature is enabled and the user is trying to enable another feature */
throw new AndroidRuntimeException("You cannot combine custom titles with other title features");
diff --git a/policy/src/com/android/internal/policy/impl/StatusView.java b/policy/src/com/android/internal/policy/impl/StatusView.java
index 1caf0b7..4b91b65 100644
--- a/policy/src/com/android/internal/policy/impl/StatusView.java
+++ b/policy/src/com/android/internal/policy/impl/StatusView.java
@@ -19,10 +19,10 @@
import android.widget.TextView;
class StatusView {
- private static final int LOCK_ICON = R.drawable.ic_lock_idle_lock;
- private static final int ALARM_ICON = R.drawable.ic_lock_idle_alarm;
- private static final int CHARGING_ICON = R.drawable.ic_lock_idle_charging;
- private static final int BATTERY_LOW_ICON = R.drawable.ic_lock_idle_low_battery;
+ public static final int LOCK_ICON = R.drawable.ic_lock_idle_lock;
+ public static final int ALARM_ICON = R.drawable.ic_lock_idle_alarm;
+ public static final int CHARGING_ICON = R.drawable.ic_lock_idle_charging;
+ public static final int BATTERY_LOW_ICON = R.drawable.ic_lock_idle_low_battery;
private String mDateFormatString;
@@ -49,6 +49,8 @@
private TextView mAlarmStatus;
private LockPatternUtils mLockPatternUtils;
+ private int mHelpMessageId;
+ private int mHelpIconId;
private View findViewById(int id) {
return mView.findViewById(id);
@@ -123,13 +125,13 @@
void setInstructionText(int stringId) {
mStatus1.setText(stringId);
mStatus1.setCompoundDrawablesWithIntrinsicBounds(LOCK_ICON, 0, 0, 0);
- mStatus1.setVisibility(View.VISIBLE);
+ mStatus1.setVisibility(stringId != 0 ? View.VISIBLE : View.INVISIBLE);
}
void setInstructionText(String string) {
mStatus1.setText(string);
mStatus1.setCompoundDrawablesWithIntrinsicBounds(LOCK_ICON, 0, 0, 0);
- mStatus1.setVisibility(View.VISIBLE);
+ mStatus1.setVisibility(TextUtils.isEmpty(string) ? View.INVISIBLE : View.VISIBLE);
}
void setCarrierText(int stringId) {
@@ -148,8 +150,8 @@
*/
void updateStatusLines(boolean showStatusLines) {
if (!showStatusLines) {
- mStatus1.setVisibility(showStatusLines ? View.VISIBLE : View.GONE);
- mAlarmStatus.setVisibility(showStatusLines ? View.VISIBLE : View.GONE);
+ mStatus1.setVisibility(showStatusLines ? View.VISIBLE : View.INVISIBLE);
+ mAlarmStatus.setVisibility(showStatusLines ? View.VISIBLE : View.INVISIBLE);
return;
}
@@ -171,15 +173,14 @@
mAlarmStatus.setText(nextAlarm);
mAlarmStatus.setVisibility(View.VISIBLE);
} else {
- mAlarmStatus.setVisibility(View.GONE);
+ mAlarmStatus.setVisibility(View.INVISIBLE);
}
// Update Status1
- if (mInstructions != null) {
+ if (!TextUtils.isEmpty(mInstructions)) {
// Instructions only
- final int resId = TextUtils.isEmpty(mInstructions) ? 0 : LOCK_ICON;
mStatus1.setText(mInstructions);
- mStatus1.setCompoundDrawablesWithIntrinsicBounds(resId, 0, 0, 0);
+ mStatus1.setCompoundDrawablesWithIntrinsicBounds(LOCK_ICON, 0, 0, 0);
mStatus1.setVisibility(View.VISIBLE);
} else if (mShowingBatteryInfo) {
// Battery status
@@ -199,13 +200,22 @@
}
mStatus1.setVisibility(View.VISIBLE);
} else {
- // nothing specific to show; show general instructions
- mStatus1.setText(R.string.lockscreen_pattern_instructions);
- mStatus1.setCompoundDrawablesWithIntrinsicBounds(LOCK_ICON, 0,0, 0);
- mStatus1.setVisibility(View.VISIBLE);
+ // nothing specific to show; show help message and icon, if provided
+ if (mHelpMessageId != 0) {
+ mStatus1.setText(mHelpMessageId);
+ mStatus1.setCompoundDrawablesWithIntrinsicBounds(mHelpIconId, 0,0, 0);
+ mStatus1.setVisibility(View.VISIBLE);
+ } else {
+ mStatus1.setVisibility(View.INVISIBLE);
+ }
}
}
+ void setHelpMessage(int messageId, int iconId) {
+ mHelpMessageId = messageId;
+ mHelpIconId = iconId;
+ }
+
void refreshTimeAndDateDisplay() {
if (mHasDate) {
mDate.setText(DateFormat.format(mDateFormatString, new Date()));
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index b5a4bd2..e314145 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -154,6 +154,24 @@
return true;
}
+static void dumpRegion(String8& dump, const SkRegion& region) {
+ if (region.isEmpty()) {
+ dump.append("<empty>");
+ return;
+ }
+
+ bool first = true;
+ for (SkRegion::Iterator it(region); !it.done(); it.next()) {
+ if (first) {
+ first = false;
+ } else {
+ dump.append("|");
+ }
+ const SkIRect& rect = it.rect();
+ dump.appendFormat("[%d,%d][%d,%d]", rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
+ }
+}
+
// --- InputDispatcher ---
@@ -495,7 +513,7 @@
if (!(flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
| InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
- if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
+ if (isTouchModal || window->touchableRegionContainsPoint(x, y)) {
// Found window.
return window;
}
@@ -1188,7 +1206,7 @@
if (! (flags & InputWindow::FLAG_NOT_TOUCHABLE)) {
bool isTouchModal = (flags & (InputWindow::FLAG_NOT_FOCUSABLE
| InputWindow::FLAG_NOT_TOUCH_MODAL)) == 0;
- if (isTouchModal || window->touchableAreaContainsPoint(x, y)) {
+ if (isTouchModal || window->touchableRegionContainsPoint(x, y)) {
if (! screenWasOff || flags & InputWindow::FLAG_TOUCHABLE_WHEN_WAKING) {
newTouchedWindow = window;
}
@@ -2884,9 +2902,7 @@
dump.appendFormat(INDENT2 "%d: name='%s', paused=%s, hasFocus=%s, hasWallpaper=%s, "
"visible=%s, canReceiveKeys=%s, flags=0x%08x, type=0x%08x, layer=%d, "
"frame=[%d,%d][%d,%d], "
- "visibleFrame=[%d,%d][%d,%d], "
- "touchableArea=[%d,%d][%d,%d], "
- "ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
+ "touchableRegion=",
i, window.name.string(),
toString(window.paused),
toString(window.hasFocus),
@@ -2896,11 +2912,9 @@
window.layoutParamsFlags, window.layoutParamsType,
window.layer,
window.frameLeft, window.frameTop,
- window.frameRight, window.frameBottom,
- window.visibleFrameLeft, window.visibleFrameTop,
- window.visibleFrameRight, window.visibleFrameBottom,
- window.touchableAreaLeft, window.touchableAreaTop,
- window.touchableAreaRight, window.touchableAreaBottom,
+ window.frameRight, window.frameBottom);
+ dumpRegion(dump, window.touchableRegion);
+ dump.appendFormat(", ownerPid=%d, ownerUid=%d, dispatchingTimeout=%0.3fms\n",
window.ownerPid, window.ownerUid,
window.dispatchingTimeout / 1000000.0);
}
diff --git a/services/input/InputWindow.cpp b/services/input/InputWindow.cpp
index 9ce45f5..b552f6d 100644
--- a/services/input/InputWindow.cpp
+++ b/services/input/InputWindow.cpp
@@ -24,9 +24,8 @@
// --- InputWindow ---
-bool InputWindow::touchableAreaContainsPoint(int32_t x, int32_t y) const {
- return x >= touchableAreaLeft && x <= touchableAreaRight
- && y >= touchableAreaTop && y <= touchableAreaBottom;
+bool InputWindow::touchableRegionContainsPoint(int32_t x, int32_t y) const {
+ return touchableRegion.contains(x, y);
}
bool InputWindow::frameContainsPoint(int32_t x, int32_t y) const {
diff --git a/services/input/InputWindow.h b/services/input/InputWindow.h
index b3d5a65..9c43067 100644
--- a/services/input/InputWindow.h
+++ b/services/input/InputWindow.h
@@ -23,6 +23,8 @@
#include <utils/Timers.h>
#include <utils/String8.h>
+#include <SkRegion.h>
+
#include "InputApplication.h"
namespace android {
@@ -129,14 +131,7 @@
int32_t frameTop;
int32_t frameRight;
int32_t frameBottom;
- int32_t visibleFrameLeft;
- int32_t visibleFrameTop;
- int32_t visibleFrameRight;
- int32_t visibleFrameBottom;
- int32_t touchableAreaLeft;
- int32_t touchableAreaTop;
- int32_t touchableAreaRight;
- int32_t touchableAreaBottom;
+ SkRegion touchableRegion;
bool visible;
bool canReceiveKeys;
bool hasFocus;
@@ -146,7 +141,7 @@
int32_t ownerPid;
int32_t ownerUid;
- bool touchableAreaContainsPoint(int32_t x, int32_t y) const;
+ bool touchableRegionContainsPoint(int32_t x, int32_t y) const;
bool frameContainsPoint(int32_t x, int32_t y) const;
/* Returns true if the window is of a trusted type that is allowed to silently
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 2b98795..7b4f246 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -2540,16 +2540,16 @@
ArrayList<String>>> enabledImes, String imeId, String subtypeHashCode) {
for (Pair<String, ArrayList<String>> enabledIme: enabledImes) {
if (enabledIme.first.equals(imeId)) {
- final ArrayList<String> enabledSubtypes = enabledIme.second;
- if (enabledSubtypes.size() == 0) {
- // If there are no enabled subtypes, applicable subtypes are enabled
- // implicitly.
+ final ArrayList<String> explicitlyEnabledSubtypes = enabledIme.second;
+ if (explicitlyEnabledSubtypes.size() == 0) {
+ // If there are no explicitly enabled subtypes, applicable subtypes are
+ // enabled implicitly.
InputMethodInfo ime = mMethodMap.get(imeId);
// If IME is enabled and no subtypes are enabled, applicable subtypes
// are enabled implicitly, so needs to treat them to be enabled.
if (ime != null && ime.getSubtypes().size() > 0) {
List<InputMethodSubtype> implicitlySelectedSubtypes =
- getApplicableSubtypesLocked(mRes, ime.getSubtypes());
+ getApplicableSubtypesLocked(mRes, ime.getSubtypes());
if (implicitlySelectedSubtypes != null) {
final int N = implicitlySelectedSubtypes.size();
for (int i = 0; i < N; ++i) {
@@ -2561,7 +2561,7 @@
}
}
} else {
- for (String s: enabledSubtypes) {
+ for (String s: explicitlyEnabledSubtypes) {
if (s.equals(subtypeHashCode)) {
// If both imeId and subtypeId are enabled, return subtypeId.
return s;
diff --git a/services/java/com/android/server/InputWindow.java b/services/java/com/android/server/InputWindow.java
index 1515290..2c2cdfe 100644
--- a/services/java/com/android/server/InputWindow.java
+++ b/services/java/com/android/server/InputWindow.java
@@ -16,6 +16,7 @@
package com.android.server;
+import android.graphics.Region;
import android.view.InputChannel;
/**
@@ -39,23 +40,14 @@
// Dispatching timeout.
public long dispatchingTimeoutNanos;
- // Window frame area.
+ // Window frame.
public int frameLeft;
public int frameTop;
public int frameRight;
public int frameBottom;
- // Window visible frame area.
- public int visibleFrameLeft;
- public int visibleFrameTop;
- public int visibleFrameRight;
- public int visibleFrameBottom;
-
- // Window touchable area.
- public int touchableAreaLeft;
- public int touchableAreaTop;
- public int touchableAreaRight;
- public int touchableAreaBottom;
+ // Window touchable region.
+ public final Region touchableRegion = new Region();
// Window is visible.
public boolean visible;
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 1c3967d..19667d4 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -4806,6 +4806,74 @@
abstract void handleReturnCode();
}
+ class MeasureParams extends HandlerParams {
+ private final PackageStats mStats;
+ private boolean mSuccess;
+
+ private final IPackageStatsObserver mObserver;
+
+ public MeasureParams(PackageStats stats, boolean success,
+ IPackageStatsObserver observer) {
+ mObserver = observer;
+ mStats = stats;
+ mSuccess = success;
+ }
+
+ @Override
+ void handleStartCopy() throws RemoteException {
+ final boolean mounted;
+
+ if (Environment.isExternalStorageEmulated()) {
+ mounted = true;
+ } else {
+ final String status = Environment.getExternalStorageState();
+
+ mounted = status.equals(Environment.MEDIA_MOUNTED)
+ || status.equals(Environment.MEDIA_MOUNTED_READ_ONLY);
+ }
+
+ if (mounted) {
+ final File externalCacheDir = Environment
+ .getExternalStorageAppCacheDirectory(mStats.packageName);
+ final long externalCacheSize = mContainerService
+ .calculateDirectorySize(externalCacheDir.getPath());
+ mStats.externalCacheSize = externalCacheSize;
+
+ final File externalDataDir = Environment
+ .getExternalStorageAppDataDirectory(mStats.packageName);
+ long externalDataSize = mContainerService.calculateDirectorySize(externalDataDir
+ .getPath());
+
+ if (externalCacheDir.getParentFile().equals(externalDataDir)) {
+ externalDataSize -= externalCacheSize;
+ }
+ mStats.externalDataSize = externalDataSize;
+
+ final File externalMediaDir = Environment
+ .getExternalStorageAppMediaDirectory(mStats.packageName);
+ mStats.externalMediaSize = mContainerService
+ .calculateDirectorySize(externalCacheDir.getPath());
+ }
+ }
+
+ @Override
+ void handleReturnCode() {
+ if (mObserver != null) {
+ try {
+ mObserver.onGetStatsCompleted(mStats, mSuccess);
+ } catch (RemoteException e) {
+ Slog.i(TAG, "Observer no longer exists.");
+ }
+ }
+ }
+
+ @Override
+ void handleServiceError() {
+ Slog.e(TAG, "Could not measure application " + mStats.packageName
+ + " external storage");
+ }
+ }
+
class InstallParams extends HandlerParams {
final IPackageInstallObserver observer;
int flags;
@@ -6619,18 +6687,16 @@
mHandler.post(new Runnable() {
public void run() {
mHandler.removeCallbacks(this);
- PackageStats lStats = new PackageStats(packageName);
- final boolean succeded;
+ PackageStats stats = new PackageStats(packageName);
+
+ final boolean success;
synchronized (mInstallLock) {
- succeded = getPackageSizeInfoLI(packageName, lStats);
+ success = getPackageSizeInfoLI(packageName, stats);
}
- if(observer != null) {
- try {
- observer.onGetStatsCompleted(lStats, succeded);
- } catch (RemoteException e) {
- Log.i(TAG, "Observer no longer exists.");
- }
- } //end if observer
+
+ Message msg = mHandler.obtainMessage(INIT_COPY);
+ msg.obj = new MeasureParams(stats, success, observer);
+ mHandler.sendMessage(msg);
} //end run
});
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 6f4b4c5..978946f 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -204,11 +204,9 @@
// TODO: Use a more reliable check to see if this product should
// support Bluetooth - see bug 988521
if (SystemProperties.get("ro.kernel.qemu").equals("1")) {
- Slog.i(TAG, "Registering null Bluetooth Service (emulator)");
- ServiceManager.addService(BluetoothAdapter.BLUETOOTH_SERVICE, null);
+ Slog.i(TAG, "No Bluetooh Service (emulator)");
} else if (factoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) {
- Slog.i(TAG, "Registering null Bluetooth Service (factory test)");
- ServiceManager.addService(BluetoothAdapter.BLUETOOTH_SERVICE, null);
+ Slog.i(TAG, "No Bluetooth Service (factory test)");
} else {
Slog.i(TAG, "Bluetooth Service");
bluetooth = new BluetoothService(context);
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index bdc779c..1b3725c 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -520,7 +520,7 @@
int mRotation;
int mAnimFlags;
- private final Rect tmpRect = new Rect();
+ private final Region mTmpRegion = new Region();
DragState(IBinder token, Surface surface, int flags, IBinder localWin) {
mToken = token;
@@ -816,31 +816,13 @@
// not touchable == don't tell about drags
continue;
}
- // account for the window's decor etc
- tmpRect.set(child.mFrame);
- if (child.mTouchableInsets == ViewTreeObserver
- .InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT) {
- // The point is inside of the window if it is
- // inside the frame, AND the content part of that
- // frame that was given by the application.
- tmpRect.left += child.mGivenContentInsets.left;
- tmpRect.top += child.mGivenContentInsets.top;
- tmpRect.right -= child.mGivenContentInsets.right;
- tmpRect.bottom -= child.mGivenContentInsets.bottom;
- } else if (child.mTouchableInsets == ViewTreeObserver
- .InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE) {
- // The point is inside of the window if it is
- // inside the frame, AND the visible part of that
- // frame that was given by the application.
- tmpRect.left += child.mGivenVisibleInsets.left;
- tmpRect.top += child.mGivenVisibleInsets.top;
- tmpRect.right -= child.mGivenVisibleInsets.right;
- tmpRect.bottom -= child.mGivenVisibleInsets.bottom;
- }
+
+ child.getTouchableRegion(mTmpRegion);
+
final int touchFlags = flags &
- (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
- if (tmpRect.contains(x, y) || touchFlags == 0) {
+ (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
+ if (mTmpRegion.contains(x, y) || touchFlags == 0) {
// Found it
touchedWin = child;
break;
@@ -2667,7 +2649,7 @@
void setInsetsWindow(Session session, IWindow client,
int touchableInsets, Rect contentInsets,
- Rect visibleInsets) {
+ Rect visibleInsets, Region touchableRegion) {
long origId = Binder.clearCallingIdentity();
try {
synchronized (mWindowMap) {
@@ -2676,6 +2658,7 @@
w.mGivenInsetsPending = false;
w.mGivenContentInsets.set(contentInsets);
w.mGivenVisibleInsets.set(visibleInsets);
+ w.mGivenTouchableRegion.set(touchableRegion);
w.mTouchableInsets = touchableInsets;
mLayoutNeeded = true;
performLayoutAndPlaceSurfacesLocked();
@@ -5882,7 +5865,7 @@
final InputWindow inputWindow = windowList.add();
inputWindow.inputChannel = mDragState.mServerChannel;
inputWindow.name = "drag";
- inputWindow.layoutParamsFlags = 0;
+ inputWindow.layoutParamsFlags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
inputWindow.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
inputWindow.dispatchingTimeoutNanos = DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
inputWindow.visible = true;
@@ -5900,15 +5883,8 @@
inputWindow.frameRight = mDisplay.getWidth();
inputWindow.frameBottom = mDisplay.getHeight();
- inputWindow.visibleFrameLeft = inputWindow.frameLeft;
- inputWindow.visibleFrameTop = inputWindow.frameTop;
- inputWindow.visibleFrameRight = inputWindow.frameRight;
- inputWindow.visibleFrameBottom = inputWindow.frameBottom;
-
- inputWindow.touchableAreaLeft = inputWindow.frameLeft;
- inputWindow.touchableAreaTop = inputWindow.frameTop;
- inputWindow.touchableAreaRight = inputWindow.frameRight;
- inputWindow.touchableAreaBottom = inputWindow.frameBottom;
+ // The drag window cannot receive new touches.
+ inputWindow.touchableRegion.setEmpty();
}
/* Updates the cached window information provided to the input dispatcher. */
@@ -5973,40 +5949,8 @@
inputWindow.frameTop = frame.top;
inputWindow.frameRight = frame.right;
inputWindow.frameBottom = frame.bottom;
-
- final Rect visibleFrame = child.mVisibleFrame;
- inputWindow.visibleFrameLeft = visibleFrame.left;
- inputWindow.visibleFrameTop = visibleFrame.top;
- inputWindow.visibleFrameRight = visibleFrame.right;
- inputWindow.visibleFrameBottom = visibleFrame.bottom;
-
- switch (child.mTouchableInsets) {
- default:
- case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME:
- inputWindow.touchableAreaLeft = frame.left;
- inputWindow.touchableAreaTop = frame.top;
- inputWindow.touchableAreaRight = frame.right;
- inputWindow.touchableAreaBottom = frame.bottom;
- break;
-
- case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT: {
- Rect inset = child.mGivenContentInsets;
- inputWindow.touchableAreaLeft = frame.left + inset.left;
- inputWindow.touchableAreaTop = frame.top + inset.top;
- inputWindow.touchableAreaRight = frame.right - inset.right;
- inputWindow.touchableAreaBottom = frame.bottom - inset.bottom;
- break;
- }
-
- case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE: {
- Rect inset = child.mGivenVisibleInsets;
- inputWindow.touchableAreaLeft = frame.left + inset.left;
- inputWindow.touchableAreaTop = frame.top + inset.top;
- inputWindow.touchableAreaRight = frame.right - inset.right;
- inputWindow.touchableAreaBottom = frame.bottom - inset.bottom;
- break;
- }
- }
+
+ child.getTouchableRegion(inputWindow.touchableRegion);
}
// Send windows to native code.
@@ -6516,9 +6460,9 @@
}
public void setInsets(IWindow window, int touchableInsets,
- Rect contentInsets, Rect visibleInsets) {
+ Rect contentInsets, Rect visibleInsets, Region touchableArea) {
setInsetsWindow(this, window, touchableInsets, contentInsets,
- visibleInsets);
+ visibleInsets, touchableArea);
}
public void getDisplayFrame(IWindow window, Rect outDisplayFrame) {
@@ -6648,7 +6592,7 @@
synchronized (mWindowMap) {
long ident = Binder.clearCallingIdentity();
try {
- if (mDragState.mToken != token) {
+ if (mDragState == null || mDragState.mToken != token) {
Slog.w(TAG, "Invalid drop-result claim by " + window);
throw new IllegalStateException("reportDropResult() by non-recipient");
}
@@ -6857,6 +6801,11 @@
final Rect mGivenVisibleInsets = new Rect();
/**
+ * This is the given touchable area relative to the window frame, or null if none.
+ */
+ final Region mGivenTouchableRegion = new Region();
+
+ /**
* Flag indicating whether the touchable region should be adjusted by
* the visible insets; if false the area outside the visible insets is
* NOT touchable, so we must use those to adjust the frame during hit
@@ -8139,6 +8088,36 @@
return true;
}
+ public void getTouchableRegion(Region outRegion) {
+ final Rect frame = mFrame;
+ switch (mTouchableInsets) {
+ default:
+ case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME:
+ outRegion.set(frame);
+ break;
+ case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT: {
+ final Rect inset = mGivenContentInsets;
+ outRegion.set(
+ frame.left + inset.left, frame.top + inset.top,
+ frame.right - inset.right, frame.bottom - inset.bottom);
+ break;
+ }
+ case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE: {
+ final Rect inset = mGivenVisibleInsets;
+ outRegion.set(
+ frame.left + inset.left, frame.top + inset.top,
+ frame.right - inset.right, frame.bottom - inset.bottom);
+ break;
+ }
+ case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION: {
+ final Region givenTouchableRegion = mGivenTouchableRegion;
+ outRegion.set(givenTouchableRegion);
+ outRegion.translate(frame.left, frame.top);
+ break;
+ }
+ }
+ }
+
void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("mSession="); pw.print(mSession);
pw.print(" mClient="); pw.println(mClient.asBinder());
diff --git a/services/jni/com_android_server_InputWindow.cpp b/services/jni/com_android_server_InputWindow.cpp
index a4609a0..75154567c 100644
--- a/services/jni/com_android_server_InputWindow.cpp
+++ b/services/jni/com_android_server_InputWindow.cpp
@@ -21,6 +21,7 @@
#include <android_runtime/AndroidRuntime.h>
#include <android_view_InputChannel.h>
+#include <android/graphics/Region.h>
#include "com_android_server_InputWindow.h"
#include "com_android_server_InputWindowHandle.h"
@@ -39,14 +40,7 @@
jfieldID frameTop;
jfieldID frameRight;
jfieldID frameBottom;
- jfieldID visibleFrameLeft;
- jfieldID visibleFrameTop;
- jfieldID visibleFrameRight;
- jfieldID visibleFrameBottom;
- jfieldID touchableAreaLeft;
- jfieldID touchableAreaTop;
- jfieldID touchableAreaRight;
- jfieldID touchableAreaBottom;
+ jfieldID touchableRegion;
jfieldID visible;
jfieldID canReceiveKeys;
jfieldID hasFocus;
@@ -108,22 +102,17 @@
gInputWindowClassInfo.frameRight);
outInputWindow->frameBottom = env->GetIntField(inputWindowObj,
gInputWindowClassInfo.frameBottom);
- outInputWindow->visibleFrameLeft = env->GetIntField(inputWindowObj,
- gInputWindowClassInfo.visibleFrameLeft);
- outInputWindow->visibleFrameTop = env->GetIntField(inputWindowObj,
- gInputWindowClassInfo.visibleFrameTop);
- outInputWindow->visibleFrameRight = env->GetIntField(inputWindowObj,
- gInputWindowClassInfo.visibleFrameRight);
- outInputWindow->visibleFrameBottom = env->GetIntField(inputWindowObj,
- gInputWindowClassInfo.visibleFrameBottom);
- outInputWindow->touchableAreaLeft = env->GetIntField(inputWindowObj,
- gInputWindowClassInfo.touchableAreaLeft);
- outInputWindow->touchableAreaTop = env->GetIntField(inputWindowObj,
- gInputWindowClassInfo.touchableAreaTop);
- outInputWindow->touchableAreaRight = env->GetIntField(inputWindowObj,
- gInputWindowClassInfo.touchableAreaRight);
- outInputWindow->touchableAreaBottom = env->GetIntField(inputWindowObj,
- gInputWindowClassInfo.touchableAreaBottom);
+
+ jobject regionObj = env->GetObjectField(inputWindowObj,
+ gInputWindowClassInfo.touchableRegion);
+ if (regionObj) {
+ SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
+ outInputWindow->touchableRegion.set(*region);
+ env->DeleteLocalRef(regionObj);
+ } else {
+ outInputWindow->touchableRegion.setEmpty();
+ }
+
outInputWindow->visible = env->GetBooleanField(inputWindowObj,
gInputWindowClassInfo.visible);
outInputWindow->canReceiveKeys = env->GetBooleanField(inputWindowObj,
@@ -187,29 +176,8 @@
GET_FIELD_ID(gInputWindowClassInfo.frameBottom, gInputWindowClassInfo.clazz,
"frameBottom", "I");
- GET_FIELD_ID(gInputWindowClassInfo.visibleFrameLeft, gInputWindowClassInfo.clazz,
- "visibleFrameLeft", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.visibleFrameTop, gInputWindowClassInfo.clazz,
- "visibleFrameTop", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.visibleFrameRight, gInputWindowClassInfo.clazz,
- "visibleFrameRight", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.visibleFrameBottom, gInputWindowClassInfo.clazz,
- "visibleFrameBottom", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.touchableAreaLeft, gInputWindowClassInfo.clazz,
- "touchableAreaLeft", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.touchableAreaTop, gInputWindowClassInfo.clazz,
- "touchableAreaTop", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.touchableAreaRight, gInputWindowClassInfo.clazz,
- "touchableAreaRight", "I");
-
- GET_FIELD_ID(gInputWindowClassInfo.touchableAreaBottom, gInputWindowClassInfo.clazz,
- "touchableAreaBottom", "I");
+ GET_FIELD_ID(gInputWindowClassInfo.touchableRegion, gInputWindowClassInfo.clazz,
+ "touchableRegion", "Landroid/graphics/Region;");
GET_FIELD_ID(gInputWindowClassInfo.visible, gInputWindowClassInfo.clazz,
"visible", "Z");
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 154b822..65ad956 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2132,6 +2132,9 @@
sh = (!sh) ? hw_h : sh;
const size_t size = sw * sh * 4;
+ LOGD("screenshot: sw=%d, sh=%d, minZ=%d, maxZ=%d",
+ sw, sh, minLayerZ, maxLayerZ);
+
// make sure to clear all GL error flags
while ( glGetError() != GL_NO_ERROR ) ;
@@ -2146,6 +2149,9 @@
GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, tname);
GLenum status = glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES);
+
+ LOGD("screenshot: FBO created, status=0x%x", status);
+
if (status == GL_FRAMEBUFFER_COMPLETE_OES) {
// invert everything, b/c glReadPixel() below will invert the FB
@@ -2161,6 +2167,8 @@
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT);
+ LOGD("screenshot: glClear() issued");
+
const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
const size_t count = layers.size();
for (size_t i=0 ; i<count ; ++i) {
@@ -2171,6 +2179,8 @@
}
}
+ LOGD("screenshot: All layers rendered");
+
// XXX: this is needed on tegra
glScissor(0, 0, sw, sh);
@@ -2185,6 +2195,10 @@
new MemoryHeapBase(size, 0, "screen-capture") );
void* const ptr = base->getBase();
if (ptr) {
+
+ LOGD("screenshot: about to call glReadPixels(0,0,%d,%d,...,%p)",
+ sw, sh, ptr);
+
// capture the screen with glReadPixels()
glReadPixels(0, 0, sw, sh, GL_RGBA, GL_UNSIGNED_BYTE, ptr);
if (glGetError() == GL_NO_ERROR) {
@@ -2197,25 +2211,32 @@
} else {
result = NO_MEMORY;
}
+
+ LOGD("screenshot: glReadPixels() returned %s", strerror(result));
+
}
glEnable(GL_SCISSOR_TEST);
glViewport(0, 0, hw_w, hw_h);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
-
-
} else {
result = BAD_VALUE;
}
+ LOGD("screenshot: about to release FBO resources");
+
// release FBO resources
glBindFramebufferOES(GL_FRAMEBUFFER_OES, 0);
glDeleteRenderbuffersOES(1, &tname);
glDeleteFramebuffersOES(1, &name);
+ LOGD("screenshot: about to call compositionComplete()");
+
hw.compositionComplete();
+ LOGD("screenshot: result = %s", strerror(result));
+
return result;
}
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index 3b52252..0b4fc51 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -164,6 +164,11 @@
}
@Override
+ public File getObbDir() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public File getCacheDir() {
throw new UnsupportedOperationException();
}
diff --git a/tools/layoutlib/bridge/Android.mk b/tools/layoutlib/bridge/Android.mk
index 9b7bc5f..a0a7307 100644
--- a/tools/layoutlib/bridge/Android.mk
+++ b/tools/layoutlib/bridge/Android.mk
@@ -20,10 +20,11 @@
LOCAL_JAVA_LIBRARIES := \
kxml2-2.3.0 \
- layoutlib_api-prebuilt \
- ninepatch-prebuilt
+ layoutlib_api-prebuilt
-LOCAL_STATIC_JAVA_LIBRARIES := temp_layoutlib
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ temp_layoutlib \
+ ninepatch-prebuilt
LOCAL_MODULE := layoutlib
diff --git a/tools/layoutlib/bridge/src/com/android/ide/common/resources/ResourceResolver.java b/tools/layoutlib/bridge/src/com/android/ide/common/resources/ResourceResolver.java
new file mode 100644
index 0000000..4c500e7
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/ide/common/resources/ResourceResolver.java
@@ -0,0 +1,560 @@
+/*
+ * Copyright (C) 2011 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.ide.common.resources;
+
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.ide.common.rendering.api.StyleResourceValue;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ResourceResolver {
+
+ public final static String RES_ANIMATOR = "animator";
+ public final static String RES_STYLE = "style";
+ public final static String RES_ATTR = "attr";
+ public final static String RES_DIMEN = "dimen";
+ public final static String RES_DRAWABLE = "drawable";
+ public final static String RES_COLOR = "color";
+ public final static String RES_LAYOUT = "layout";
+ public final static String RES_STRING = "string";
+ public final static String RES_ID = "id";
+
+ public final static String REFERENCE_NULL = "@null";
+
+ private final static String REFERENCE_STYLE = RES_STYLE + "/";
+ private final static String PREFIX_ANDROID_RESOURCE_REF = "@android:";
+ private final static String PREFIX_RESOURCE_REF = "@";
+ private final static String PREFIX_ANDROID_THEME_REF = "?android:";
+ private final static String PREFIX_THEME_REF = "?";
+ private final static String PREFIX_ANDROID = "android:";
+
+
+ private final IFrameworkResourceIdProvider mFrameworkProvider;
+ private final Map<String, Map<String, ResourceValue>> mProjectResources;
+ private final Map<String, Map<String, ResourceValue>> mFrameworkResources;
+ private final LayoutLog mLogger;
+
+ private final Map<StyleResourceValue, StyleResourceValue> mStyleInheritanceMap =
+ new HashMap<StyleResourceValue, StyleResourceValue>();
+ private StyleResourceValue mTheme;
+
+ public interface IFrameworkResourceIdProvider {
+ Integer getId(String resType, String resName);
+ }
+
+ private ResourceResolver(
+ IFrameworkResourceIdProvider provider,
+ Map<String, Map<String, ResourceValue>> projectResources,
+ Map<String, Map<String, ResourceValue>> frameworkResources,
+ LayoutLog logger) {
+ mFrameworkProvider = provider;
+ mProjectResources = projectResources;
+ mFrameworkResources = frameworkResources;
+ mLogger = logger;
+ }
+
+ /**
+ * Creates a new ResourceResolver object.
+ *
+ * @param IFrameworkResourceIdProvider an optional framework resource ID provider
+ * @param projectResources the project resources.
+ * @param frameworkResources the framework resources.
+ * @param themeName the name of the current theme.
+ * @param isProjectTheme Is this a project theme?
+ * @return
+ */
+ public static ResourceResolver create(
+ IFrameworkResourceIdProvider provider,
+ Map<String, Map<String, ResourceValue>> projectResources,
+ Map<String, Map<String, ResourceValue>> frameworkResources,
+ String themeName, boolean isProjectTheme, LayoutLog logger) {
+
+ ResourceResolver resolver = new ResourceResolver(provider,
+ projectResources, frameworkResources,
+ logger);
+
+ resolver.computeStyleMaps(themeName, isProjectTheme);
+
+ return resolver;
+ }
+
+ public StyleResourceValue getTheme() {
+ return mTheme;
+ }
+
+ /**
+ * Returns a framework resource by type and name. The returned resource is resolved.
+ * @param resourceType the type of the resource
+ * @param resourceName the name of the resource
+ */
+ public ResourceValue getFrameworkResource(String resourceType, String resourceName) {
+ return getResource(resourceType, resourceName, mFrameworkResources);
+ }
+
+ /**
+ * Returns a project resource by type and name. The returned resource is resolved.
+ * @param resourceType the type of the resource
+ * @param resourceName the name of the resource
+ */
+ public ResourceValue getProjectResource(String resourceType, String resourceName) {
+ return getResource(resourceType, resourceName, mProjectResources);
+ }
+
+ /**
+ * Returns the {@link ResourceValue} matching a given name in the current theme. If the
+ * item is not directly available in the theme, the method looks in its parent theme.
+ *
+ * @param itemName the name of the item to search for.
+ * @return the {@link ResourceValue} object or <code>null</code>
+ */
+ public ResourceValue findItemInTheme(String itemName) {
+ if (mTheme != null) {
+ return findItemInStyle(mTheme, itemName);
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the {@link ResourceValue} matching a given name in a given style. If the
+ * item is not directly available in the style, the method looks in its parent style.
+ *
+ * @param style the style to search in
+ * @param itemName the name of the item to search for.
+ * @return the {@link ResourceValue} object or <code>null</code>
+ */
+ public ResourceValue findItemInStyle(StyleResourceValue style, String itemName) {
+ ResourceValue item = style.findValue(itemName);
+
+ // if we didn't find it, we look in the parent style (if applicable)
+ if (item == null && mStyleInheritanceMap != null) {
+ StyleResourceValue parentStyle = mStyleInheritanceMap.get(style);
+ if (parentStyle != null) {
+ return findItemInStyle(parentStyle, itemName);
+ }
+ }
+
+ return item;
+ }
+
+ /**
+ * Searches for, and returns a {@link ResourceValue} by its reference.
+ * <p/>
+ * The reference format can be:
+ * <pre>@resType/resName</pre>
+ * <pre>@android:resType/resName</pre>
+ * <pre>@resType/android:resName</pre>
+ * <pre>?resType/resName</pre>
+ * <pre>?android:resType/resName</pre>
+ * <pre>?resType/android:resName</pre>
+ * Any other string format will return <code>null</code>.
+ * <p/>
+ * The actual format of a reference is <pre>@[namespace:]resType/resName</pre> but this method
+ * only support the android namespace.
+ *
+ * @param reference the resource reference to search for.
+ * @param forceFrameworkOnly if true all references are considered to be toward framework
+ * resource even if the reference does not include the android: prefix.
+ * @return a {@link ResourceValue} or <code>null</code>.
+ */
+ public ResourceValue findResValue(String reference, boolean forceFrameworkOnly) {
+ if (reference == null) {
+ return null;
+ }
+ if (reference.startsWith(PREFIX_THEME_REF)) {
+ // no theme? no need to go further!
+ if (mTheme == null) {
+ return null;
+ }
+
+ boolean frameworkOnly = false;
+
+ // eliminate the prefix from the string
+ if (reference.startsWith(PREFIX_ANDROID_THEME_REF)) {
+ frameworkOnly = true;
+ reference = reference.substring(PREFIX_ANDROID_THEME_REF.length());
+ } else {
+ reference = reference.substring(PREFIX_THEME_REF.length());
+ }
+
+ // at this point, value can contain type/name (drawable/foo for instance).
+ // split it to make sure.
+ String[] segments = reference.split("\\/");
+
+ // we look for the referenced item name.
+ String referenceName = null;
+
+ if (segments.length == 2) {
+ // there was a resType in the reference. If it's attr, we ignore it
+ // else, we assert for now.
+ if (RES_ATTR.equals(segments[0])) {
+ referenceName = segments[1];
+ } else {
+ // At this time, no support for ?type/name where type is not "attr"
+ return null;
+ }
+ } else {
+ // it's just an item name.
+ referenceName = segments[0];
+ }
+
+ // now we look for android: in the referenceName in order to support format
+ // such as: ?attr/android:name
+ if (referenceName.startsWith(PREFIX_ANDROID)) {
+ frameworkOnly = true;
+ referenceName = referenceName.substring(PREFIX_ANDROID.length());
+ }
+
+ // Now look for the item in the theme, starting with the current one.
+ if (frameworkOnly) {
+ // FIXME for now we do the same as if it didn't specify android:
+ return findItemInStyle(mTheme, referenceName);
+ }
+
+ return findItemInStyle(mTheme, referenceName);
+ } else if (reference.startsWith(PREFIX_RESOURCE_REF)) {
+ boolean frameworkOnly = false;
+
+ // check for the specific null reference value.
+ if (REFERENCE_NULL.equals(reference)) {
+ return null;
+ }
+
+ // Eliminate the prefix from the string.
+ if (reference.startsWith(PREFIX_ANDROID_RESOURCE_REF)) {
+ frameworkOnly = true;
+ reference = reference.substring(
+ PREFIX_ANDROID_RESOURCE_REF.length());
+ } else {
+ reference = reference.substring(PREFIX_RESOURCE_REF.length());
+ }
+
+ // at this point, value contains type/[android:]name (drawable/foo for instance)
+ String[] segments = reference.split("\\/");
+
+ // now we look for android: in the resource name in order to support format
+ // such as: @drawable/android:name
+ if (segments[1].startsWith(PREFIX_ANDROID)) {
+ frameworkOnly = true;
+ segments[1] = segments[1].substring(PREFIX_ANDROID.length());
+ }
+
+ return findResValue(segments[0], segments[1],
+ forceFrameworkOnly ? true :frameworkOnly);
+ }
+
+ // Looks like the value didn't reference anything. Return null.
+ return null;
+ }
+
+ /**
+ * Resolves the value of a resource, if the value references a theme or resource value.
+ * <p/>
+ * This method ensures that it returns a {@link ResourceValue} object that does not
+ * reference another resource.
+ * If the resource cannot be resolved, it returns <code>null</code>.
+ * <p/>
+ * If a value that does not need to be resolved is given, the method will return a new
+ * instance of {@link ResourceValue} that contains the input value.
+ *
+ * @param type the type of the resource
+ * @param name the name of the attribute containing this value.
+ * @param value the resource value, or reference to resolve
+ * @param isFrameworkValue whether the value is a framework value.
+ *
+ * @return the resolved resource value or <code>null</code> if it failed to resolve it.
+ */
+ public ResourceValue resolveValue(String type, String name, String value,
+ boolean isFrameworkValue) {
+ if (value == null) {
+ return null;
+ }
+
+ // get the ResourceValue referenced by this value
+ ResourceValue resValue = findResValue(value, isFrameworkValue);
+
+ // if resValue is null, but value is not null, this means it was not a reference.
+ // we return the name/value wrapper in a ResourceValue. the isFramework flag doesn't
+ // matter.
+ if (resValue == null) {
+ return new ResourceValue(type, name, value, isFrameworkValue);
+ }
+
+ // we resolved a first reference, but we need to make sure this isn't a reference also.
+ return resolveResValue(resValue);
+ }
+
+ /**
+ * Returns the {@link ResourceValue} referenced by the value of <var>value</var>.
+ * <p/>
+ * This method ensures that it returns a {@link ResourceValue} object that does not
+ * reference another resource.
+ * If the resource cannot be resolved, it returns <code>null</code>.
+ * <p/>
+ * If a value that does not need to be resolved is given, the method will return the input
+ * value.
+ *
+ * @param value the value containing the reference to resolve.
+ * @return a {@link ResourceValue} object or <code>null</code>
+ */
+ public ResourceValue resolveResValue(ResourceValue value) {
+ if (value == null) {
+ return null;
+ }
+
+ // if the resource value is a style, we simply return it.
+ if (value instanceof StyleResourceValue) {
+ return value;
+ }
+
+ // else attempt to find another ResourceValue referenced by this one.
+ ResourceValue resolvedValue = findResValue(value.getValue(), value.isFramework());
+
+ // if the value did not reference anything, then we simply return the input value
+ if (resolvedValue == null) {
+ return value;
+ }
+
+ // otherwise, we attempt to resolve this new value as well
+ return resolveResValue(resolvedValue);
+ }
+
+
+ /**
+ * Searches for, and returns a {@link ResourceValue} by its name, and type.
+ * @param resType the type of the resource
+ * @param resName the name of the resource
+ * @param frameworkOnly if <code>true</code>, the method does not search in the
+ * project resources
+ */
+ private ResourceValue findResValue(String resType, String resName, boolean frameworkOnly) {
+ // map of ResouceValue for the given type
+ Map<String, ResourceValue> typeMap;
+
+ // if allowed, search in the project resources first.
+ if (frameworkOnly == false) {
+ typeMap = mProjectResources.get(resType);
+ if (typeMap != null) {
+ ResourceValue item = typeMap.get(resName);
+ if (item != null) {
+ return item;
+ }
+ }
+ }
+
+ // now search in the framework resources.
+ typeMap = mFrameworkResources.get(resType);
+ if (typeMap != null) {
+ ResourceValue item = typeMap.get(resName);
+ if (item != null) {
+ return item;
+ }
+
+ // if it was not found and the type is an id, it is possible that the ID was
+ // generated dynamically when compiling the framework resources.
+ // Look for it in the R map.
+ if (mFrameworkProvider != null && RES_ID.equals(resType)) {
+ if (mFrameworkProvider.getId(resType, resName) != null) {
+ return new ResourceValue(resType, resName, true);
+ }
+ }
+ }
+
+ // didn't find the resource anywhere.
+ // This is normal if the resource is an ID that is generated automatically.
+ // For other resources, we output a warning
+ if ("+id".equals(resType) == false && "+android:id".equals(resType) == false) { //$NON-NLS-1$ //$NON-NLS-2$
+ mLogger.warning(LayoutLog.TAG_RESOURCES_RESOLVE,
+ "Couldn't resolve resource @" +
+ (frameworkOnly ? "android:" : "") + resType + "/" + resName,
+ new ResourceValue(resType, resName, frameworkOnly));
+ }
+ return null;
+ }
+
+ ResourceValue getResource(String resourceType, String resourceName,
+ Map<String, Map<String, ResourceValue>> resourceRepository) {
+ Map<String, ResourceValue> typeMap = resourceRepository.get(resourceType);
+ if (typeMap != null) {
+ ResourceValue item = typeMap.get(resourceName);
+ if (item != null) {
+ item = resolveResValue(item);
+ return item;
+ }
+ }
+
+ // didn't find the resource anywhere.
+ return null;
+
+ }
+
+ /**
+ * Compute style information from the given list of style for the project and framework.
+ * @param themeName the name of the current theme.
+ * @param isProjectTheme Is this a project theme?
+ */
+ private void computeStyleMaps(String themeName, boolean isProjectTheme) {
+ Map<String, ResourceValue> projectStyleMap = mProjectResources.get(RES_STYLE);
+ Map<String, ResourceValue> frameworkStyleMap = mFrameworkResources.get(RES_STYLE);
+
+ if (projectStyleMap != null && frameworkStyleMap != null) {
+ // first, get the theme
+ ResourceValue theme = null;
+
+ // project theme names have been prepended with a *
+ if (isProjectTheme) {
+ theme = projectStyleMap.get(themeName);
+ } else {
+ theme = frameworkStyleMap.get(themeName);
+ }
+
+ if (theme instanceof StyleResourceValue) {
+ // compute the inheritance map for both the project and framework styles
+ computeStyleInheritance(projectStyleMap.values(), projectStyleMap,
+ frameworkStyleMap);
+
+ // Compute the style inheritance for the framework styles/themes.
+ // Since, for those, the style parent values do not contain 'android:'
+ // we want to force looking in the framework style only to avoid using
+ // similarly named styles from the project.
+ // To do this, we pass null in lieu of the project style map.
+ computeStyleInheritance(frameworkStyleMap.values(), null /*inProjectStyleMap */,
+ frameworkStyleMap);
+
+ mTheme = (StyleResourceValue) theme;
+ }
+ }
+ }
+
+
+
+ /**
+ * Compute the parent style for all the styles in a given list.
+ * @param styles the styles for which we compute the parent.
+ * @param inProjectStyleMap the map of project styles.
+ * @param inFrameworkStyleMap the map of framework styles.
+ * @param outInheritanceMap the map of style inheritance. This is filled by the method.
+ */
+ private void computeStyleInheritance(Collection<ResourceValue> styles,
+ Map<String, ResourceValue> inProjectStyleMap,
+ Map<String, ResourceValue> inFrameworkStyleMap) {
+ for (ResourceValue value : styles) {
+ if (value instanceof StyleResourceValue) {
+ StyleResourceValue style = (StyleResourceValue)value;
+ StyleResourceValue parentStyle = null;
+
+ // first look for a specified parent.
+ String parentName = style.getParentStyle();
+
+ // no specified parent? try to infer it from the name of the style.
+ if (parentName == null) {
+ parentName = getParentName(value.getName());
+ }
+
+ if (parentName != null) {
+ parentStyle = getStyle(parentName, inProjectStyleMap, inFrameworkStyleMap);
+
+ if (parentStyle != null) {
+ mStyleInheritanceMap.put(style, parentStyle);
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Computes the name of the parent style, or <code>null</code> if the style is a root style.
+ */
+ private String getParentName(String styleName) {
+ int index = styleName.lastIndexOf('.');
+ if (index != -1) {
+ return styleName.substring(0, index);
+ }
+
+ return null;
+ }
+
+ /**
+ * Searches for and returns the {@link StyleResourceValue} from a given name.
+ * <p/>The format of the name can be:
+ * <ul>
+ * <li>[android:]<name></li>
+ * <li>[android:]style/<name></li>
+ * <li>@[android:]style/<name></li>
+ * </ul>
+ * @param parentName the name of the style.
+ * @param inProjectStyleMap the project style map. Can be <code>null</code>
+ * @param inFrameworkStyleMap the framework style map.
+ * @return The matching {@link StyleResourceValue} object or <code>null</code> if not found.
+ */
+ private StyleResourceValue getStyle(String parentName,
+ Map<String, ResourceValue> inProjectStyleMap,
+ Map<String, ResourceValue> inFrameworkStyleMap) {
+ boolean frameworkOnly = false;
+
+ String name = parentName;
+
+ // remove the useless @ if it's there
+ if (name.startsWith(PREFIX_RESOURCE_REF)) {
+ name = name.substring(PREFIX_RESOURCE_REF.length());
+ }
+
+ // check for framework identifier.
+ if (name.startsWith(PREFIX_ANDROID)) {
+ frameworkOnly = true;
+ name = name.substring(PREFIX_ANDROID.length());
+ }
+
+ // at this point we could have the format <type>/<name>. we want only the name as long as
+ // the type is style.
+ if (name.startsWith(REFERENCE_STYLE)) {
+ name = name.substring(REFERENCE_STYLE.length());
+ } else if (name.indexOf('/') != -1) {
+ return null;
+ }
+
+ ResourceValue parent = null;
+
+ // if allowed, search in the project resources.
+ if (frameworkOnly == false && inProjectStyleMap != null) {
+ parent = inProjectStyleMap.get(name);
+ }
+
+ // if not found, then look in the framework resources.
+ if (parent == null) {
+ parent = inFrameworkStyleMap.get(name);
+ }
+
+ // make sure the result is the proper class type and return it.
+ if (parent instanceof StyleResourceValue) {
+ return (StyleResourceValue)parent;
+ }
+
+ assert false;
+ mLogger.error(LayoutLog.TAG_RESOURCES_RESOLVE,
+ String.format("Unable to resolve parent style name: %s", parentName),
+ null /*data*/);
+
+ return null;
+ }
+
+
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
index 194687e..112af1e 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeConstants.java
@@ -41,25 +41,6 @@
public final static String R = "com.android.internal.R";
- public final static String PREFIX_ANDROID_RESOURCE_REF = "@android:";
- public final static String PREFIX_RESOURCE_REF = "@";
- public final static String PREFIX_ANDROID_THEME_REF = "?android:";
- public final static String PREFIX_THEME_REF = "?";
-
- public final static String PREFIX_ANDROID = "android:";
-
- public final static String RES_ANIMATOR = "animator";
- public final static String RES_STYLE = "style";
- public final static String RES_ATTR = "attr";
- public final static String RES_DIMEN = "dimen";
- public final static String RES_DRAWABLE = "drawable";
- public final static String RES_COLOR = "color";
- public final static String RES_LAYOUT = "layout";
- public final static String RES_STRING = "string";
- public final static String RES_ID = "id";
-
- public final static String REFERENCE_STYLE = RES_STYLE + "/";
- public final static String REFERENCE_NULL = "@null";
public final static String MATCH_PARENT = "match_parent";
public final static String FILL_PARENT = "fill_parent";
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 82e217a..f633201 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -20,6 +20,7 @@
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.rendering.api.StyleResourceValue;
+import com.android.ide.common.resources.ResourceResolver;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.BridgeConstants;
import com.android.layoutlib.bridge.impl.Stack;
@@ -76,12 +77,9 @@
private Resources mResources;
private Theme mTheme;
private final HashMap<View, Object> mViewKeyMap = new HashMap<View, Object>();
- private final StyleResourceValue mThemeValues;
private final Object mProjectKey;
private final DisplayMetrics mMetrics;
- private final Map<String, Map<String, ResourceValue>> mProjectResources;
- private final Map<String, Map<String, ResourceValue>> mFrameworkResources;
- private final Map<StyleResourceValue, StyleResourceValue> mStyleInheritanceMap;
+ private final ResourceResolver mResourceResolver;
private final Map<Object, Map<String, String>> mDefaultPropMaps =
new IdentityHashMap<Object, Map<String,String>>();
@@ -116,19 +114,13 @@
* @param projectCallback
*/
public BridgeContext(Object projectKey, DisplayMetrics metrics,
- StyleResourceValue currentTheme,
- Map<String, Map<String, ResourceValue>> projectResources,
- Map<String, Map<String, ResourceValue>> frameworkResources,
- Map<StyleResourceValue, StyleResourceValue> styleInheritanceMap,
+ ResourceResolver resourceResolver,
IProjectCallback projectCallback) {
mProjectKey = projectKey;
mMetrics = metrics;
mProjectCallback = projectCallback;
- mThemeValues = currentTheme;
- mProjectResources = projectResources;
- mFrameworkResources = frameworkResources;
- mStyleInheritanceMap = styleInheritanceMap;
+ mResourceResolver = resourceResolver;
mFragments.mCurState = Fragment.CREATED;
mFragments.mActivity = this;
@@ -180,6 +172,10 @@
return mProjectCallback;
}
+ public ResourceResolver getResolver() {
+ return mResourceResolver;
+ }
+
public Map<String, String> getDefaultPropMap(Object key) {
return mDefaultPropMaps.get(key);
}
@@ -265,7 +261,7 @@
@Override
public final TypedArray obtainStyledAttributes(int[] attrs) {
- return createStyleBasedTypedArray(mThemeValues, attrs);
+ return createStyleBasedTypedArray(mResourceResolver.getTheme(), attrs);
}
@Override
@@ -362,7 +358,8 @@
customStyle = set.getAttributeValue(null /* namespace*/, "style");
}
if (customStyle != null) {
- ResourceValue item = findResValue(customStyle, false /*forceFrameworkOnly*/);
+ ResourceValue item = mResourceResolver.findResValue(customStyle,
+ false /*forceFrameworkOnly*/);
if (item instanceof StyleResourceValue) {
defStyleValues = (StyleResourceValue)item;
@@ -378,22 +375,21 @@
}
// look for the style in the current theme, and its parent:
- if (mThemeValues != null) {
- ResourceValue item = findItemInStyle(mThemeValues, defStyleName);
+ ResourceValue item = mResourceResolver.findItemInTheme(defStyleName);
- if (item != null) {
- // item is a reference to a style entry. Search for it.
- item = findResValue(item.getValue(), false /*forceFrameworkOnly*/);
+ if (item != null) {
+ // item is a reference to a style entry. Search for it.
+ item = mResourceResolver.findResValue(item.getValue(),
+ false /*forceFrameworkOnly*/);
- if (item instanceof StyleResourceValue) {
- defStyleValues = (StyleResourceValue)item;
- }
- } else {
- Bridge.getLog().error(null,
- String.format(
- "Failed to find style '%s' in current theme", defStyleName),
- null /*data*/);
+ if (item instanceof StyleResourceValue) {
+ defStyleValues = (StyleResourceValue)item;
}
+ } else {
+ Bridge.getLog().error(null,
+ String.format(
+ "Failed to find style '%s' in current theme", defStyleName),
+ null /*data*/);
}
}
@@ -425,13 +421,13 @@
// look for the value in the defStyle first (and its parent if needed)
if (defStyleValues != null) {
- resValue = findItemInStyle(defStyleValues, name);
+ resValue = mResourceResolver.findItemInStyle(defStyleValues, name);
}
// if the item is not present in the defStyle, we look in the main theme (and
// its parent themes)
- if (resValue == null && mThemeValues != null) {
- resValue = findItemInStyle(mThemeValues, name);
+ if (resValue == null) {
+ resValue = mResourceResolver.findItemInTheme(name);
}
// if we found a value, we make sure this doesn't reference another value.
@@ -442,14 +438,15 @@
defaultPropMap.put(name, resValue.getValue());
}
- resValue = resolveResValue(resValue);
+ resValue = mResourceResolver.resolveResValue(resValue);
}
ta.bridgeSetValue(index, name, resValue);
} else {
// there is a value in the XML, but we need to resolve it in case it's
// referencing another resource or a theme value.
- ta.bridgeSetValue(index, name, resolveValue(null, name, value, isPlatformFile));
+ ta.bridgeSetValue(index, name,
+ mResourceResolver.resolveValue(null, name, value, isPlatformFile));
}
}
}
@@ -487,10 +484,10 @@
String name = styleAttribute.getValue();
// get the value from the style, or its parent styles.
- ResourceValue resValue = findItemInStyle(style, name);
+ ResourceValue resValue = mResourceResolver.findItemInStyle(style, name);
// resolve it to make sure there are no references left.
- ta.bridgeSetValue(index, name, resolveResValue(resValue));
+ ta.bridgeSetValue(index, name, mResourceResolver.resolveResValue(resValue));
}
ta.sealArray();
@@ -500,295 +497,6 @@
/**
- * Resolves the value of a resource, if the value references a theme or resource value.
- * <p/>
- * This method ensures that it returns a {@link ResourceValue} object that does not
- * reference another resource.
- * If the resource cannot be resolved, it returns <code>null</code>.
- * <p/>
- * If a value that does not need to be resolved is given, the method will return a new
- * instance of {@link ResourceValue} that contains the input value.
- *
- * @param type the type of the resource
- * @param name the name of the attribute containing this value.
- * @param value the resource value, or reference to resolve
- * @param isFrameworkValue whether the value is a framework value.
- *
- * @return the resolved resource value or <code>null</code> if it failed to resolve it.
- */
- private ResourceValue resolveValue(String type, String name, String value,
- boolean isFrameworkValue) {
- if (value == null) {
- return null;
- }
-
- // get the ResourceValue referenced by this value
- ResourceValue resValue = findResValue(value, isFrameworkValue);
-
- // if resValue is null, but value is not null, this means it was not a reference.
- // we return the name/value wrapper in a ResourceValue. the isFramework flag doesn't
- // matter.
- if (resValue == null) {
- return new ResourceValue(type, name, value, isFrameworkValue);
- }
-
- // we resolved a first reference, but we need to make sure this isn't a reference also.
- return resolveResValue(resValue);
- }
-
- /**
- * Returns the {@link ResourceValue} referenced by the value of <var>value</var>.
- * <p/>
- * This method ensures that it returns a {@link ResourceValue} object that does not
- * reference another resource.
- * If the resource cannot be resolved, it returns <code>null</code>.
- * <p/>
- * If a value that does not need to be resolved is given, the method will return the input
- * value.
- *
- * @param value the value containing the reference to resolve.
- * @return a {@link ResourceValue} object or <code>null</code>
- */
- public ResourceValue resolveResValue(ResourceValue value) {
- if (value == null) {
- return null;
- }
-
- // if the resource value is a style, we simply return it.
- if (value instanceof StyleResourceValue) {
- return value;
- }
-
- // else attempt to find another ResourceValue referenced by this one.
- ResourceValue resolvedValue = findResValue(value.getValue(), value.isFramework());
-
- // if the value did not reference anything, then we simply return the input value
- if (resolvedValue == null) {
- return value;
- }
-
- // otherwise, we attempt to resolve this new value as well
- return resolveResValue(resolvedValue);
- }
-
- /**
- * Searches for, and returns a {@link ResourceValue} by its reference.
- * <p/>
- * The reference format can be:
- * <pre>@resType/resName</pre>
- * <pre>@android:resType/resName</pre>
- * <pre>@resType/android:resName</pre>
- * <pre>?resType/resName</pre>
- * <pre>?android:resType/resName</pre>
- * <pre>?resType/android:resName</pre>
- * Any other string format will return <code>null</code>.
- * <p/>
- * The actual format of a reference is <pre>@[namespace:]resType/resName</pre> but this method
- * only support the android namespace.
- *
- * @param reference the resource reference to search for.
- * @param forceFrameworkOnly if true all references are considered to be toward framework
- * resource even if the reference does not include the android: prefix.
- * @return a {@link ResourceValue} or <code>null</code>.
- */
- ResourceValue findResValue(String reference, boolean forceFrameworkOnly) {
- if (reference == null) {
- return null;
- }
- if (reference.startsWith(BridgeConstants.PREFIX_THEME_REF)) {
- // no theme? no need to go further!
- if (mThemeValues == null) {
- return null;
- }
-
- boolean frameworkOnly = false;
-
- // eliminate the prefix from the string
- if (reference.startsWith(BridgeConstants.PREFIX_ANDROID_THEME_REF)) {
- frameworkOnly = true;
- reference = reference.substring(BridgeConstants.PREFIX_ANDROID_THEME_REF.length());
- } else {
- reference = reference.substring(BridgeConstants.PREFIX_THEME_REF.length());
- }
-
- // at this point, value can contain type/name (drawable/foo for instance).
- // split it to make sure.
- String[] segments = reference.split("\\/");
-
- // we look for the referenced item name.
- String referenceName = null;
-
- if (segments.length == 2) {
- // there was a resType in the reference. If it's attr, we ignore it
- // else, we assert for now.
- if (BridgeConstants.RES_ATTR.equals(segments[0])) {
- referenceName = segments[1];
- } else {
- // At this time, no support for ?type/name where type is not "attr"
- return null;
- }
- } else {
- // it's just an item name.
- referenceName = segments[0];
- }
-
- // now we look for android: in the referenceName in order to support format
- // such as: ?attr/android:name
- if (referenceName.startsWith(BridgeConstants.PREFIX_ANDROID)) {
- frameworkOnly = true;
- referenceName = referenceName.substring(BridgeConstants.PREFIX_ANDROID.length());
- }
-
- // Now look for the item in the theme, starting with the current one.
- if (frameworkOnly) {
- // FIXME for now we do the same as if it didn't specify android:
- return findItemInStyle(mThemeValues, referenceName);
- }
-
- return findItemInStyle(mThemeValues, referenceName);
- } else if (reference.startsWith(BridgeConstants.PREFIX_RESOURCE_REF)) {
- boolean frameworkOnly = false;
-
- // check for the specific null reference value.
- if (BridgeConstants.REFERENCE_NULL.equals(reference)) {
- return null;
- }
-
- // Eliminate the prefix from the string.
- if (reference.startsWith(BridgeConstants.PREFIX_ANDROID_RESOURCE_REF)) {
- frameworkOnly = true;
- reference = reference.substring(
- BridgeConstants.PREFIX_ANDROID_RESOURCE_REF.length());
- } else {
- reference = reference.substring(BridgeConstants.PREFIX_RESOURCE_REF.length());
- }
-
- // at this point, value contains type/[android:]name (drawable/foo for instance)
- String[] segments = reference.split("\\/");
-
- // now we look for android: in the resource name in order to support format
- // such as: @drawable/android:name
- if (segments[1].startsWith(BridgeConstants.PREFIX_ANDROID)) {
- frameworkOnly = true;
- segments[1] = segments[1].substring(BridgeConstants.PREFIX_ANDROID.length());
- }
-
- return findResValue(segments[0], segments[1],
- forceFrameworkOnly ? true :frameworkOnly);
- }
-
- // Looks like the value didn't reference anything. Return null.
- return null;
- }
-
- /**
- * Searches for, and returns a {@link ResourceValue} by its name, and type.
- * @param resType the type of the resource
- * @param resName the name of the resource
- * @param frameworkOnly if <code>true</code>, the method does not search in the
- * project resources
- */
- private ResourceValue findResValue(String resType, String resName, boolean frameworkOnly) {
- // map of ResouceValue for the given type
- Map<String, ResourceValue> typeMap;
-
- // if allowed, search in the project resources first.
- if (frameworkOnly == false) {
- typeMap = mProjectResources.get(resType);
- if (typeMap != null) {
- ResourceValue item = typeMap.get(resName);
- if (item != null) {
- return item;
- }
- }
- }
-
- // now search in the framework resources.
- typeMap = mFrameworkResources.get(resType);
- if (typeMap != null) {
- ResourceValue item = typeMap.get(resName);
- if (item != null) {
- return item;
- }
-
- // if it was not found and the type is an id, it is possible that the ID was
- // generated dynamically when compiling the framework resources.
- // Look for it in the R map.
- if (BridgeConstants.RES_ID.equals(resType)) {
- if (Bridge.getResourceValue(resType, resName) != null) {
- return new ResourceValue(resType, resName, true);
- }
- }
- }
-
- // didn't find the resource anywhere.
- // This is normal if the resource is an ID that is generated automatically.
- // For other resources, we output a warning
- if ("+id".equals(resType) == false && "+android:id".equals(resType) == false) { //$NON-NLS-1$ //$NON-NLS-2$
- Bridge.getLog().warning(LayoutLog.TAG_RESOURCES_RESOLVE,
- "Couldn't resolve resource @" +
- (frameworkOnly ? "android:" : "") + resType + "/" + resName,
- new ResourceValue(resType, resName, frameworkOnly));
- }
- return null;
- }
-
- /**
- * Returns a framework resource by type and name. The returned resource is resolved.
- * @param resourceType the type of the resource
- * @param resourceName the name of the resource
- */
- public ResourceValue getFrameworkResource(String resourceType, String resourceName) {
- return getResource(resourceType, resourceName, mFrameworkResources);
- }
-
- /**
- * Returns a project resource by type and name. The returned resource is resolved.
- * @param resourceType the type of the resource
- * @param resourceName the name of the resource
- */
- public ResourceValue getProjectResource(String resourceType, String resourceName) {
- return getResource(resourceType, resourceName, mProjectResources);
- }
-
- ResourceValue getResource(String resourceType, String resourceName,
- Map<String, Map<String, ResourceValue>> resourceRepository) {
- Map<String, ResourceValue> typeMap = resourceRepository.get(resourceType);
- if (typeMap != null) {
- ResourceValue item = typeMap.get(resourceName);
- if (item != null) {
- item = resolveResValue(item);
- return item;
- }
- }
-
- // didn't find the resource anywhere.
- return null;
-
- }
-
- /**
- * Returns the {@link ResourceValue} matching a given name in a given style. If the
- * item is not directly available in the style, the method looks in its parent style.
- * @param style the style to search in
- * @param itemName the name of the item to search for.
- * @return the {@link ResourceValue} object or <code>null</code>
- */
- public ResourceValue findItemInStyle(StyleResourceValue style, String itemName) {
- ResourceValue item = style.findValue(itemName);
-
- // if we didn't find it, we look in the parent style (if applicable)
- if (item == null && mStyleInheritanceMap != null) {
- StyleResourceValue parentStyle = mStyleInheritanceMap.get(style);
- if (parentStyle != null) {
- return findItemInStyle(parentStyle, itemName);
- }
- }
-
- return item;
- }
-
- /**
* The input int[] attrs is one of com.android.internal.R.styleable fields where the name
* of the field is the style being referenced and the array contains one index per attribute.
* <p/>
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
index e95d295b..61f47ba 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeInflater.java
@@ -19,8 +19,8 @@
import com.android.ide.common.rendering.api.IProjectCallback;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.ide.common.resources.ResourceResolver;
import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.BridgeConstants;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
@@ -155,14 +155,14 @@
String[] layoutInfo = Bridge.resolveResourceValue(resource);
if (layoutInfo != null) {
- value = bridgeContext.getFrameworkResource(BridgeConstants.RES_LAYOUT,
- layoutInfo[0]);
+ value = bridgeContext.getResolver().getFrameworkResource(
+ ResourceResolver.RES_LAYOUT, layoutInfo[0]);
} else {
layoutInfo = mProjectCallback.resolveResourceValue(resource);
if (layoutInfo != null) {
- value = bridgeContext.getProjectResource(BridgeConstants.RES_LAYOUT,
- layoutInfo[0]);
+ value = bridgeContext.getResolver().getProjectResource(
+ ResourceResolver.RES_LAYOUT, layoutInfo[0]);
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
index 23d81a2..3af6a1b 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
@@ -104,7 +104,7 @@
if (resourceInfo != null) {
platformResFlag_out[0] = true;
- return mContext.getFrameworkResource(resourceInfo[1], resourceInfo[0]);
+ return mContext.getResolver().getFrameworkResource(resourceInfo[1], resourceInfo[0]);
}
// didn't find a match in the framework? look in the project.
@@ -113,7 +113,7 @@
if (resourceInfo != null) {
platformResFlag_out[0] = false;
- return mContext.getProjectResource(resourceInfo[1], resourceInfo[0]);
+ return mContext.getResolver().getProjectResource(resourceInfo[1], resourceInfo[0]);
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
index 84bb4d1..b166da5 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeTypedArray.java
@@ -19,6 +19,7 @@
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.rendering.api.StyleResourceValue;
+import com.android.ide.common.resources.ResourceResolver;
import com.android.internal.util.XmlUtils;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.BridgeConstants;
@@ -633,11 +634,11 @@
// if this is a framework id
if (mPlatformFile || value.startsWith("@android") || value.startsWith("@+android")) {
// look for idName in the android R classes
- return mContext.getFrameworkResourceValue(BridgeConstants.RES_ID, idName, defValue);
+ return mContext.getFrameworkResourceValue(ResourceResolver.RES_ID, idName, defValue);
}
// look for idName in the project R class.
- return mContext.getProjectResourceValue(BridgeConstants.RES_ID, idName, defValue);
+ return mContext.getProjectResourceValue(ResourceResolver.RES_ID, idName, defValue);
}
// not a direct id valid reference? resolve it
@@ -682,7 +683,7 @@
ResourceValue value = mResourceData[index];
String stringValue = value.getValue();
- if (stringValue == null || BridgeConstants.REFERENCE_NULL.equals(stringValue)) {
+ if (stringValue == null || ResourceResolver.REFERENCE_NULL.equals(stringValue)) {
return null;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
index 443d881..8422d48 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -102,7 +102,7 @@
}
public void setInsets(IWindow window, int touchable, Rect contentInsets,
- Rect visibleInsets) {
+ Rect visibleInsets, Region touchableRegion) {
// pass for now.
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlPullAttributes.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlPullAttributes.java
index ba45217..45d8e26 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlPullAttributes.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeXmlPullAttributes.java
@@ -17,6 +17,7 @@
package com.android.layoutlib.bridge.android;
import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.ide.common.resources.ResourceResolver;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.BridgeConstants;
@@ -57,7 +58,7 @@
String ns = mParser.getAttributeNamespace(index);
if (BridgeConstants.NS_RESOURCES.equals(ns)) {
- Integer v = Bridge.getResourceValue(BridgeConstants.RES_ATTR, name);
+ Integer v = Bridge.getResourceValue(ResourceResolver.RES_ATTR, name);
if (v != null) {
return v.intValue();
}
@@ -68,7 +69,7 @@
// this is not an attribute in the android namespace, we query the customviewloader, if
// the namespaces match.
if (mContext.getProjectCallback().getNamespace().equals(ns)) {
- Integer v = mContext.getProjectCallback().getResourceValue(BridgeConstants.RES_ATTR,
+ Integer v = mContext.getProjectCallback().getResourceValue(ResourceResolver.RES_ATTR,
name);
if (v != null) {
return v.intValue();
@@ -102,8 +103,9 @@
private int resolveResourceValue(String value, int defaultValue) {
// now look for this particular value
- ResourceValue resource = mContext.resolveResValue(
- mContext.findResValue(value, mPlatformFile));
+ ResourceResolver resolver = mContext.getResolver();
+ ResourceValue resource = resolver.resolveResValue(
+ resolver.findResValue(value, mPlatformFile));
if (resource != null) {
Integer id = null;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 2439791..a227d0c 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -38,9 +38,10 @@
import com.android.ide.common.rendering.api.ViewInfo;
import com.android.ide.common.rendering.api.Params.RenderingMode;
import com.android.ide.common.rendering.api.Result.Status;
+import com.android.ide.common.resources.ResourceResolver;
+import com.android.ide.common.resources.ResourceResolver.IFrameworkResourceIdProvider;
import com.android.internal.util.XmlUtils;
import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.BridgeConstants;
import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.android.BridgeInflater;
import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
@@ -73,8 +74,6 @@
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@@ -106,7 +105,6 @@
private BridgeContext mContext;
private BridgeXmlBlockParser mBlockParser;
private BridgeInflater mInflater;
- private StyleResourceValue mCurrentTheme;
private int mScreenOffset;
private ResourceValue mWindowBackground;
private FrameLayout mViewRoot;
@@ -170,18 +168,23 @@
metrics.xdpi = mParams.getXdpi();
metrics.ydpi = mParams.getYdpi();
- // find the current theme and compute the style inheritance map
- Map<StyleResourceValue, StyleResourceValue> styleParentMap =
- new HashMap<StyleResourceValue, StyleResourceValue>();
+ // create the resource resolver
+ ResourceResolver resolver = ResourceResolver.create(
+ new IFrameworkResourceIdProvider() {
+ public Integer getId(String resType, String resName) {
+ return Bridge.getResourceValue(resType, resName);
+ }
+ },
+ mParams.getProjectResources(),
+ mParams.getFrameworkResources(),
+ mParams.getThemeName(),
+ mParams.isProjectTheme(),
+ mParams.getLog());
- mCurrentTheme = computeStyleMaps(mParams.getThemeName(), mParams.isProjectTheme(),
- mParams.getProjectResources().get(BridgeConstants.RES_STYLE),
- mParams.getFrameworkResources().get(BridgeConstants.RES_STYLE), styleParentMap);
// build the context
- mContext = new BridgeContext(mParams.getProjectKey(), metrics, mCurrentTheme,
- mParams.getProjectResources(), mParams.getFrameworkResources(),
- styleParentMap, mParams.getProjectCallback());
+ mContext = new BridgeContext(mParams.getProjectKey(), metrics, resolver,
+ mParams.getProjectCallback());
// set the current rendering context
sCurrentContext = mContext;
@@ -193,12 +196,12 @@
// get the screen offset and window-background resource
mWindowBackground = null;
mScreenOffset = 0;
- if (mCurrentTheme != null && mParams.isBgColorOverridden() == false) {
- mWindowBackground = mContext.findItemInStyle(mCurrentTheme, "windowBackground");
- mWindowBackground = mContext.resolveResValue(mWindowBackground);
+ StyleResourceValue theme = resolver.getTheme();
+ if (theme != null && mParams.isBgColorOverridden() == false) {
+ mWindowBackground = resolver.findItemInTheme("windowBackground");
+ mWindowBackground = resolver.resolveResValue(mWindowBackground);
- mScreenOffset = getScreenOffset(mParams.getFrameworkResources(), mCurrentTheme,
- mContext);
+ mScreenOffset = getScreenOffset(resolver, metrics);
}
// build the inflater and parser.
@@ -499,18 +502,18 @@
ResourceValue animationResource = null;
int animationId = 0;
if (isFrameworkAnimation) {
- animationResource = mContext.getFrameworkResource(BridgeConstants.RES_ANIMATOR,
- animationName);
+ animationResource = mContext.getResolver().getFrameworkResource(
+ ResourceResolver.RES_ANIMATOR, animationName);
if (animationResource != null) {
- animationId = Bridge.getResourceValue(BridgeConstants.RES_ANIMATOR,
+ animationId = Bridge.getResourceValue(ResourceResolver.RES_ANIMATOR,
animationName);
}
} else {
- animationResource = mContext.getProjectResource(BridgeConstants.RES_ANIMATOR,
- animationName);
+ animationResource = mContext.getResolver().getProjectResource(
+ ResourceResolver.RES_ANIMATOR, animationName);
if (animationResource != null) {
animationId = mContext.getProjectCallback().getResourceValue(
- BridgeConstants.RES_ANIMATOR, animationName);
+ ResourceResolver.RES_ANIMATOR, animationName);
}
}
@@ -905,182 +908,21 @@
}
}
-
- /**
- * Compute style information from the given list of style for the project and framework.
- * @param themeName the name of the current theme. In order to differentiate project and
- * platform themes sharing the same name, all project themes must be prepended with
- * a '*' character.
- * @param isProjectTheme Is this a project theme
- * @param inProjectStyleMap the project style map
- * @param inFrameworkStyleMap the framework style map
- * @param outInheritanceMap the map of style inheritance. This is filled by the method
- * @return the {@link StyleResourceValue} matching <var>themeName</var>
- */
- private StyleResourceValue computeStyleMaps(
- String themeName, boolean isProjectTheme, Map<String,
- ResourceValue> inProjectStyleMap, Map<String, ResourceValue> inFrameworkStyleMap,
- Map<StyleResourceValue, StyleResourceValue> outInheritanceMap) {
-
- if (inProjectStyleMap != null && inFrameworkStyleMap != null) {
- // first, get the theme
- ResourceValue theme = null;
-
- // project theme names have been prepended with a *
- if (isProjectTheme) {
- theme = inProjectStyleMap.get(themeName);
- } else {
- theme = inFrameworkStyleMap.get(themeName);
- }
-
- if (theme instanceof StyleResourceValue) {
- // compute the inheritance map for both the project and framework styles
- computeStyleInheritance(inProjectStyleMap.values(), inProjectStyleMap,
- inFrameworkStyleMap, outInheritanceMap);
-
- // Compute the style inheritance for the framework styles/themes.
- // Since, for those, the style parent values do not contain 'android:'
- // we want to force looking in the framework style only to avoid using
- // similarly named styles from the project.
- // To do this, we pass null in lieu of the project style map.
- computeStyleInheritance(inFrameworkStyleMap.values(), null /*inProjectStyleMap */,
- inFrameworkStyleMap, outInheritanceMap);
-
- return (StyleResourceValue)theme;
- }
- }
-
- return null;
- }
-
- /**
- * Compute the parent style for all the styles in a given list.
- * @param styles the styles for which we compute the parent.
- * @param inProjectStyleMap the map of project styles.
- * @param inFrameworkStyleMap the map of framework styles.
- * @param outInheritanceMap the map of style inheritance. This is filled by the method.
- */
- private void computeStyleInheritance(Collection<ResourceValue> styles,
- Map<String, ResourceValue> inProjectStyleMap,
- Map<String, ResourceValue> inFrameworkStyleMap,
- Map<StyleResourceValue, StyleResourceValue> outInheritanceMap) {
- for (ResourceValue value : styles) {
- if (value instanceof StyleResourceValue) {
- StyleResourceValue style = (StyleResourceValue)value;
- StyleResourceValue parentStyle = null;
-
- // first look for a specified parent.
- String parentName = style.getParentStyle();
-
- // no specified parent? try to infer it from the name of the style.
- if (parentName == null) {
- parentName = getParentName(value.getName());
- }
-
- if (parentName != null) {
- parentStyle = getStyle(parentName, inProjectStyleMap, inFrameworkStyleMap);
-
- if (parentStyle != null) {
- outInheritanceMap.put(style, parentStyle);
- }
- }
- }
- }
- }
-
- /**
- * Searches for and returns the {@link StyleResourceValue} from a given name.
- * <p/>The format of the name can be:
- * <ul>
- * <li>[android:]<name></li>
- * <li>[android:]style/<name></li>
- * <li>@[android:]style/<name></li>
- * </ul>
- * @param parentName the name of the style.
- * @param inProjectStyleMap the project style map. Can be <code>null</code>
- * @param inFrameworkStyleMap the framework style map.
- * @return The matching {@link StyleResourceValue} object or <code>null</code> if not found.
- */
- private StyleResourceValue getStyle(String parentName,
- Map<String, ResourceValue> inProjectStyleMap,
- Map<String, ResourceValue> inFrameworkStyleMap) {
- boolean frameworkOnly = false;
-
- String name = parentName;
-
- // remove the useless @ if it's there
- if (name.startsWith(BridgeConstants.PREFIX_RESOURCE_REF)) {
- name = name.substring(BridgeConstants.PREFIX_RESOURCE_REF.length());
- }
-
- // check for framework identifier.
- if (name.startsWith(BridgeConstants.PREFIX_ANDROID)) {
- frameworkOnly = true;
- name = name.substring(BridgeConstants.PREFIX_ANDROID.length());
- }
-
- // at this point we could have the format <type>/<name>. we want only the name as long as
- // the type is style.
- if (name.startsWith(BridgeConstants.REFERENCE_STYLE)) {
- name = name.substring(BridgeConstants.REFERENCE_STYLE.length());
- } else if (name.indexOf('/') != -1) {
- return null;
- }
-
- ResourceValue parent = null;
-
- // if allowed, search in the project resources.
- if (frameworkOnly == false && inProjectStyleMap != null) {
- parent = inProjectStyleMap.get(name);
- }
-
- // if not found, then look in the framework resources.
- if (parent == null) {
- parent = inFrameworkStyleMap.get(name);
- }
-
- // make sure the result is the proper class type and return it.
- if (parent instanceof StyleResourceValue) {
- return (StyleResourceValue)parent;
- }
-
- assert false;
- mParams.getLog().error(LayoutLog.TAG_RESOURCES_RESOLVE,
- String.format("Unable to resolve parent style name: %s", parentName),
- null /*data*/);
-
- return null;
- }
-
- /**
- * Computes the name of the parent style, or <code>null</code> if the style is a root style.
- */
- private String getParentName(String styleName) {
- int index = styleName.lastIndexOf('.');
- if (index != -1) {
- return styleName.substring(0, index);
- }
-
- return null;
- }
-
/**
* Returns the top screen offset. This depends on whether the current theme defines the user
* of the title and status bars.
- * @param frameworkResources The framework resources
- * @param currentTheme The current theme
- * @param context The context
+ * @param resolver The {@link ResourceResolver}
+ * @param metrics The display metrics
* @return the pixel height offset
*/
- private int getScreenOffset(Map<String, Map<String, ResourceValue>> frameworkResources,
- StyleResourceValue currentTheme, BridgeContext context) {
+ private int getScreenOffset(ResourceResolver resolver, DisplayMetrics metrics) {
int offset = 0;
// get the title bar flag from the current theme.
- ResourceValue value = context.findItemInStyle(currentTheme, "windowNoTitle");
+ ResourceValue value = resolver.findItemInTheme("windowNoTitle");
// because it may reference something else, we resolve it.
- value = context.resolveResValue(value);
+ value = resolver.resolveResValue(value);
// if there's a value and it's true (default is false)
if (value == null || value.getValue() == null ||
@@ -1089,17 +931,17 @@
int defaultOffset = DEFAULT_TITLE_BAR_HEIGHT;
// get value from the theme.
- value = context.findItemInStyle(currentTheme, "windowTitleSize");
+ value = resolver.findItemInTheme("windowTitleSize");
// resolve it
- value = context.resolveResValue(value);
+ value = resolver.resolveResValue(value);
if (value != null) {
// get the numerical value, if available
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
if (typedValue != null) {
// compute the pixel value based on the display metrics
- defaultOffset = (int)typedValue.getDimension(context.getResources().mMetrics);
+ defaultOffset = (int)typedValue.getDimension(metrics);
}
}
@@ -1107,10 +949,10 @@
}
// get the fullscreen flag from the current theme.
- value = context.findItemInStyle(currentTheme, "windowFullscreen");
+ value = resolver.findItemInTheme("windowFullscreen");
// because it may reference something else, we resolve it.
- value = context.resolveResValue(value);
+ value = resolver.resolveResValue(value);
if (value == null || value.getValue() == null ||
XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) {
@@ -1118,16 +960,13 @@
// default value
int defaultOffset = DEFAULT_STATUS_BAR_HEIGHT;
- // get the real value, first the list of Dimensions from the framework map
- Map<String, ResourceValue> dimens = frameworkResources.get(BridgeConstants.RES_DIMEN);
-
- // now get the value
- value = dimens.get("status_bar_height");
+ // get the real value
+ value = resolver.getFrameworkResource(ResourceResolver.RES_DIMEN, "status_bar_height");
if (value != null) {
TypedValue typedValue = ResourceHelper.getValue(value.getValue());
if (typedValue != null) {
// compute the pixel value based on the display metrics
- defaultOffset = (int)typedValue.getDimension(context.getResources().mMetrics);
+ defaultOffset = (int)typedValue.getDimension(metrics);
}
}
@@ -1136,7 +975,6 @@
}
return offset;
-
}
/**