Merge "Finish fixing Zygote descriptor leakage problem"
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 97baf9a..d3080e5 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1541,11 +1541,11 @@
/**
* Creates the top level resources for the given package.
*/
- Resources getTopLevelResources(String resDir,
+ Resources getTopLevelResources(String resDir, String[] overlayDirs,
int displayId, Configuration overrideConfiguration,
LoadedApk pkgInfo) {
- return mResourcesManager.getTopLevelResources(resDir, displayId, overrideConfiguration,
- pkgInfo.getCompatibilityInfo(), null);
+ return mResourcesManager.getTopLevelResources(resDir, overlayDirs, displayId,
+ overrideConfiguration, pkgInfo.getCompatibilityInfo(), null);
}
final Handler getHandler() {
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index b505d4f..a280448 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -774,7 +774,7 @@
}
Resources r = mContext.mMainThread.getTopLevelResources(
app.uid == Process.myUid() ? app.sourceDir : app.publicSourceDir,
- Display.DEFAULT_DISPLAY, null, mContext.mPackageInfo);
+ app.resourceDirs, Display.DEFAULT_DISPLAY, null, mContext.mPackageInfo);
if (r != null) {
return r;
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 190ddb4..8d127c6 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1911,8 +1911,8 @@
ContextImpl c = new ContextImpl();
c.init(mPackageInfo, null, mMainThread);
c.mResources = mResourcesManager.getTopLevelResources(mPackageInfo.getResDir(),
- getDisplayId(), overrideConfiguration, mResources.getCompatibilityInfo(),
- mActivityToken);
+ mPackageInfo.getOverlayDirs(), getDisplayId(), overrideConfiguration,
+ mResources.getCompatibilityInfo(), mActivityToken);
return c;
}
@@ -1929,7 +1929,7 @@
context.mDisplay = display;
DisplayAdjustments daj = getDisplayAdjustments(displayId);
context.mResources = mResourcesManager.getTopLevelResources(mPackageInfo.getResDir(),
- displayId, null, daj.getCompatibilityInfo(), null);
+ mPackageInfo.getOverlayDirs(), displayId, null, daj.getCompatibilityInfo(), null);
return context;
}
@@ -2041,7 +2041,8 @@
mDisplayAdjustments.setCompatibilityInfo(compatInfo);
mDisplayAdjustments.setActivityToken(activityToken);
mResources = mResourcesManager.getTopLevelResources(mPackageInfo.getResDir(),
- Display.DEFAULT_DISPLAY, null, compatInfo, activityToken);
+ mPackageInfo.getOverlayDirs(), Display.DEFAULT_DISPLAY, null, compatInfo,
+ activityToken);
} else {
mDisplayAdjustments.setCompatibilityInfo(packageInfo.getCompatibilityInfo());
mDisplayAdjustments.setActivityToken(activityToken);
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 4239a5d..0115d1b 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -76,6 +76,7 @@
final String mPackageName;
private final String mAppDir;
private final String mResDir;
+ private final String[] mOverlayDirs;
private final String[] mSharedLibraries;
private final String mDataDir;
private final String mLibDir;
@@ -120,6 +121,7 @@
final int myUid = Process.myUid();
mResDir = aInfo.uid == myUid ? aInfo.sourceDir
: aInfo.publicSourceDir;
+ mOverlayDirs = aInfo.resourceDirs;
if (!UserHandle.isSameUser(aInfo.uid, myUid) && !Process.isIsolated()) {
aInfo.dataDir = PackageManager.getDataDirForUser(UserHandle.getUserId(myUid),
mPackageName);
@@ -159,6 +161,7 @@
mPackageName = name;
mAppDir = null;
mResDir = null;
+ mOverlayDirs = null;
mSharedLibraries = null;
mDataDir = null;
mDataDirFile = null;
@@ -471,6 +474,10 @@
return mResDir;
}
+ public String[] getOverlayDirs() {
+ return mOverlayDirs;
+ }
+
public String getDataDir() {
return mDataDir;
}
@@ -485,7 +492,7 @@
public Resources getResources(ActivityThread mainThread) {
if (mResources == null) {
- mResources = mainThread.getTopLevelResources(mResDir,
+ mResources = mainThread.getTopLevelResources(mResDir, mOverlayDirs,
Display.DEFAULT_DISPLAY, null, this);
}
return mResources;
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index f55dba4..728f372 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -147,7 +147,7 @@
* @param compatInfo the compability info. Must not be null.
* @param token the application token for determining stack bounds.
*/
- public Resources getTopLevelResources(String resDir, int displayId,
+ public Resources getTopLevelResources(String resDir, String[] overlayDirs, int displayId,
Configuration overrideConfiguration, CompatibilityInfo compatInfo, IBinder token) {
final float scale = compatInfo.applicationScale;
ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfiguration, scale,
@@ -180,6 +180,12 @@
return null;
}
+ if (overlayDirs != null) {
+ for (String idmapPath : overlayDirs) {
+ assets.addOverlayPath(idmapPath);
+ }
+ }
+
//Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
DisplayMetrics dm = getDisplayMetricsLocked(displayId);
Configuration config;
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index af1a6d5..785f2b4 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -227,6 +227,14 @@
/** @hide */
public String requiredAccountType;
+ /**
+ * What package, if any, this package will overlay.
+ *
+ * Package name of target package, or null.
+ * @hide
+ */
+ public String overlayTarget;
+
public PackageInfo() {
}
@@ -270,6 +278,7 @@
dest.writeInt(requiredForAllUsers ? 1 : 0);
dest.writeString(restrictedAccountType);
dest.writeString(requiredAccountType);
+ dest.writeString(overlayTarget);
}
public static final Parcelable.Creator<PackageInfo> CREATOR
@@ -311,5 +320,6 @@
requiredForAllUsers = source.readInt() != 0;
restrictedAccountType = source.readString();
requiredAccountType = source.readString();
+ overlayTarget = source.readString();
}
}
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 4607902..52564eb 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -307,6 +307,7 @@
}
pi.restrictedAccountType = p.mRestrictedAccountType;
pi.requiredAccountType = p.mRequiredAccountType;
+ pi.overlayTarget = p.mOverlayTarget;
pi.firstInstallTime = firstInstallTime;
pi.lastUpdateTime = lastUpdateTime;
if ((flags&PackageManager.GET_GIDS) != 0) {
@@ -490,6 +491,11 @@
public Package parsePackage(File sourceFile, String destCodePath,
DisplayMetrics metrics, int flags) {
+ return parsePackage(sourceFile, destCodePath, metrics, flags, false);
+ }
+
+ public Package parsePackage(File sourceFile, String destCodePath,
+ DisplayMetrics metrics, int flags, boolean trustedOverlay) {
mParseError = PackageManager.INSTALL_SUCCEEDED;
mArchiveSourcePath = sourceFile.getPath();
@@ -542,7 +548,7 @@
Exception errorException = null;
try {
// XXXX todo: need to figure out correct configuration.
- pkg = parsePackage(res, parser, flags, errorText);
+ pkg = parsePackage(res, parser, flags, trustedOverlay, errorText);
} catch (Exception e) {
errorException = e;
mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
@@ -951,8 +957,8 @@
}
private Package parsePackage(
- Resources res, XmlResourceParser parser, int flags, String[] outError)
- throws XmlPullParserException, IOException {
+ Resources res, XmlResourceParser parser, int flags, boolean trustedOverlay,
+ String[] outError) throws XmlPullParserException, IOException {
AttributeSet attrs = parser;
mParseInstrumentationArgs = null;
@@ -1051,6 +1057,31 @@
if (!parseApplication(pkg, res, parser, attrs, flags, outError)) {
return null;
}
+ } else if (tagName.equals("overlay")) {
+ pkg.mTrustedOverlay = trustedOverlay;
+
+ sa = res.obtainAttributes(attrs,
+ com.android.internal.R.styleable.AndroidManifestResourceOverlay);
+ pkg.mOverlayTarget = sa.getString(
+ com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage);
+ pkg.mOverlayPriority = sa.getInt(
+ com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority,
+ -1);
+ sa.recycle();
+
+ if (pkg.mOverlayTarget == null) {
+ outError[0] = "<overlay> does not specify a target package";
+ mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+ return null;
+ }
+ if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) {
+ outError[0] = "<overlay> priority must be between 0 and 9999";
+ mParseError =
+ PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+ return null;
+ }
+ XmlUtils.skipCurrentTag(parser);
+
} else if (tagName.equals("keys")) {
if (!parseKeys(pkg, res, parser, attrs, outError)) {
return null;
@@ -3546,6 +3577,10 @@
*/
public ManifestDigest manifestDigest;
+ public String mOverlayTarget;
+ public int mOverlayPriority;
+ public boolean mTrustedOverlay;
+
/**
* Data used to feed the KeySetManager
*/
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 780c4be..418bdda 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -90,7 +90,7 @@
mNumRefs = 0;
incRefsLocked(this.hashCode());
}
- init();
+ init(false);
if (localLOGV) Log.v(TAG, "New asset manager: " + this);
ensureSystemAssets();
}
@@ -113,7 +113,7 @@
incRefsLocked(this.hashCode());
}
}
- init();
+ init(true);
if (localLOGV) Log.v(TAG, "New asset manager: " + this);
}
@@ -615,6 +615,16 @@
private native final int addAssetPathNative(String path);
+ /**
+ * Add a set of assets to overlay an already added set of assets.
+ *
+ * This is only intended for application resources. System wide resources
+ * are handled before any Java code is executed.
+ *
+ * {@hide}
+ */
+ public native final int addOverlayPath(String idmapPath);
+
/**
* Add multiple sets of assets to the asset manager at once. See
* {@link #addAssetPath(String)} for more information. Returns array of
@@ -752,7 +762,7 @@
private native final int[] getArrayStringInfo(int arrayRes);
/*package*/ native final int[] getArrayIntResource(int arrayRes);
- private native final void init();
+ private native final void init(boolean isSystem);
private native final void destroy();
private final void incRefsLocked(long id) {
diff --git a/core/java/android/emoji/EmojiFactory.java b/core/java/android/emoji/EmojiFactory.java
index 8fd8695..aba990d 100644
--- a/core/java/android/emoji/EmojiFactory.java
+++ b/core/java/android/emoji/EmojiFactory.java
@@ -54,7 +54,7 @@
}
// A pointer to native EmojiFactory object.
- private int mNativeEmojiFactory;
+ private long mNativeEmojiFactory;
private String mName;
// Cache.
private Map<Integer, WeakReference<Bitmap>> mCache;
@@ -68,7 +68,7 @@
*
* This can be called from JNI code.
*/
- private EmojiFactory(int nativeEmojiFactory, String name) {
+ private EmojiFactory(long nativeEmojiFactory, String name) {
mNativeEmojiFactory = nativeEmojiFactory;
mName = name;
mCache = new CustomLinkedHashMap<Integer, WeakReference<Bitmap>>();
@@ -272,18 +272,18 @@
// native methods
- private native void nativeDestructor(int factory);
- private native Bitmap nativeGetBitmapFromAndroidPua(int nativeEmojiFactory, int AndroidPua);
- private native int nativeGetAndroidPuaFromVendorSpecificSjis(int nativeEmojiFactory,
+ private native void nativeDestructor(long nativeEmojiFactory);
+ private native Bitmap nativeGetBitmapFromAndroidPua(long nativeEmojiFactory, int AndroidPua);
+ private native int nativeGetAndroidPuaFromVendorSpecificSjis(long nativeEmojiFactory,
char sjis);
- private native int nativeGetVendorSpecificSjisFromAndroidPua(int nativeEmojiFactory,
+ private native int nativeGetVendorSpecificSjisFromAndroidPua(long nativeEmojiFactory,
int pua);
- private native int nativeGetAndroidPuaFromVendorSpecificPua(int nativeEmojiFactory,
+ private native int nativeGetAndroidPuaFromVendorSpecificPua(long nativeEmojiFactory,
int vsp);
- private native int nativeGetVendorSpecificPuaFromAndroidPua(int nativeEmojiFactory,
+ private native int nativeGetVendorSpecificPuaFromAndroidPua(long nativeEmojiFactory,
int pua);
- private native int nativeGetMaximumVendorSpecificPua(int nativeEmojiFactory);
- private native int nativeGetMinimumVendorSpecificPua(int nativeEmojiFactory);
- private native int nativeGetMaximumAndroidPua(int nativeEmojiFactory);
- private native int nativeGetMinimumAndroidPua(int nativeEmojiFactory);
+ private native int nativeGetMaximumVendorSpecificPua(long nativeEmojiFactory);
+ private native int nativeGetMinimumVendorSpecificPua(long nativeEmojiFactory);
+ private native int nativeGetMaximumAndroidPua(long nativeEmojiFactory);
+ private native int nativeGetMinimumAndroidPua(long nativeEmojiFactory);
}
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 6716098..3470790 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -1246,9 +1246,6 @@
} else if (v instanceof Parcelable[]) {
writeInt(VAL_PARCELABLEARRAY);
writeParcelableArray((Parcelable[]) v, 0);
- } else if (v instanceof Object[]) {
- writeInt(VAL_OBJECTARRAY);
- writeArray((Object[]) v);
} else if (v instanceof int[]) {
writeInt(VAL_INTARRAY);
writeIntArray((int[]) v);
@@ -1258,12 +1255,20 @@
} else if (v instanceof Byte) {
writeInt(VAL_BYTE);
writeInt((Byte) v);
- } else if (v instanceof Serializable) {
- // Must be last
- writeInt(VAL_SERIALIZABLE);
- writeSerializable((Serializable) v);
} else {
- throw new RuntimeException("Parcel: unable to marshal value " + v);
+ Class<?> clazz = v.getClass();
+ if (clazz.isArray() && clazz.getComponentType() == Object.class) {
+ // Only pure Object[] are written here, Other arrays of non-primitive types are
+ // handled by serialization as this does not record the component type.
+ writeInt(VAL_OBJECTARRAY);
+ writeArray((Object[]) v);
+ } else if (v instanceof Serializable) {
+ // Must be last
+ writeInt(VAL_SERIALIZABLE);
+ writeSerializable((Serializable) v);
+ } else {
+ throw new RuntimeException("Parcel: unable to marshal value " + v);
+ }
}
}
diff --git a/core/jni/android/graphics/pdf/PdfDocument.cpp b/core/jni/android/graphics/pdf/PdfDocument.cpp
index 6175a8f..d54aaa8 100644
--- a/core/jni/android/graphics/pdf/PdfDocument.cpp
+++ b/core/jni/android/graphics/pdf/PdfDocument.cpp
@@ -113,24 +113,24 @@
PageRecord* mCurrentPage;
};
-static jint nativeCreateDocument(JNIEnv* env, jobject thiz) {
- return reinterpret_cast<jint>(new PdfDocument());
+static jlong nativeCreateDocument(JNIEnv* env, jobject thiz) {
+ return reinterpret_cast<jlong>(new PdfDocument());
}
-static jint nativeStartPage(JNIEnv* env, jobject thiz, jint documentPtr,
+static jlong nativeStartPage(JNIEnv* env, jobject thiz, jlong documentPtr,
jint pageWidth, jint pageHeight,
jint contentLeft, jint contentTop, jint contentRight, jint contentBottom) {
PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
- return reinterpret_cast<jint>(document->startPage(pageWidth, pageHeight,
+ return reinterpret_cast<jlong>(document->startPage(pageWidth, pageHeight,
contentLeft, contentTop, contentRight, contentBottom));
}
-static void nativeFinishPage(JNIEnv* env, jobject thiz, jint documentPtr) {
+static void nativeFinishPage(JNIEnv* env, jobject thiz, jlong documentPtr) {
PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
document->finishPage();
}
-static void nativeWriteTo(JNIEnv* env, jobject thiz, jint documentPtr, jobject out,
+static void nativeWriteTo(JNIEnv* env, jobject thiz, jlong documentPtr, jobject out,
jbyteArray chunk) {
PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
SkWStream* skWStream = CreateJavaOutputStreamAdaptor(env, out, chunk);
@@ -138,17 +138,17 @@
delete skWStream;
}
-static void nativeClose(JNIEnv* env, jobject thiz, jint documentPtr) {
+static void nativeClose(JNIEnv* env, jobject thiz, jlong documentPtr) {
PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
document->close();
}
static JNINativeMethod gPdfDocument_Methods[] = {
- {"nativeCreateDocument", "()I", (void*) nativeCreateDocument},
- {"nativeStartPage", "(IIIIIII)I", (void*) nativeStartPage},
- {"nativeFinishPage", "(I)V", (void*) nativeFinishPage},
- {"nativeWriteTo", "(ILjava/io/OutputStream;[B)V", (void*) nativeWriteTo},
- {"nativeClose", "(I)V", (void*) nativeClose}
+ {"nativeCreateDocument", "()J", (void*) nativeCreateDocument},
+ {"nativeStartPage", "(JIIIIII)J", (void*) nativeStartPage},
+ {"nativeFinishPage", "(J)V", (void*) nativeFinishPage},
+ {"nativeWriteTo", "(JLjava/io/OutputStream;[B)V", (void*) nativeWriteTo},
+ {"nativeClose", "(J)V", (void*) nativeClose}
};
int register_android_graphics_pdf_PdfDocument(JNIEnv* env) {
diff --git a/core/jni/android_database_SQLiteGlobal.cpp b/core/jni/android_database_SQLiteGlobal.cpp
index acc2276..89d64fa 100644
--- a/core/jni/android_database_SQLiteGlobal.cpp
+++ b/core/jni/android_database_SQLiteGlobal.cpp
@@ -39,7 +39,7 @@
bool verboseLog = !!data;
if (iErrCode == 0 || iErrCode == SQLITE_CONSTRAINT || iErrCode == SQLITE_SCHEMA) {
if (verboseLog) {
- ALOGV(LOG_VERBOSE, SQLITE_LOG_TAG, "(%d) %s\n", iErrCode, zMsg);
+ ALOG(LOG_VERBOSE, SQLITE_LOG_TAG, "(%d) %s\n", iErrCode, zMsg);
}
} else {
ALOG(LOG_ERROR, SQLITE_LOG_TAG, "(%d) %s\n", iErrCode, zMsg);
diff --git a/core/jni/android_emoji_EmojiFactory.cpp b/core/jni/android_emoji_EmojiFactory.cpp
index 5276934..f127d29 100644
--- a/core/jni/android_emoji_EmojiFactory.cpp
+++ b/core/jni/android_emoji_EmojiFactory.cpp
@@ -104,7 +104,7 @@
static jobject create_java_EmojiFactory(
JNIEnv* env, EmojiFactory* factory, jstring name) {
jobject obj = env->NewObject(gEmojiFactory_class, gEmojiFactory_constructorMethodID,
- static_cast<jint>(reinterpret_cast<uintptr_t>(factory)), name);
+ reinterpret_cast<jlong>(factory), name);
if (env->ExceptionCheck() != 0) {
ALOGE("*** Uncaught exception returned from Java call!\n");
env->ExceptionDescribe();
@@ -155,7 +155,7 @@
}
static jobject android_emoji_EmojiFactory_getBitmapFromAndroidPua(
- JNIEnv* env, jobject clazz, jint nativeEmojiFactory, jint pua) {
+ JNIEnv* env, jobject clazz, jlong nativeEmojiFactory, jint pua) {
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
int size;
@@ -175,7 +175,7 @@
}
static void android_emoji_EmojiFactory_destructor(
- JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
+ JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
/*
// Must not delete this object!!
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
@@ -184,49 +184,49 @@
}
static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis(
- JNIEnv* env, jobject obj, jint nativeEmojiFactory, jchar sjis) {
+ JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jchar sjis) {
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
return factory->GetAndroidPuaFromVendorSpecificSjis(sjis);
}
static jint android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua(
- JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint pua) {
+ JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jint pua) {
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
return factory->GetVendorSpecificSjisFromAndroidPua(pua);
}
static jint android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua(
- JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint vsu) {
+ JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jint vsu) {
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
return factory->GetAndroidPuaFromVendorSpecificPua(vsu);
}
static jint android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua(
- JNIEnv* env, jobject obj, jint nativeEmojiFactory, jint pua) {
+ JNIEnv* env, jobject obj, jlong nativeEmojiFactory, jint pua) {
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
return factory->GetVendorSpecificPuaFromAndroidPua(pua);
}
static jint android_emoji_EmojiFactory_getMaximumVendorSpecificPua(
- JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
+ JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
return factory->GetMaximumVendorSpecificPua();
}
static jint android_emoji_EmojiFactory_getMinimumVendorSpecificPua(
- JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
+ JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
return factory->GetMinimumVendorSpecificPua();
}
static jint android_emoji_EmojiFactory_getMaximumAndroidPua(
- JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
+ JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
return factory->GetMaximumAndroidPua();
}
static jint android_emoji_EmojiFactory_getMinimumAndroidPua(
- JNIEnv* env, jobject obj, jint nativeEmojiFactory) {
+ JNIEnv* env, jobject obj, jlong nativeEmojiFactory) {
EmojiFactory *factory = reinterpret_cast<EmojiFactory *>(nativeEmojiFactory);
return factory->GetMinimumAndroidPua();
}
@@ -236,25 +236,25 @@
(void*)android_emoji_EmojiFactory_newInstance},
{ "newAvailableInstance", "()Landroid/emoji/EmojiFactory;",
(void*)android_emoji_EmojiFactory_newAvailableInstance},
- { "nativeDestructor", "(I)V",
+ { "nativeDestructor", "(J)V",
(void*)android_emoji_EmojiFactory_destructor},
- { "nativeGetBitmapFromAndroidPua", "(II)Landroid/graphics/Bitmap;",
+ { "nativeGetBitmapFromAndroidPua", "(JI)Landroid/graphics/Bitmap;",
(void*)android_emoji_EmojiFactory_getBitmapFromAndroidPua},
- { "nativeGetAndroidPuaFromVendorSpecificSjis", "(IC)I",
+ { "nativeGetAndroidPuaFromVendorSpecificSjis", "(JC)I",
(void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificSjis},
- { "nativeGetVendorSpecificSjisFromAndroidPua", "(II)I",
+ { "nativeGetVendorSpecificSjisFromAndroidPua", "(JI)I",
(void*)android_emoji_EmojiFactory_getVendorSpecificSjisFromAndroidPua},
- { "nativeGetAndroidPuaFromVendorSpecificPua", "(II)I",
+ { "nativeGetAndroidPuaFromVendorSpecificPua", "(JI)I",
(void*)android_emoji_EmojiFactory_getAndroidPuaFromVendorSpecificPua},
- { "nativeGetVendorSpecificPuaFromAndroidPua", "(II)I",
+ { "nativeGetVendorSpecificPuaFromAndroidPua", "(JI)I",
(void*)android_emoji_EmojiFactory_getVendorSpecificPuaFromAndroidPua},
- { "nativeGetMaximumVendorSpecificPua", "(I)I",
+ { "nativeGetMaximumVendorSpecificPua", "(J)I",
(void*)android_emoji_EmojiFactory_getMaximumVendorSpecificPua},
- { "nativeGetMinimumVendorSpecificPua", "(I)I",
+ { "nativeGetMinimumVendorSpecificPua", "(J)I",
(void*)android_emoji_EmojiFactory_getMinimumVendorSpecificPua},
- { "nativeGetMaximumAndroidPua", "(I)I",
+ { "nativeGetMaximumAndroidPua", "(J)I",
(void*)android_emoji_EmojiFactory_getMaximumAndroidPua},
- { "nativeGetMinimumAndroidPua", "(I)I",
+ { "nativeGetMinimumAndroidPua", "(J)I",
(void*)android_emoji_EmojiFactory_getMinimumAndroidPua}
};
@@ -276,7 +276,7 @@
int register_android_emoji_EmojiFactory(JNIEnv* env) {
gEmojiFactory_class = make_globalref(env, "android/emoji/EmojiFactory");
gEmojiFactory_constructorMethodID = env->GetMethodID(
- gEmojiFactory_class, "<init>", "(ILjava/lang/String;)V");
+ gEmojiFactory_class, "<init>", "(JLjava/lang/String;)V");
return jniRegisterNativeMethods(env, "android/emoji/EmojiFactory",
gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android_os_SELinux.cpp b/core/jni/android_os_SELinux.cpp
index 2b85fef..db84d000 100644
--- a/core/jni/android_os_SELinux.cpp
+++ b/core/jni/android_os_SELinux.cpp
@@ -411,7 +411,7 @@
ScopedUtfChars pathname(env, pathnameStr);
if (pathname.c_str() == NULL) {
- ALOGV("restorecon(%p) => threw exception", pathname);
+ ALOGV("restorecon(%p) => threw exception", pathnameStr);
return false;
}
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index f96aef8..7162a1c 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -35,7 +35,16 @@
#include <androidfw/AssetManager.h>
#include <androidfw/ResourceTypes.h>
+#include <private/android_filesystem_config.h> // for AID_SYSTEM
+
#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <linux/capability.h>
+extern "C" int capget(cap_user_header_t hdrp, cap_user_data_t datap);
+extern "C" int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
+
namespace android {
@@ -100,6 +109,63 @@
return block;
}
+// This is called by zygote (running as user root) as part of preloadResources.
+static void verifySystemIdmaps()
+{
+ pid_t pid;
+ char system_id[10];
+
+ snprintf(system_id, sizeof(system_id), "%d", AID_SYSTEM);
+
+ switch (pid = fork()) {
+ case -1:
+ ALOGE("failed to fork for idmap: %s", strerror(errno));
+ break;
+ case 0: // child
+ {
+ struct __user_cap_header_struct capheader;
+ struct __user_cap_data_struct capdata;
+
+ memset(&capheader, 0, sizeof(capheader));
+ memset(&capdata, 0, sizeof(capdata));
+
+ capheader.version = _LINUX_CAPABILITY_VERSION;
+ capheader.pid = 0;
+
+ if (capget(&capheader, &capdata) != 0) {
+ ALOGE("capget: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ capdata.effective = capdata.permitted;
+ if (capset(&capheader, &capdata) != 0) {
+ ALOGE("capset: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ if (setgid(AID_SYSTEM) != 0) {
+ ALOGE("setgid: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ if (setuid(AID_SYSTEM) != 0) {
+ ALOGE("setuid: %s\n", strerror(errno));
+ exit(1);
+ }
+
+ execl(AssetManager::IDMAP_BIN, AssetManager::IDMAP_BIN, "--scan",
+ AssetManager::OVERLAY_DIR, AssetManager::TARGET_PACKAGE_NAME,
+ AssetManager::TARGET_APK_PATH, AssetManager::IDMAP_DIR, (char*)NULL);
+ ALOGE("failed to execl for idmap: %s", strerror(errno));
+ exit(1); // should never get here
+ }
+ break;
+ default: // parent
+ waitpid(pid, NULL, 0);
+ break;
+ }
+}
+
// ----------------------------------------------------------------------------
// this guy is exported to other jni routines
@@ -444,6 +510,25 @@
return (res) ? static_cast<jint>(cookie) : 0;
}
+static jint android_content_AssetManager_addOverlayPath(JNIEnv* env, jobject clazz,
+ jstring idmapPath)
+{
+ ScopedUtfChars idmapPath8(env, idmapPath);
+ if (idmapPath8.c_str() == NULL) {
+ return 0;
+ }
+
+ AssetManager* am = assetManagerForJavaObject(env, clazz);
+ if (am == NULL) {
+ return 0;
+ }
+
+ int32_t cookie;
+ bool res = am->addOverlayPath(String8(idmapPath8.c_str()), &cookie);
+
+ return (res) ? (jint)cookie : 0;
+}
+
static jboolean android_content_AssetManager_isUpToDate(JNIEnv* env, jobject clazz)
{
AssetManager* am = assetManagerForJavaObject(env, clazz);
@@ -1579,8 +1664,11 @@
return array;
}
-static void android_content_AssetManager_init(JNIEnv* env, jobject clazz)
+static void android_content_AssetManager_init(JNIEnv* env, jobject clazz, jboolean isSystem)
{
+ if (isSystem) {
+ verifySystemIdmaps();
+ }
AssetManager* am = new AssetManager();
if (am == NULL) {
jniThrowException(env, "java/lang/OutOfMemoryError", "");
@@ -1658,6 +1746,8 @@
(void*) android_content_AssetManager_getAssetRemainingLength },
{ "addAssetPathNative", "(Ljava/lang/String;)I",
(void*) android_content_AssetManager_addAssetPath },
+ { "addOverlayPath", "(Ljava/lang/String;)I",
+ (void*) android_content_AssetManager_addOverlayPath },
{ "isUpToDate", "()Z",
(void*) android_content_AssetManager_isUpToDate },
@@ -1724,7 +1814,7 @@
(void*) android_content_AssetManager_getArrayIntResource },
// Bookkeeping.
- { "init", "()V",
+ { "init", "(Z)V",
(void*) android_content_AssetManager_init },
{ "destroy", "()V",
(void*) android_content_AssetManager_destroy },
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index a0982bd..3035d15 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -50,36 +50,41 @@
static inline EGLDisplay getDisplay(JNIEnv* env, jobject o) {
if (!o) return EGL_NO_DISPLAY;
- return (EGLDisplay)env->GetIntField(o, gDisplay_EGLDisplayFieldID);
+ return (EGLDisplay)env->GetLongField(o, gDisplay_EGLDisplayFieldID);
}
static inline EGLSurface getSurface(JNIEnv* env, jobject o) {
if (!o) return EGL_NO_SURFACE;
- return (EGLSurface)env->GetIntField(o, gSurface_EGLSurfaceFieldID);
+ return (EGLSurface)env->GetLongField(o, gSurface_EGLSurfaceFieldID);
}
static inline EGLContext getContext(JNIEnv* env, jobject o) {
if (!o) return EGL_NO_CONTEXT;
- return (EGLContext)env->GetIntField(o, gContext_EGLContextFieldID);
+ return (EGLContext)env->GetLongField(o, gContext_EGLContextFieldID);
}
static inline EGLConfig getConfig(JNIEnv* env, jobject o) {
if (!o) return 0;
- return (EGLConfig)env->GetIntField(o, gConfig_EGLConfigFieldID);
+ return (EGLConfig)env->GetLongField(o, gConfig_EGLConfigFieldID);
}
+
+static inline jboolean EglBoolToJBool(EGLBoolean eglBool) {
+ return eglBool == EGL_TRUE ? JNI_TRUE : JNI_FALSE;
+}
+
static void nativeClassInit(JNIEnv *_env, jclass eglImplClass)
{
jclass config_class = _env->FindClass("com/google/android/gles_jni/EGLConfigImpl");
gConfig_class = (jclass) _env->NewGlobalRef(config_class);
- gConfig_ctorID = _env->GetMethodID(gConfig_class, "<init>", "(I)V");
- gConfig_EGLConfigFieldID = _env->GetFieldID(gConfig_class, "mEGLConfig", "I");
+ gConfig_ctorID = _env->GetMethodID(gConfig_class, "<init>", "(J)V");
+ gConfig_EGLConfigFieldID = _env->GetFieldID(gConfig_class, "mEGLConfig", "J");
jclass display_class = _env->FindClass("com/google/android/gles_jni/EGLDisplayImpl");
- gDisplay_EGLDisplayFieldID = _env->GetFieldID(display_class, "mEGLDisplay", "I");
+ gDisplay_EGLDisplayFieldID = _env->GetFieldID(display_class, "mEGLDisplay", "J");
jclass context_class = _env->FindClass("com/google/android/gles_jni/EGLContextImpl");
- gContext_EGLContextFieldID = _env->GetFieldID(context_class, "mEGLContext", "I");
+ gContext_EGLContextFieldID = _env->GetFieldID(context_class, "mEGLContext", "J");
jclass surface_class = _env->FindClass("com/google/android/gles_jni/EGLSurfaceImpl");
- gSurface_EGLSurfaceFieldID = _env->GetFieldID(surface_class, "mEGLSurface", "I");
- gSurface_NativePixelRefFieldID = _env->GetFieldID(surface_class, "mNativePixelRef", "I");
+ gSurface_EGLSurfaceFieldID = _env->GetFieldID(surface_class, "mEGLSurface", "J");
+ gSurface_NativePixelRefFieldID = _env->GetFieldID(surface_class, "mNativePixelRef", "J");
jclass bitmap_class = _env->FindClass("android/graphics/Bitmap");
gBitmap_NativeBitmapFieldID = _env->GetFieldID(bitmap_class, "mNativeBitmap", "J");
@@ -123,7 +128,7 @@
}
EGLDisplay dpy = getDisplay(_env, display);
- jboolean success = eglInitialize(dpy, NULL, NULL);
+ EGLBoolean success = eglInitialize(dpy, NULL, NULL);
if (success && major_minor) {
int len = _env->GetArrayLength(major_minor);
if (len) {
@@ -134,7 +139,7 @@
_env->ReleasePrimitiveArrayCritical(major_minor, base, JNI_ABORT);
}
}
- return success;
+ return EglBoolToJBool(success);
}
static jboolean jni_eglQueryContext(JNIEnv *_env, jobject _this, jobject display,
@@ -146,14 +151,14 @@
}
EGLDisplay dpy = getDisplay(_env, display);
EGLContext ctx = getContext(_env, context);
- jboolean success = JNI_FALSE;
+ EGLBoolean success = EGL_FALSE;
int len = _env->GetArrayLength(value);
if (len) {
jint* base = (jint *)_env->GetPrimitiveArrayCritical(value, (jboolean *)0);
success = eglQueryContext(dpy, ctx, attribute, base);
_env->ReleasePrimitiveArrayCritical(value, base, JNI_ABORT);
}
- return success;
+ return EglBoolToJBool(success);
}
static jboolean jni_eglQuerySurface(JNIEnv *_env, jobject _this, jobject display,
@@ -166,14 +171,14 @@
EGLDisplay dpy = getDisplay(_env, display);
EGLContext sur = getSurface(_env, surface);
- jboolean success = JNI_FALSE;
+ EGLBoolean success = EGL_FALSE;
int len = _env->GetArrayLength(value);
if (len) {
jint* base = (jint *)_env->GetPrimitiveArrayCritical(value, (jboolean *)0);
success = eglQuerySurface(dpy, sur, attribute, base);
_env->ReleasePrimitiveArrayCritical(value, base, JNI_ABORT);
}
- return success;
+ return EglBoolToJBool(success);
}
static jint jni_getInitCount(JNIEnv *_env, jobject _clazz, jobject display) {
@@ -183,7 +188,7 @@
}
static jboolean jni_eglReleaseThread(JNIEnv *_env, jobject _this) {
- return eglReleaseThread();
+ return EglBoolToJBool(eglReleaseThread());
}
static jboolean jni_eglChooseConfig(JNIEnv *_env, jobject _this, jobject display,
@@ -196,7 +201,7 @@
return JNI_FALSE;
}
EGLDisplay dpy = getDisplay(_env, display);
- jboolean success = JNI_FALSE;
+ EGLBoolean success = EGL_FALSE;
if (configs == NULL) {
config_size = 0;
@@ -214,14 +219,14 @@
if (success && configs!=NULL) {
for (int i=0 ; i<num ; i++) {
- jobject obj = _env->NewObject(gConfig_class, gConfig_ctorID, (jint)nativeConfigs[i]);
+ jobject obj = _env->NewObject(gConfig_class, gConfig_ctorID, reinterpret_cast<jlong>(nativeConfigs[i]));
_env->SetObjectArrayElement(configs, i, obj);
}
}
- return success;
+ return EglBoolToJBool(success);
}
-static jint jni_eglCreateContext(JNIEnv *_env, jobject _this, jobject display,
+static jlong jni_eglCreateContext(JNIEnv *_env, jobject _this, jobject display,
jobject config, jobject share_context, jintArray attrib_list) {
if (display == NULL || config == NULL || share_context == NULL
|| !validAttribList(_env, attrib_list)) {
@@ -234,10 +239,10 @@
jint* base = beginNativeAttribList(_env, attrib_list);
EGLContext ctx = eglCreateContext(dpy, cnf, shr, base);
endNativeAttributeList(_env, attrib_list, base);
- return (jint)ctx;
+ return reinterpret_cast<jlong>(ctx);
}
-static jint jni_eglCreatePbufferSurface(JNIEnv *_env, jobject _this, jobject display,
+static jlong jni_eglCreatePbufferSurface(JNIEnv *_env, jobject _this, jobject display,
jobject config, jintArray attrib_list) {
if (display == NULL || config == NULL
|| !validAttribList(_env, attrib_list)) {
@@ -249,7 +254,7 @@
jint* base = beginNativeAttribList(_env, attrib_list);
EGLSurface sur = eglCreatePbufferSurface(dpy, cnf, base);
endNativeAttributeList(_env, attrib_list, base);
- return (jint)sur;
+ return reinterpret_cast<jlong>(sur);
}
static PixelFormat convertPixelFormat(SkBitmap::Config format)
@@ -300,15 +305,15 @@
endNativeAttributeList(_env, attrib_list, base);
if (sur != EGL_NO_SURFACE) {
- _env->SetIntField(out_sur, gSurface_EGLSurfaceFieldID, (int)sur);
- _env->SetIntField(out_sur, gSurface_NativePixelRefFieldID, (int)ref);
+ _env->SetLongField(out_sur, gSurface_EGLSurfaceFieldID, reinterpret_cast<jlong>(sur));
+ _env->SetLongField(out_sur, gSurface_NativePixelRefFieldID, reinterpret_cast<jlong>(ref));
} else {
ref->unlockPixels();
SkSafeUnref(ref);
}
}
-static jint jni_eglCreateWindowSurface(JNIEnv *_env, jobject _this, jobject display,
+static jlong jni_eglCreateWindowSurface(JNIEnv *_env, jobject _this, jobject display,
jobject config, jobject native_window, jintArray attrib_list) {
if (display == NULL || config == NULL
|| !validAttribList(_env, attrib_list)) {
@@ -332,15 +337,15 @@
jint* base = beginNativeAttribList(_env, attrib_list);
EGLSurface sur = eglCreateWindowSurface(dpy, cnf, window.get(), base);
endNativeAttributeList(_env, attrib_list, base);
- return (jint)sur;
+ return reinterpret_cast<jlong>(sur);
}
-static jint jni_eglCreateWindowSurfaceTexture(JNIEnv *_env, jobject _this, jobject display,
+static jlong jni_eglCreateWindowSurfaceTexture(JNIEnv *_env, jobject _this, jobject display,
jobject config, jobject native_window, jintArray attrib_list) {
if (display == NULL || config == NULL
|| !validAttribList(_env, attrib_list)) {
jniThrowException(_env, "java/lang/IllegalArgumentException", NULL);
- return JNI_FALSE;
+ return 0;
}
EGLDisplay dpy = getDisplay(_env, display);
EGLContext cnf = getConfig(_env, config);
@@ -360,7 +365,7 @@
jint* base = beginNativeAttribList(_env, attrib_list);
EGLSurface sur = eglCreateWindowSurface(dpy, cnf, window.get(), base);
endNativeAttributeList(_env, attrib_list, base);
- return (jint)sur;
+ return reinterpret_cast<jlong>(sur);
}
static jboolean jni_eglGetConfigAttrib(JNIEnv *_env, jobject _this, jobject display,
@@ -372,13 +377,13 @@
}
EGLDisplay dpy = getDisplay(_env, display);
EGLContext cnf = getConfig(_env, config);
- jboolean success = JNI_FALSE;
+ EGLBoolean success = EGL_FALSE;
jint localValue;
success = eglGetConfigAttrib(dpy, cnf, attribute, &localValue);
if (success) {
_env->SetIntArrayRegion(value, 0, 1, &localValue);
}
- return success;
+ return EglBoolToJBool(success);
}
static jboolean jni_eglGetConfigs(JNIEnv *_env, jobject _this, jobject display,
@@ -389,7 +394,7 @@
return JNI_FALSE;
}
EGLDisplay dpy = getDisplay(_env, display);
- jboolean success = JNI_FALSE;
+ EGLBoolean success = EGL_FALSE;
if (configs == NULL) {
config_size = 0;
}
@@ -401,11 +406,11 @@
}
if (success && configs) {
for (int i=0 ; i<num ; i++) {
- jobject obj = _env->NewObject(gConfig_class, gConfig_ctorID, (jint)nativeConfigs[i]);
+ jobject obj = _env->NewObject(gConfig_class, gConfig_ctorID, reinterpret_cast<jlong>(nativeConfigs[i]));
_env->SetObjectArrayElement(configs, i, obj);
}
}
- return success;
+ return EglBoolToJBool(success);
}
static jint jni_eglGetError(JNIEnv *_env, jobject _this) {
@@ -413,20 +418,20 @@
return error;
}
-static jint jni_eglGetCurrentContext(JNIEnv *_env, jobject _this) {
- return (jint)eglGetCurrentContext();
+static jlong jni_eglGetCurrentContext(JNIEnv *_env, jobject _this) {
+ return reinterpret_cast<jlong>(eglGetCurrentContext());
}
-static jint jni_eglGetCurrentDisplay(JNIEnv *_env, jobject _this) {
- return (jint)eglGetCurrentDisplay();
+static jlong jni_eglGetCurrentDisplay(JNIEnv *_env, jobject _this) {
+ return reinterpret_cast<jlong>(eglGetCurrentDisplay());
}
-static jint jni_eglGetCurrentSurface(JNIEnv *_env, jobject _this, jint readdraw) {
+static jlong jni_eglGetCurrentSurface(JNIEnv *_env, jobject _this, jint readdraw) {
if ((readdraw != EGL_READ) && (readdraw != EGL_DRAW)) {
jniThrowException(_env, "java/lang/IllegalArgumentException", NULL);
return 0;
}
- return (jint)eglGetCurrentSurface(readdraw);
+ return reinterpret_cast<jlong>(eglGetCurrentSurface(readdraw));
}
static jboolean jni_eglDestroyContext(JNIEnv *_env, jobject _this, jobject display, jobject context) {
@@ -436,7 +441,7 @@
}
EGLDisplay dpy = getDisplay(_env, display);
EGLContext ctx = getContext(_env, context);
- return eglDestroyContext(dpy, ctx);
+ return EglBoolToJBool(eglDestroyContext(dpy, ctx));
}
static jboolean jni_eglDestroySurface(JNIEnv *_env, jobject _this, jobject display, jobject surface) {
@@ -448,18 +453,18 @@
EGLSurface sur = getSurface(_env, surface);
if (sur) {
- SkPixelRef* ref = (SkPixelRef*)(_env->GetIntField(surface,
+ SkPixelRef* ref = (SkPixelRef*)(_env->GetLongField(surface,
gSurface_NativePixelRefFieldID));
if (ref) {
ref->unlockPixels();
SkSafeUnref(ref);
}
}
- return eglDestroySurface(dpy, sur);
+ return EglBoolToJBool(eglDestroySurface(dpy, sur));
}
-static jint jni_eglGetDisplay(JNIEnv *_env, jobject _this, jobject native_display) {
- return (jint)eglGetDisplay(EGL_DEFAULT_DISPLAY);
+static jlong jni_eglGetDisplay(JNIEnv *_env, jobject _this, jobject native_display) {
+ return reinterpret_cast<jlong>(eglGetDisplay(EGL_DEFAULT_DISPLAY));
}
static jboolean jni_eglMakeCurrent(JNIEnv *_env, jobject _this, jobject display, jobject draw, jobject read, jobject context) {
@@ -471,7 +476,7 @@
EGLSurface sdr = getSurface(_env, draw);
EGLSurface srd = getSurface(_env, read);
EGLContext ctx = getContext(_env, context);
- return eglMakeCurrent(dpy, sdr, srd, ctx);
+ return EglBoolToJBool(eglMakeCurrent(dpy, sdr, srd, ctx));
}
static jstring jni_eglQueryString(JNIEnv *_env, jobject _this, jobject display, jint name) {
@@ -491,7 +496,7 @@
}
EGLDisplay dpy = getDisplay(_env, display);
EGLSurface sur = getSurface(_env, surface);
- return eglSwapBuffers(dpy, sur);
+ return EglBoolToJBool(eglSwapBuffers(dpy, sur));
}
static jboolean jni_eglTerminate(JNIEnv *_env, jobject _this, jobject display) {
@@ -500,7 +505,7 @@
return JNI_FALSE;
}
EGLDisplay dpy = getDisplay(_env, display);
- return eglTerminate(dpy);
+ return EglBoolToJBool(eglTerminate(dpy));
}
static jboolean jni_eglCopyBuffers(JNIEnv *_env, jobject _this, jobject display,
@@ -514,11 +519,11 @@
}
static jboolean jni_eglWaitGL(JNIEnv *_env, jobject _this) {
- return eglWaitGL();
+ return EglBoolToJBool(eglWaitGL());
}
static jboolean jni_eglWaitNative(JNIEnv *_env, jobject _this, jint engine, jobject bindTarget) {
- return eglWaitNative(engine);
+ return EglBoolToJBool(eglWaitNative(engine));
}
@@ -540,21 +545,21 @@
{"eglReleaseThread","()Z", (void*)jni_eglReleaseThread },
{"getInitCount", "(" DISPLAY ")I", (void*)jni_getInitCount },
{"eglChooseConfig", "(" DISPLAY "[I[" CONFIG "I[I)Z", (void*)jni_eglChooseConfig },
-{"_eglCreateContext","(" DISPLAY CONFIG CONTEXT "[I)I", (void*)jni_eglCreateContext },
+{"_eglCreateContext","(" DISPLAY CONFIG CONTEXT "[I)J", (void*)jni_eglCreateContext },
{"eglGetConfigs", "(" DISPLAY "[" CONFIG "I[I)Z", (void*)jni_eglGetConfigs },
{"eglTerminate", "(" DISPLAY ")Z", (void*)jni_eglTerminate },
{"eglCopyBuffers", "(" DISPLAY SURFACE OBJECT ")Z", (void*)jni_eglCopyBuffers },
{"eglWaitNative", "(I" OBJECT ")Z", (void*)jni_eglWaitNative },
{"eglGetError", "()I", (void*)jni_eglGetError },
{"eglGetConfigAttrib", "(" DISPLAY CONFIG "I[I)Z", (void*)jni_eglGetConfigAttrib },
-{"_eglGetDisplay", "(" OBJECT ")I", (void*)jni_eglGetDisplay },
-{"_eglGetCurrentContext", "()I", (void*)jni_eglGetCurrentContext },
-{"_eglGetCurrentDisplay", "()I", (void*)jni_eglGetCurrentDisplay },
-{"_eglGetCurrentSurface", "(I)I", (void*)jni_eglGetCurrentSurface },
-{"_eglCreatePbufferSurface","(" DISPLAY CONFIG "[I)I", (void*)jni_eglCreatePbufferSurface },
+{"_eglGetDisplay", "(" OBJECT ")J", (void*)jni_eglGetDisplay },
+{"_eglGetCurrentContext", "()J", (void*)jni_eglGetCurrentContext },
+{"_eglGetCurrentDisplay", "()J", (void*)jni_eglGetCurrentDisplay },
+{"_eglGetCurrentSurface", "(I)J", (void*)jni_eglGetCurrentSurface },
+{"_eglCreatePbufferSurface","(" DISPLAY CONFIG "[I)J", (void*)jni_eglCreatePbufferSurface },
{"_eglCreatePixmapSurface", "(" SURFACE DISPLAY CONFIG OBJECT "[I)V", (void*)jni_eglCreatePixmapSurface },
-{"_eglCreateWindowSurface", "(" DISPLAY CONFIG OBJECT "[I)I", (void*)jni_eglCreateWindowSurface },
-{"_eglCreateWindowSurfaceTexture", "(" DISPLAY CONFIG OBJECT "[I)I", (void*)jni_eglCreateWindowSurfaceTexture },
+{"_eglCreateWindowSurface", "(" DISPLAY CONFIG OBJECT "[I)J", (void*)jni_eglCreateWindowSurface },
+{"_eglCreateWindowSurfaceTexture", "(" DISPLAY CONFIG OBJECT "[I)J", (void*)jni_eglCreateWindowSurfaceTexture },
{"eglDestroyContext", "(" DISPLAY CONTEXT ")Z", (void*)jni_eglDestroyContext },
{"eglDestroySurface", "(" DISPLAY SURFACE ")Z", (void*)jni_eglDestroySurface },
{"eglMakeCurrent", "(" DISPLAY SURFACE SURFACE CONTEXT")Z", (void*)jni_eglMakeCurrent },
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index b20f5ba..4647413 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1777,6 +1777,16 @@
<attr name="publicKey" />
</declare-styleable>
+ <!-- Attributes relating to resource overlay packages. -->
+ <declare-styleable name="AndroidManifestResourceOverlay" parent="AndroidManifest">
+ <!-- Package name of base package whose resources will be overlaid. -->
+ <attr name="targetPackage" />
+
+ <!-- Load order of overlay package. -->
+ <attr name="priority" />
+
+ </declare-styleable>
+
<!-- Declaration of an {@link android.content.Intent} object in XML. May
also include zero or more {@link #IntentCategory <category> and
{@link #Extra <extra>} tags. -->
diff --git a/core/tests/overlaytests/OverlayAppFirst/Android.mk b/core/tests/overlaytests/OverlayAppFirst/Android.mk
new file mode 100644
index 0000000..ee991fc
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppFirst/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_PACKAGE_NAME := com.android.overlaytest.first_app_overlay
+
+include $(BUILD_PACKAGE)
diff --git a/core/tests/overlaytests/OverlayAppFirst/AndroidManifest.xml b/core/tests/overlaytests/OverlayAppFirst/AndroidManifest.xml
new file mode 100644
index 0000000..ec10bbc
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppFirst/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.overlaytest.first_app_overlay"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <overlay android:targetPackage="com.android.overlaytest" android:priority="1"/>
+</manifest>
diff --git a/core/tests/overlaytests/OverlayTestOverlay/res/drawable-nodpi/default_wallpaper.jpg b/core/tests/overlaytests/OverlayAppFirst/res/drawable-nodpi/drawable.jpg
similarity index 100%
rename from core/tests/overlaytests/OverlayTestOverlay/res/drawable-nodpi/default_wallpaper.jpg
rename to core/tests/overlaytests/OverlayAppFirst/res/drawable-nodpi/drawable.jpg
Binary files differ
diff --git a/core/tests/overlaytests/OverlayAppFirst/res/raw/lorem_ipsum.txt b/core/tests/overlaytests/OverlayAppFirst/res/raw/lorem_ipsum.txt
new file mode 100644
index 0000000..756b0a3
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppFirst/res/raw/lorem_ipsum.txt
@@ -0,0 +1 @@
+Lorem ipsum: single overlay.
diff --git a/core/tests/overlaytests/OverlayAppFirst/res/values-sv/config.xml b/core/tests/overlaytests/OverlayAppFirst/res/values-sv/config.xml
new file mode 100644
index 0000000..9cdc73e
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppFirst/res/values-sv/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <integer name="matrix_100100">400</integer>
+ <integer name="matrix_100101">400</integer>
+ <integer name="matrix_100110">400</integer>
+ <integer name="matrix_100111">400</integer>
+ <integer name="matrix_101100">400</integer>
+ <integer name="matrix_101101">400</integer>
+ <integer name="matrix_101110">400</integer>
+ <integer name="matrix_101111">400</integer>
+ <integer name="matrix_110100">400</integer>
+ <integer name="matrix_110101">400</integer>
+ <integer name="matrix_110110">400</integer>
+ <integer name="matrix_110111">400</integer>
+ <integer name="matrix_111100">400</integer>
+ <integer name="matrix_111101">400</integer>
+ <integer name="matrix_111110">400</integer>
+ <integer name="matrix_111111">400</integer>
+</resources>
diff --git a/core/tests/overlaytests/OverlayAppFirst/res/values/config.xml b/core/tests/overlaytests/OverlayAppFirst/res/values/config.xml
new file mode 100644
index 0000000..972137a
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppFirst/res/values/config.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="str">single</string>
+ <string name="str2">single</string>
+ <integer name="matrix_101000">300</integer>
+ <integer name="matrix_101001">300</integer>
+ <integer name="matrix_101010">300</integer>
+ <integer name="matrix_101011">300</integer>
+ <integer name="matrix_101100">300</integer>
+ <integer name="matrix_101101">300</integer>
+ <integer name="matrix_101110">300</integer>
+ <integer name="matrix_101111">300</integer>
+ <integer name="matrix_111000">300</integer>
+ <integer name="matrix_111001">300</integer>
+ <integer name="matrix_111010">300</integer>
+ <integer name="matrix_111011">300</integer>
+ <integer name="matrix_111100">300</integer>
+ <integer name="matrix_111101">300</integer>
+ <integer name="matrix_111110">300</integer>
+ <integer name="matrix_111111">300</integer>
+ <bool name="usually_false">true</bool>
+ <integer-array name="fibonacci">
+ <item>21</item>
+ <item>13</item>
+ <item>8</item>
+ <item>5</item>
+ <item>3</item>
+ <item>2</item>
+ <item>1</item>
+ <item>1</item>
+ </integer-array>
+ <!-- The following integer does not exist in the original package. Idmap
+ generation should therefore ignore it. -->
+ <integer name="integer_not_in_original_package">0</integer>
+</resources>
diff --git a/core/tests/overlaytests/OverlayAppFirst/res/xml/integer.xml b/core/tests/overlaytests/OverlayAppFirst/res/xml/integer.xml
new file mode 100644
index 0000000..7f628d9
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppFirst/res/xml/integer.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<integer value="1"/>
diff --git a/core/tests/overlaytests/OverlayAppSecond/Android.mk b/core/tests/overlaytests/OverlayAppSecond/Android.mk
new file mode 100644
index 0000000..87402c43
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppSecond/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := current
+
+LOCAL_PACKAGE_NAME := com.android.overlaytest.second_app_overlay
+
+include $(BUILD_PACKAGE)
diff --git a/core/tests/overlaytests/OverlayAppSecond/AndroidManifest.xml b/core/tests/overlaytests/OverlayAppSecond/AndroidManifest.xml
new file mode 100644
index 0000000..ed49863
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppSecond/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.overlaytest.second_app_overlay"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <overlay android:targetPackage="com.android.overlaytest" android:priority="2"/>
+</manifest>
diff --git a/core/tests/overlaytests/OverlayAppSecond/res/raw/lorem_ipsum.txt b/core/tests/overlaytests/OverlayAppSecond/res/raw/lorem_ipsum.txt
new file mode 100644
index 0000000..613f5b6
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppSecond/res/raw/lorem_ipsum.txt
@@ -0,0 +1 @@
+Lorem ipsum: multiple overlays.
diff --git a/core/tests/overlaytests/OverlayAppSecond/res/values-sv/config.xml b/core/tests/overlaytests/OverlayAppSecond/res/values-sv/config.xml
new file mode 100644
index 0000000..ec4b6c0
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppSecond/res/values-sv/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <integer name="matrix_100001">600</integer>
+ <integer name="matrix_100011">600</integer>
+ <integer name="matrix_100101">600</integer>
+ <integer name="matrix_100111">600</integer>
+ <integer name="matrix_101001">600</integer>
+ <integer name="matrix_101011">600</integer>
+ <integer name="matrix_101101">600</integer>
+ <integer name="matrix_101111">600</integer>
+ <integer name="matrix_110001">600</integer>
+ <integer name="matrix_110011">600</integer>
+ <integer name="matrix_110101">600</integer>
+ <integer name="matrix_110111">600</integer>
+ <integer name="matrix_111001">600</integer>
+ <integer name="matrix_111011">600</integer>
+ <integer name="matrix_111101">600</integer>
+ <integer name="matrix_111111">600</integer>
+</resources>
diff --git a/core/tests/overlaytests/OverlayAppSecond/res/values/config.xml b/core/tests/overlaytests/OverlayAppSecond/res/values/config.xml
new file mode 100644
index 0000000..8b07216
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppSecond/res/values/config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="str">multiple</string>
+ <integer name="matrix_100010">500</integer>
+ <integer name="matrix_100011">500</integer>
+ <integer name="matrix_100110">500</integer>
+ <integer name="matrix_100111">500</integer>
+ <integer name="matrix_101010">500</integer>
+ <integer name="matrix_101011">500</integer>
+ <integer name="matrix_101110">500</integer>
+ <integer name="matrix_101111">500</integer>
+ <integer name="matrix_110010">500</integer>
+ <integer name="matrix_110011">500</integer>
+ <integer name="matrix_110110">500</integer>
+ <integer name="matrix_110111">500</integer>
+ <integer name="matrix_111010">500</integer>
+ <integer name="matrix_111011">500</integer>
+ <integer name="matrix_111110">500</integer>
+ <integer name="matrix_111111">500</integer>
+ <bool name="usually_false">false</bool>
+</resources>
diff --git a/core/tests/overlaytests/OverlayAppSecond/res/xml/integer.xml b/core/tests/overlaytests/OverlayAppSecond/res/xml/integer.xml
new file mode 100644
index 0000000..f3370a6
--- /dev/null
+++ b/core/tests/overlaytests/OverlayAppSecond/res/xml/integer.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<integer value="2"/>
diff --git a/core/tests/overlaytests/OverlayTest/Android.mk b/core/tests/overlaytests/OverlayTest/Android.mk
index f7f67f6..4767e52 100644
--- a/core/tests/overlaytests/OverlayTest/Android.mk
+++ b/core/tests/overlaytests/OverlayTest/Android.mk
@@ -5,6 +5,10 @@
LOCAL_PACKAGE_NAME := OverlayTest
+LOCAL_DEX_PREOPT := false
+
+LOCAL_MODULE_PATH := $(TARGET_OUT)/app
+
LOCAL_SRC_FILES := $(call all-java-files-under, src)
include $(BUILD_PACKAGE)
diff --git a/core/tests/overlaytests/OverlayTest/res/drawable-nodpi/drawable.jpg b/core/tests/overlaytests/OverlayTest/res/drawable-nodpi/drawable.jpg
new file mode 100644
index 0000000..a3f14f3
--- /dev/null
+++ b/core/tests/overlaytests/OverlayTest/res/drawable-nodpi/drawable.jpg
Binary files differ
diff --git a/core/tests/overlaytests/OverlayTest/res/raw/lorem_ipsum.txt b/core/tests/overlaytests/OverlayTest/res/raw/lorem_ipsum.txt
new file mode 100644
index 0000000..cee7a92
--- /dev/null
+++ b/core/tests/overlaytests/OverlayTest/res/raw/lorem_ipsum.txt
@@ -0,0 +1 @@
+Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
diff --git a/core/tests/overlaytests/OverlayTest/res/values-sv/config.xml b/core/tests/overlaytests/OverlayTest/res/values-sv/config.xml
new file mode 100644
index 0000000..891853e
--- /dev/null
+++ b/core/tests/overlaytests/OverlayTest/res/values-sv/config.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <integer name="matrix_110000">200</integer>
+ <integer name="matrix_110001">200</integer>
+ <integer name="matrix_110010">200</integer>
+ <integer name="matrix_110011">200</integer>
+ <integer name="matrix_110100">200</integer>
+ <integer name="matrix_110101">200</integer>
+ <integer name="matrix_110110">200</integer>
+ <integer name="matrix_110111">200</integer>
+ <integer name="matrix_111000">200</integer>
+ <integer name="matrix_111001">200</integer>
+ <integer name="matrix_111010">200</integer>
+ <integer name="matrix_111011">200</integer>
+ <integer name="matrix_111100">200</integer>
+ <integer name="matrix_111101">200</integer>
+ <integer name="matrix_111110">200</integer>
+ <integer name="matrix_111111">200</integer>
+</resources>
diff --git a/core/tests/overlaytests/OverlayTest/res/values/config.xml b/core/tests/overlaytests/OverlayTest/res/values/config.xml
new file mode 100644
index 0000000..c692a262
--- /dev/null
+++ b/core/tests/overlaytests/OverlayTest/res/values/config.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="str">none</string>
+ <string name="str2">none</string>
+ <integer name="matrix_100000">100</integer>
+ <integer name="matrix_100001">100</integer>
+ <integer name="matrix_100010">100</integer>
+ <integer name="matrix_100011">100</integer>
+ <integer name="matrix_100100">100</integer>
+ <integer name="matrix_100101">100</integer>
+ <integer name="matrix_100110">100</integer>
+ <integer name="matrix_100111">100</integer>
+ <integer name="matrix_101000">100</integer>
+ <integer name="matrix_101001">100</integer>
+ <integer name="matrix_101010">100</integer>
+ <integer name="matrix_101011">100</integer>
+ <integer name="matrix_101100">100</integer>
+ <integer name="matrix_101101">100</integer>
+ <integer name="matrix_101110">100</integer>
+ <integer name="matrix_101111">100</integer>
+ <integer name="matrix_110000">100</integer>
+ <integer name="matrix_110001">100</integer>
+ <integer name="matrix_110010">100</integer>
+ <integer name="matrix_110011">100</integer>
+ <integer name="matrix_110100">100</integer>
+ <integer name="matrix_110101">100</integer>
+ <integer name="matrix_110110">100</integer>
+ <integer name="matrix_110111">100</integer>
+ <integer name="matrix_111000">100</integer>
+ <integer name="matrix_111001">100</integer>
+ <integer name="matrix_111010">100</integer>
+ <integer name="matrix_111011">100</integer>
+ <integer name="matrix_111100">100</integer>
+ <integer name="matrix_111101">100</integer>
+ <integer name="matrix_111110">100</integer>
+ <integer name="matrix_111111">100</integer>
+ <bool name="usually_false">false</bool>
+ <bool name="always_true">true</bool>
+ <integer-array name="fibonacci">
+ <item>1</item>
+ <item>1</item>
+ <item>2</item>
+ <item>3</item>
+ <item>5</item>
+ <item>8</item>
+ <item>13</item>
+ <item>21</item>
+ </integer-array>
+ <integer-array name="prime_numbers">
+ <item>2</item>
+ <item>3</item>
+ <item>5</item>
+ <item>7</item>
+ <item>11</item>
+ <item>13</item>
+ <item>17</item>
+ <item>19</item>
+ </integer-array>
+</resources>
diff --git a/core/tests/overlaytests/OverlayTest/res/xml/integer.xml b/core/tests/overlaytests/OverlayTest/res/xml/integer.xml
new file mode 100644
index 0000000..9383daa
--- /dev/null
+++ b/core/tests/overlaytests/OverlayTest/res/xml/integer.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?>
+<integer value="0"/>
diff --git a/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/OverlayBaseTest.java b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/OverlayBaseTest.java
index 6211c1c..58b7db9 100644
--- a/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/OverlayBaseTest.java
+++ b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/OverlayBaseTest.java
@@ -2,13 +2,21 @@
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
import android.test.AndroidTestCase;
+import android.util.AttributeSet;
+import android.util.Xml;
+import java.io.BufferedReader;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.util.Locale;
public abstract class OverlayBaseTest extends AndroidTestCase {
private Resources mResources;
- protected boolean mWithOverlay; // will be set by subclasses
+ protected int mMode; // will be set by subclasses
+ static final protected int MODE_NO_OVERLAY = 0;
+ static final protected int MODE_SINGLE_OVERLAY = 1;
+ static final protected int MODE_MULTIPLE_OVERLAYS = 2;
protected void setUp() {
mResources = getContext().getResources();
@@ -36,20 +44,82 @@
mResources.updateConfiguration(config, mResources.getDisplayMetrics());
}
- private void assertResource(int resId, boolean ewo, boolean ew) throws Throwable {
- boolean expected = mWithOverlay ? ew : ewo;
+ private boolean getExpected(boolean no, boolean so, boolean mo) {
+ switch (mMode) {
+ case MODE_NO_OVERLAY:
+ return no;
+ case MODE_SINGLE_OVERLAY:
+ return so;
+ case MODE_MULTIPLE_OVERLAYS:
+ return mo;
+ default:
+ fail("Unknown mode!");
+ return no;
+ }
+ }
+
+ private String getExpected(String no, String so, String mo) {
+ switch (mMode) {
+ case MODE_NO_OVERLAY:
+ return no;
+ case MODE_SINGLE_OVERLAY:
+ return so;
+ case MODE_MULTIPLE_OVERLAYS:
+ return mo;
+ default:
+ fail("Unknown mode!");
+ return no;
+ }
+ }
+
+ private int getExpected(int no, int so, int mo) {
+ switch (mMode) {
+ case MODE_NO_OVERLAY:
+ return no;
+ case MODE_SINGLE_OVERLAY:
+ return so;
+ case MODE_MULTIPLE_OVERLAYS:
+ return mo;
+ default:
+ fail("Unknown mode!");
+ return no;
+ }
+ }
+
+ private int[] getExpected(int[] no, int[] so, int[] mo) {
+ switch (mMode) {
+ case MODE_NO_OVERLAY:
+ return no;
+ case MODE_SINGLE_OVERLAY:
+ return so;
+ case MODE_MULTIPLE_OVERLAYS:
+ return mo;
+ default:
+ fail("Unknown mode!");
+ return no;
+ }
+ }
+
+ private void assertResource(int resId, boolean no, boolean so, boolean mo) throws Throwable {
+ boolean expected = getExpected(no, so, mo);
boolean actual = mResources.getBoolean(resId);
assertEquals(expected, actual);
}
- private void assertResource(int resId, String ewo, String ew) throws Throwable {
- String expected = mWithOverlay ? ew : ewo;
+ private void assertResource(int resId, int no, int so, int mo) throws Throwable {
+ int expected = getExpected(no, so, mo);
+ int actual = mResources.getInteger(resId);
+ assertEquals(expected, actual);
+ }
+
+ private void assertResource(int resId, String no, String so, String mo) throws Throwable {
+ String expected = getExpected(no, so, mo);
String actual = mResources.getString(resId);
assertEquals(expected, actual);
}
- private void assertResource(int resId, int[] ewo, int[] ew) throws Throwable {
- int[] expected = mWithOverlay ? ew : ewo;
+ private void assertResource(int resId, int[] no, int[] so, int[] mo) throws Throwable {
+ int[] expected = getExpected(no, so, mo);
int[] actual = mResources.getIntArray(resId);
assertEquals("length:", expected.length, actual.length);
for (int i = 0; i < actual.length; ++i) {
@@ -57,62 +127,334 @@
}
}
+ public void testFrameworkBooleanOverlay() throws Throwable {
+ // config_annoy_dianne has the value:
+ // - true when no overlay exists (MODE_NO_OVERLAY)
+ // - false when a single overlay exists (MODE_SINGLE_OVERLAY)
+ // - false when multiple overlays exists (MODE_MULTIPLE_OVERLAYS)
+ final int resId = com.android.internal.R.bool.config_annoy_dianne;
+ assertResource(resId, true, false, false);
+ }
+
public void testBooleanOverlay() throws Throwable {
- // config_automatic_brightness_available has overlay (default config)
- final int resId = com.android.internal.R.bool.config_automatic_brightness_available;
- assertResource(resId, false, true);
+ // usually_false has the value:
+ // - false when no overlay exists (MODE_NO_OVERLAY)
+ // - true when a single overlay exists (MODE_SINGLE_OVERLAY)
+ // - false when multiple overlays exists (MODE_MULTIPLE_OVERLAYS)
+ final int resId = R.bool.usually_false;
+ assertResource(resId, false, true, false);
}
public void testBoolean() throws Throwable {
- // config_annoy_dianne has no overlay
- final int resId = com.android.internal.R.bool.config_annoy_dianne;
- assertResource(resId, true, true);
- }
-
- public void testStringOverlay() throws Throwable {
- // phoneTypeCar has an overlay (default config), which shouldn't shadow
- // the Swedish translation
- final int resId = com.android.internal.R.string.phoneTypeCar;
- setLocale("sv_SE");
- assertResource(resId, "Bil", "Bil");
- }
-
- public void testStringSwedishOverlay() throws Throwable {
- // phoneTypeWork has overlay (no default config, only for lang=sv)
- final int resId = com.android.internal.R.string.phoneTypeWork;
- setLocale("en_US");
- assertResource(resId, "Work", "Work");
- setLocale("sv_SE");
- assertResource(resId, "Arbete", "Jobb");
- }
-
- public void testString() throws Throwable {
- // phoneTypeHome has no overlay
- final int resId = com.android.internal.R.string.phoneTypeHome;
- setLocale("en_US");
- assertResource(resId, "Home", "Home");
- setLocale("sv_SE");
- assertResource(resId, "Hem", "Hem");
+ // always_true has no overlay
+ final int resId = R.bool.always_true;
+ assertResource(resId, true, true, true);
}
public void testIntegerArrayOverlay() throws Throwable {
- // config_scrollBarrierVibePattern has overlay (default config)
- final int resId = com.android.internal.R.array.config_scrollBarrierVibePattern;
- assertResource(resId, new int[]{0, 15, 10, 10}, new int[]{100, 200, 300});
+ // fibonacci has values:
+ // - eight first values of Fibonacci sequence, when no overlay exists (MODE_NO_OVERLAY)
+ // - eight first values of Fibonacci sequence (reversed), for single and multiple overlays
+ // (MODE_SINGLE_OVERLAY, MODE_MULTIPLE_OVERLAYS)
+ final int resId = R.array.fibonacci;
+ assertResource(resId,
+ new int[]{1, 1, 2, 3, 5, 8, 13, 21},
+ new int[]{21, 13, 8, 5, 3, 2, 1, 1},
+ new int[]{21, 13, 8, 5, 3, 2, 1, 1});
}
public void testIntegerArray() throws Throwable {
- // config_virtualKeyVibePattern has no overlay
- final int resId = com.android.internal.R.array.config_virtualKeyVibePattern;
- final int[] expected = {0, 10, 20, 30};
- assertResource(resId, expected, expected);
+ // prime_numbers has no overlay
+ final int resId = R.array.prime_numbers;
+ final int[] expected = {2, 3, 5, 7, 11, 13, 17, 19};
+ assertResource(resId, expected, expected, expected);
}
- public void testAsset() throws Throwable {
- // drawable/default_background.jpg has overlay (default config)
- final int resId = com.android.internal.R.drawable.default_wallpaper;
+ public void testDrawable() throws Throwable {
+ // drawable-nodpi/drawable has overlay (default config)
+ final int resId = R.drawable.drawable;
int actual = calculateRawResourceChecksum(resId);
- int expected = mWithOverlay ? 0x000051da : 0x0014ebce;
+ int expected = 0;
+ switch (mMode) {
+ case MODE_NO_OVERLAY:
+ expected = 0x00005665;
+ break;
+ case MODE_SINGLE_OVERLAY:
+ case MODE_MULTIPLE_OVERLAYS:
+ expected = 0x000051da;
+ break;
+ default:
+ fail("Unknown mode " + mMode);
+ }
assertEquals(expected, actual);
}
+
+ public void testAppString() throws Throwable {
+ final int resId = R.string.str;
+ assertResource(resId, "none", "single", "multiple");
+ }
+
+ public void testApp2() throws Throwable {
+ final int resId = R.string.str2; // only in base package and first app overlay
+ assertResource(resId, "none", "single", "single");
+ }
+
+ public void testAppXml() throws Throwable {
+ int expected = getExpected(0, 1, 2);
+ int actual = -1;
+ XmlResourceParser parser = mResources.getXml(R.xml.integer);
+ int type = parser.getEventType();
+ while (type != XmlResourceParser.END_DOCUMENT && actual == -1) {
+ if (type == XmlResourceParser.START_TAG && "integer".equals(parser.getName())) {
+ AttributeSet as = Xml.asAttributeSet(parser);
+ actual = as.getAttributeIntValue(null, "value", -1);
+ }
+ type = parser.next();
+ }
+ parser.close();
+ assertEquals(expected, actual);
+ }
+
+ public void testAppRaw() throws Throwable {
+ final int resId = R.raw.lorem_ipsum;
+
+ InputStream input = null;
+ BufferedReader reader = null;
+ String actual = "";
+ try {
+ input = mResources.openRawResource(resId);
+ reader = new BufferedReader(new InputStreamReader(input));
+ actual = reader.readLine();
+ } finally {
+ reader.close();
+ input.close();
+ }
+
+ final String no = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, " +
+ "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. " +
+ "Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip " +
+ "ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit " +
+ "esse cillum dolore eu fugiat nulla pariatur. " +
+ "Excepteur sint occaecat cupidatat non proident, " +
+ "sunt in culpa qui officia deserunt mollit anim id est laborum.";
+ final String so = "Lorem ipsum: single overlay.";
+ final String mo = "Lorem ipsum: multiple overlays.";
+
+ assertEquals(getExpected(no, so, mo), actual);
+ }
+
+ /*
+ * testMatrix* tests
+ *
+ * The naming convention textMatrixABCDEF refers to in which packages and
+ * which configurations a resource is defined (1 if the resource is
+ * defined). If defined, a slot is always given the same value.
+ *
+ * SLOT PACKAGE CONFIGURATION VALUE
+ * A target package (default) 100
+ * B target package -sv 200
+ * C OverlayAppFirst (default) 300
+ * D OverlayAppFirst -sv 400
+ * E OverlayAppSecond (default) 500
+ * F OverlayAppSecond -sv 600
+ *
+ * Example: in testMatrix101110, the base package defines the
+ * R.integer.matrix101110 resource for the default configuration (value
+ * 100), OverlayAppFirst defines it for both default and Swedish
+ * configurations (values 300 and 400, respectively), and OverlayAppSecond
+ * defines it for the default configuration (value 500). If both overlays
+ * are loaded, the expected value after setting the language to Swedish is
+ * 400.
+ */
+ public void testMatrix100000() throws Throwable {
+ final int resId = R.integer.matrix_100000;
+ setLocale("sv_SE");
+ assertResource(resId, 100, 100, 100);
+ }
+
+ public void testMatrix100001() throws Throwable {
+ final int resId = R.integer.matrix_100001;
+ setLocale("sv_SE");
+ assertResource(resId, 100, 100, 600);
+ }
+
+ public void testMatrix100010() throws Throwable {
+ final int resId = R.integer.matrix_100010;
+ setLocale("sv_SE");
+ assertResource(resId, 100, 100, 500);
+ }
+
+ public void testMatrix100011() throws Throwable {
+ final int resId = R.integer.matrix_100011;
+ setLocale("sv_SE");
+ assertResource(resId, 100, 100, 600);
+ }
+
+ public void testMatrix100100() throws Throwable {
+ final int resId = R.integer.matrix_100100;
+ setLocale("sv_SE");
+ assertResource(resId, 100, 400, 400);
+ }
+
+ public void testMatrix100101() throws Throwable {
+ final int resId = R.integer.matrix_100101;
+ setLocale("sv_SE");
+ assertResource(resId, 100, 400, 600);
+ }
+
+ public void testMatrix100110() throws Throwable {
+ final int resId = R.integer.matrix_100110;
+ setLocale("sv_SE");
+ assertResource(resId, 100, 400, 400);
+ }
+
+ public void testMatrix100111() throws Throwable {
+ final int resId = R.integer.matrix_100111;
+ setLocale("sv_SE");
+ assertResource(resId, 100, 400, 600);
+ }
+
+ public void testMatrix101000() throws Throwable {
+ final int resId = R.integer.matrix_101000;
+ setLocale("sv_SE");
+ assertResource(resId, 100, 300, 300);
+ }
+
+ public void testMatrix101001() throws Throwable {
+ final int resId = R.integer.matrix_101001;
+ setLocale("sv_SE");
+ assertResource(resId, 100, 300, 600);
+ }
+
+ public void testMatrix101010() throws Throwable {
+ final int resId = R.integer.matrix_101010;
+ setLocale("sv_SE");
+ assertResource(resId, 100, 300, 500);
+ }
+
+ public void testMatrix101011() throws Throwable {
+ final int resId = R.integer.matrix_101011;
+ setLocale("sv_SE");
+ assertResource(resId, 100, 300, 600);
+ }
+
+ public void testMatrix101100() throws Throwable {
+ final int resId = R.integer.matrix_101100;
+ setLocale("sv_SE");
+ assertResource(resId, 100, 400, 400);
+ }
+
+ public void testMatrix101101() throws Throwable {
+ final int resId = R.integer.matrix_101101;
+ setLocale("sv_SE");
+ assertResource(resId, 100, 400, 600);
+ }
+
+ public void testMatrix101110() throws Throwable {
+ final int resId = R.integer.matrix_101110;
+ setLocale("sv_SE");
+ assertResource(resId, 100, 400, 400);
+ }
+
+ public void testMatrix101111() throws Throwable {
+ final int resId = R.integer.matrix_101111;
+ setLocale("sv_SE");
+ assertResource(resId, 100, 400, 600);
+ }
+
+ public void testMatrix110000() throws Throwable {
+ final int resId = R.integer.matrix_110000;
+ setLocale("sv_SE");
+ assertResource(resId, 200, 200, 200);
+ }
+
+ public void testMatrix110001() throws Throwable {
+ final int resId = R.integer.matrix_110001;
+ setLocale("sv_SE");
+ assertResource(resId, 200, 200, 600);
+ }
+
+ public void testMatrix110010() throws Throwable {
+ final int resId = R.integer.matrix_110010;
+ setLocale("sv_SE");
+ assertResource(resId, 200, 200, 200);
+ }
+
+ public void testMatrix110011() throws Throwable {
+ final int resId = R.integer.matrix_110011;
+ setLocale("sv_SE");
+ assertResource(resId, 200, 200, 600);
+ }
+
+ public void testMatrix110100() throws Throwable {
+ final int resId = R.integer.matrix_110100;
+ setLocale("sv_SE");
+ assertResource(resId, 200, 400, 400);
+ }
+
+ public void testMatrix110101() throws Throwable {
+ final int resId = R.integer.matrix_110101;
+ setLocale("sv_SE");
+ assertResource(resId, 200, 400, 600);
+ }
+
+ public void testMatrix110110() throws Throwable {
+ final int resId = R.integer.matrix_110110;
+ setLocale("sv_SE");
+ assertResource(resId, 200, 400, 400);
+ }
+
+ public void testMatrix110111() throws Throwable {
+ final int resId = R.integer.matrix_110111;
+ setLocale("sv_SE");
+ assertResource(resId, 200, 400, 600);
+ }
+
+ public void testMatrix111000() throws Throwable {
+ final int resId = R.integer.matrix_111000;
+ setLocale("sv_SE");
+ assertResource(resId, 200, 200, 200);
+ }
+
+ public void testMatrix111001() throws Throwable {
+ final int resId = R.integer.matrix_111001;
+ setLocale("sv_SE");
+ assertResource(resId, 200, 200, 600);
+ }
+
+ public void testMatrix111010() throws Throwable {
+ final int resId = R.integer.matrix_111010;
+ setLocale("sv_SE");
+ assertResource(resId, 200, 200, 200);
+ }
+
+ public void testMatrix111011() throws Throwable {
+ final int resId = R.integer.matrix_111011;
+ setLocale("sv_SE");
+ assertResource(resId, 200, 200, 600);
+ }
+
+ public void testMatrix111100() throws Throwable {
+ final int resId = R.integer.matrix_111100;
+ setLocale("sv_SE");
+ assertResource(resId, 200, 400, 400);
+ }
+
+ public void testMatrix111101() throws Throwable {
+ final int resId = R.integer.matrix_111101;
+ setLocale("sv_SE");
+ assertResource(resId, 200, 400, 600);
+ }
+
+ public void testMatrix111110() throws Throwable {
+ final int resId = R.integer.matrix_111110;
+ setLocale("sv_SE");
+ assertResource(resId, 200, 400, 400);
+ }
+
+ public void testMatrix111111() throws Throwable {
+ final int resId = R.integer.matrix_111111;
+ setLocale("sv_SE");
+ assertResource(resId, 200, 400, 600);
+ }
}
diff --git a/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithMultipleOverlaysTest.java b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithMultipleOverlaysTest.java
new file mode 100644
index 0000000..e104f5a
--- /dev/null
+++ b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithMultipleOverlaysTest.java
@@ -0,0 +1,7 @@
+package com.android.overlaytest;
+
+public class WithMultipleOverlaysTest extends OverlayBaseTest {
+ public WithMultipleOverlaysTest() {
+ mMode = MODE_MULTIPLE_OVERLAYS;
+ }
+}
diff --git a/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithOverlayTest.java b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithOverlayTest.java
index 1292d03..816a476 100644
--- a/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithOverlayTest.java
+++ b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithOverlayTest.java
@@ -2,6 +2,6 @@
public class WithOverlayTest extends OverlayBaseTest {
public WithOverlayTest() {
- mWithOverlay = true;
+ mMode = MODE_SINGLE_OVERLAY;
}
}
diff --git a/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithoutOverlayTest.java b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithoutOverlayTest.java
index 630ff8f..318cccc 100644
--- a/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithoutOverlayTest.java
+++ b/core/tests/overlaytests/OverlayTest/src/com/android/overlaytest/WithoutOverlayTest.java
@@ -2,6 +2,6 @@
public class WithoutOverlayTest extends OverlayBaseTest {
public WithoutOverlayTest() {
- mWithOverlay = false;
+ mMode = MODE_NO_OVERLAY;
}
}
diff --git a/core/tests/overlaytests/OverlayTestOverlay/AndroidManifest.xml b/core/tests/overlaytests/OverlayTestOverlay/AndroidManifest.xml
index bcbb0d1..f8b6c7b 100644
--- a/core/tests/overlaytests/OverlayTestOverlay/AndroidManifest.xml
+++ b/core/tests/overlaytests/OverlayTestOverlay/AndroidManifest.xml
@@ -2,5 +2,5 @@
package="com.android.overlaytest.overlay"
android:versionCode="1"
android:versionName="1.0">
- <overlay-package android:name="android"/>
+ <overlay android:targetPackage="android" android:priority="1"/>
</manifest>
diff --git a/core/tests/overlaytests/OverlayTestOverlay/res/values-sv/config.xml b/core/tests/overlaytests/OverlayTestOverlay/res/values-sv/config.xml
deleted file mode 100644
index bc52367..0000000
--- a/core/tests/overlaytests/OverlayTestOverlay/res/values-sv/config.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <string name="phoneTypeWork">Jobb</string>
-</resources>
diff --git a/core/tests/overlaytests/OverlayTestOverlay/res/values/config.xml b/core/tests/overlaytests/OverlayTestOverlay/res/values/config.xml
index 794f475..c1e3de1 100644
--- a/core/tests/overlaytests/OverlayTestOverlay/res/values/config.xml
+++ b/core/tests/overlaytests/OverlayTestOverlay/res/values/config.xml
@@ -1,13 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <bool name="config_automatic_brightness_available">true</bool>
- <string name="phoneTypeCar">Automobile</string>
- <integer-array name="config_scrollBarrierVibePattern">
- <item>100</item>
- <item>200</item>
- <item>300</item>
- </integer-array>
- <!-- The following integer does not exist in the original package. Idmap
- generation should therefore ignore it. -->
- <integer name="integer_not_in_original_package">0</integer>
+ <bool name="config_annoy_dianne">false</bool>
</resources>
diff --git a/core/tests/overlaytests/README b/core/tests/overlaytests/README
deleted file mode 100644
index 4b3e6f2..0000000
--- a/core/tests/overlaytests/README
+++ /dev/null
@@ -1,15 +0,0 @@
-Unit tests for runtime resource overlay
-=======================================
-
-As of this writing, runtime resource overlay is only triggered for
-/system/framework/framework-res.apk. Because of this, installation of
-overlay packages require the Android platform be rebooted. However, the
-regular unit tests (triggered via development/testrunner/runtest.py)
-cannot handle reboots. As a workaround, this directory contains a shell
-script which will trigger the tests in a non-standard way.
-
-Once runtime resource overlay may be applied to applications, the tests
-in this directory should be moved to core/tests/coretests. Also, by
-applying runtime resource overlay to a dedicated test application, the
-test cases would not need to assume default values for non-overlaid
-resources.
diff --git a/core/tests/overlaytests/runtests.sh b/core/tests/overlaytests/runtests.sh
deleted file mode 100755
index 0a721ad40..0000000
--- a/core/tests/overlaytests/runtests.sh
+++ /dev/null
@@ -1,129 +0,0 @@
-#!/bin/bash
-
-adb="adb"
-if [[ $# -gt 0 ]]; then
- adb="adb $*" # for setting -e, -d or -s <serial>
-fi
-
-function atexit()
-{
- local retval=$?
-
- if [[ $retval -eq 0 ]]; then
- rm $log
- else
- echo "There were errors, please check log at $log"
- fi
-}
-
-log=$(mktemp)
-trap "atexit" EXIT
-
-function compile_module()
-{
- local android_mk="$1"
-
- echo "Compiling .${android_mk:${#PWD}}"
- ONE_SHOT_MAKEFILE="$android_mk" make -C "../../../../../" files | tee -a $log
- if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
- exit 1
- fi
-}
-
-function wait_for_boot_completed()
-{
- echo "Rebooting device"
- $adb wait-for-device logcat -c
- $adb wait-for-device logcat | grep -m 1 -e 'PowerManagerService.*bootCompleted' >/dev/null
-}
-
-function mkdir_if_needed()
-{
- local path="$1"
-
- if [[ "${path:0:1}" != "/" ]]; then
- echo "mkdir_if_needed: error: path '$path' does not begin with /" | tee -a $log
- exit 1
- fi
-
- local basename=$(basename "$path")
- local dirname=$(dirname "$path")
- local t=$($adb shell ls -l $dirname | tr -d '\r' | grep -e "${basename}$" | grep -oe '^.')
-
- case "$t" in
- d) # File exists, and is a directory ...
- # do nothing
- ;;
- l) # ... (or symbolic link possibly to a directory).
- # do nothing
- ;;
- "") # File does not exist.
- mkdir_if_needed "$dirname"
- $adb shell mkdir "$path"
- ;;
- *) # File exists, but is not a directory.
- echo "mkdir_if_needed: file '$path' exists, but is not a directory" | tee -a $log
- exit 1
- ;;
- esac
-}
-
-function disable_overlay()
-{
- echo "Disabling overlay"
- $adb shell rm /vendor/overlay/framework/framework-res.apk
- $adb shell rm /data/resource-cache/vendor@overlay@framework@framework-res.apk@idmap
-}
-
-function enable_overlay()
-{
- echo "Enabling overlay"
- mkdir_if_needed "/system/vendor"
- mkdir_if_needed "/vendor/overlay/framework"
- $adb shell ln -s /data/app/com.android.overlaytest.overlay.apk /vendor/overlay/framework/framework-res.apk
-}
-
-function instrument()
-{
- local class="$1"
-
- echo "Instrumenting $class"
- $adb shell am instrument -w -e class $class com.android.overlaytest/android.test.InstrumentationTestRunner | tee -a $log
-}
-
-function remount()
-{
- echo "Remounting file system writable"
- $adb remount | tee -a $log
-}
-
-function sync()
-{
- echo "Syncing to device"
- $adb sync data | tee -a $log
-}
-
-# some commands require write access, remount once and for all
-remount
-
-# build and sync
-compile_module "$PWD/OverlayTest/Android.mk"
-compile_module "$PWD/OverlayTestOverlay/Android.mk"
-sync
-
-# instrument test (without overlay)
-$adb shell stop
-disable_overlay
-$adb shell start
-wait_for_boot_completed
-instrument "com.android.overlaytest.WithoutOverlayTest"
-
-# instrument test (with overlay)
-$adb shell stop
-enable_overlay
-$adb shell start
-wait_for_boot_completed
-instrument "com.android.overlaytest.WithOverlayTest"
-
-# cleanup
-exit $(grep -c -e '^FAILURES' $log)
diff --git a/core/tests/overlaytests/testrunner.py b/core/tests/overlaytests/testrunner.py
new file mode 100755
index 0000000..4f94373
--- /dev/null
+++ b/core/tests/overlaytests/testrunner.py
@@ -0,0 +1,679 @@
+#!/usr/bin/python
+import hashlib
+import optparse
+import os
+import re
+import shlex
+import subprocess
+import sys
+import threading
+import time
+
+TASK_COMPILATION = 'compile'
+TASK_DISABLE_OVERLAYS = 'disable overlays'
+TASK_ENABLE_MULTIPLE_OVERLAYS = 'enable multiple overlays'
+TASK_ENABLE_SINGLE_OVERLAY = 'enable single overlay'
+TASK_FILE_EXISTS_TEST = 'test (file exists)'
+TASK_GREP_IDMAP_TEST = 'test (grep idmap)'
+TASK_MD5_TEST = 'test (md5)'
+TASK_IDMAP_PATH = 'idmap --path'
+TASK_IDMAP_SCAN = 'idmap --scan'
+TASK_INSTRUMENTATION = 'instrumentation'
+TASK_INSTRUMENTATION_TEST = 'test (instrumentation)'
+TASK_MKDIR = 'mkdir'
+TASK_PUSH = 'push'
+TASK_ROOT = 'root'
+TASK_REMOUNT = 'remount'
+TASK_RM = 'rm'
+TASK_SETUP_IDMAP_PATH = 'setup idmap --path'
+TASK_SETUP_IDMAP_SCAN = 'setup idmap --scan'
+TASK_START = 'start'
+TASK_STOP = 'stop'
+
+adb = 'adb'
+
+def _adb_shell(cmd):
+ argv = shlex.split(adb + " shell '" + cmd + "; echo $?'")
+ proc = subprocess.Popen(argv, bufsize=1, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ (stdout, stderr) = proc.communicate()
+ (stdout, stderr) = (stdout.replace('\r', ''), stderr.replace('\r', ''))
+ tmp = stdout.rsplit('\n', 2)
+ if len(tmp) == 2:
+ stdout == ''
+ returncode = int(tmp[0])
+ else:
+ stdout = tmp[0] + '\n'
+ returncode = int(tmp[1])
+ return returncode, stdout, stderr
+
+class VerbosePrinter:
+ class Ticker(threading.Thread):
+ def _print(self):
+ s = '\r' + self.text + '[' + '.' * self.i + ' ' * (4 - self.i) + ']'
+ sys.stdout.write(s)
+ sys.stdout.flush()
+ self.i = (self.i + 1) % 5
+
+ def __init__(self, cond_var, text):
+ threading.Thread.__init__(self)
+ self.text = text
+ self.setDaemon(True)
+ self.cond_var = cond_var
+ self.running = False
+ self.i = 0
+ self._print()
+ self.running = True
+
+ def run(self):
+ self.cond_var.acquire()
+ while True:
+ self.cond_var.wait(0.25)
+ running = self.running
+ if not running:
+ break
+ self._print()
+ self.cond_var.release()
+
+ def stop(self):
+ self.cond_var.acquire()
+ self.running = False
+ self.cond_var.notify_all()
+ self.cond_var.release()
+
+ def _start_ticker(self):
+ self.ticker = VerbosePrinter.Ticker(self.cond_var, self.text)
+ self.ticker.start()
+
+ def _stop_ticker(self):
+ self.ticker.stop()
+ self.ticker.join()
+ self.ticker = None
+
+ def _format_begin(self, type, name):
+ N = self.width - len(type) - len(' [ ] ')
+ fmt = '%%s %%-%ds ' % N
+ return fmt % (type, name)
+
+ def __init__(self, use_color):
+ self.cond_var = threading.Condition()
+ self.ticker = None
+ if use_color:
+ self.color_RED = '\033[1;31m'
+ self.color_red = '\033[0;31m'
+ self.color_reset = '\033[0;37m'
+ else:
+ self.color_RED = ''
+ self.color_red = ''
+ self.color_reset = ''
+
+ argv = shlex.split('stty size') # get terminal width
+ proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ (stdout, stderr) = proc.communicate()
+ if proc.returncode == 0:
+ (h, w) = stdout.split()
+ self.width = int(w)
+ else:
+ self.width = 72 # conservative guesstimate
+
+ def begin(self, type, name):
+ self.text = self._format_begin(type, name)
+ sys.stdout.write(self.text + '[ ]')
+ sys.stdout.flush()
+ self._start_ticker()
+
+ def end_pass(self, type, name):
+ self._stop_ticker()
+ sys.stdout.write('\r' + self.text + '[ OK ]\n')
+ sys.stdout.flush()
+
+ def end_fail(self, type, name, msg):
+ self._stop_ticker()
+ sys.stdout.write('\r' + self.color_RED + self.text + '[FAIL]\n')
+ sys.stdout.write(self.color_red)
+ sys.stdout.write(msg)
+ sys.stdout.write(self.color_reset)
+ sys.stdout.flush()
+
+class QuietPrinter:
+ def begin(self, type, name):
+ pass
+
+ def end_pass(self, type, name):
+ sys.stdout.write('PASS ' + type + ' ' + name + '\n')
+ sys.stdout.flush()
+
+ def end_fail(self, type, name, msg):
+ sys.stdout.write('FAIL ' + type + ' ' + name + '\n')
+ sys.stdout.flush()
+
+class CompilationTask:
+ def __init__(self, makefile):
+ self.makefile = makefile
+
+ def get_type(self):
+ return TASK_COMPILATION
+
+ def get_name(self):
+ return self.makefile
+
+ def execute(self):
+ os.putenv('ONE_SHOT_MAKEFILE', os.getcwd() + "/" + self.makefile)
+ argv = shlex.split('make -C "../../../../../" files')
+ proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ (stdout, stderr) = proc.communicate()
+ return proc.returncode, stdout, stderr
+
+class InstrumentationTask:
+ def __init__(self, instrumentation_class):
+ self.instrumentation_class = instrumentation_class
+
+ def get_type(self):
+ return TASK_INSTRUMENTATION
+
+ def get_name(self):
+ return self.instrumentation_class
+
+ def execute(self):
+ return _adb_shell('am instrument -r -w -e class %s com.android.overlaytest/android.test.InstrumentationTestRunner' % self.instrumentation_class)
+
+class PushTask:
+ def __init__(self, src, dest):
+ self.src = src
+ self.dest = dest
+
+ def get_type(self):
+ return TASK_PUSH
+
+ def get_name(self):
+ return "%s -> %s" % (self.src, self.dest)
+
+ def execute(self):
+ src = os.getenv('OUT') + "/" + self.src
+ argv = shlex.split(adb + ' push %s %s' % (src, self.dest))
+ proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ (stdout, stderr) = proc.communicate()
+ return proc.returncode, stdout, stderr
+
+class MkdirTask:
+ def __init__(self, path):
+ self.path = path
+
+ def get_type(self):
+ return TASK_MKDIR
+
+ def get_name(self):
+ return self.path
+
+ def execute(self):
+ return _adb_shell('mkdir -p %s' % self.path)
+
+class RmTask:
+ def __init__(self, path):
+ self.path = path
+
+ def get_type(self):
+ return TASK_RM
+
+ def get_name(self):
+ return self.path
+
+ def execute(self):
+ returncode, stdout, stderr = _adb_shell('ls %s' % self.path)
+ if returncode != 0 and stdout.endswith(': No such file or directory\n'):
+ return 0, "", ""
+ return _adb_shell('rm -r %s' % self.path)
+
+class IdmapPathTask:
+ def __init__(self, path_target_apk, path_overlay_apk, path_idmap):
+ self.path_target_apk = path_target_apk
+ self.path_overlay_apk = path_overlay_apk
+ self.path_idmap = path_idmap
+
+ def get_type(self):
+ return TASK_IDMAP_PATH
+
+ def get_name(self):
+ return self.path_idmap
+
+ def execute(self):
+ return _adb_shell('su system idmap --path "%s" "%s" "%s"' % (self.path_target_apk, self.path_overlay_apk, self.path_idmap))
+
+class IdmapScanTask:
+ def __init__(self, overlay_dir, target_pkg_name, target_pkg, idmap_dir, symlink_dir):
+ self.overlay_dir = overlay_dir
+ self.target_pkg_name = target_pkg_name
+ self.target_pkg = target_pkg
+ self.idmap_dir = idmap_dir
+ self.symlink_dir = symlink_dir
+
+ def get_type(self):
+ return TASK_IDMAP_SCAN
+
+ def get_name(self):
+ return self.target_pkg_name
+
+ def execute(self):
+ return _adb_shell('su system idmap --scan "%s" "%s" "%s" "%s"' % (self.overlay_dir, self.target_pkg_name, self.target_pkg, self.idmap_dir))
+
+class FileExistsTest:
+ def __init__(self, path):
+ self.path = path
+
+ def get_type(self):
+ return TASK_FILE_EXISTS_TEST
+
+ def get_name(self):
+ return self.path
+
+ def execute(self):
+ return _adb_shell('ls %s' % self.path)
+
+class GrepIdmapTest:
+ def __init__(self, path_idmap, pattern, expected_n):
+ self.path_idmap = path_idmap
+ self.pattern = pattern
+ self.expected_n = expected_n
+
+ def get_type(self):
+ return TASK_GREP_IDMAP_TEST
+
+ def get_name(self):
+ return self.pattern
+
+ def execute(self):
+ returncode, stdout, stderr = _adb_shell('idmap --inspect %s' % self.path_idmap)
+ if returncode != 0:
+ return returncode, stdout, stderr
+ all_matches = re.findall('\s' + self.pattern + '$', stdout, flags=re.MULTILINE)
+ if len(all_matches) != self.expected_n:
+ return 1, 'pattern=%s idmap=%s expected=%d found=%d\n' % (self.pattern, self.path_idmap, self.expected_n, len(all_matches)), ''
+ return 0, "", ""
+
+class Md5Test:
+ def __init__(self, path, expected_content):
+ self.path = path
+ self.expected_md5 = hashlib.md5(expected_content).hexdigest()
+
+ def get_type(self):
+ return TASK_MD5_TEST
+
+ def get_name(self):
+ return self.path
+
+ def execute(self):
+ returncode, stdout, stderr = _adb_shell('md5 %s' % self.path)
+ if returncode != 0:
+ return returncode, stdout, stderr
+ actual_md5 = stdout.split()[0]
+ if actual_md5 != self.expected_md5:
+ return 1, 'expected %s, got %s\n' % (self.expected_md5, actual_md5), ''
+ return 0, "", ""
+
+class StartTask:
+ def get_type(self):
+ return TASK_START
+
+ def get_name(self):
+ return ""
+
+ def execute(self):
+ (returncode, stdout, stderr) = _adb_shell('start')
+ if returncode != 0:
+ return returncode, stdout, stderr
+
+ while True:
+ (returncode, stdout, stderr) = _adb_shell('getprop dev.bootcomplete')
+ if returncode != 0:
+ return returncode, stdout, stderr
+ if stdout.strip() == "1":
+ break
+ time.sleep(0.5)
+
+ return 0, "", ""
+
+class StopTask:
+ def get_type(self):
+ return TASK_STOP
+
+ def get_name(self):
+ return ""
+
+ def execute(self):
+ (returncode, stdout, stderr) = _adb_shell('stop')
+ if returncode != 0:
+ return returncode, stdout, stderr
+ return _adb_shell('setprop dev.bootcomplete 0')
+
+class RootTask:
+ def get_type(self):
+ return TASK_ROOT
+
+ def get_name(self):
+ return ""
+
+ def execute(self):
+ (returncode, stdout, stderr) = _adb_shell('getprop service.adb.root 0')
+ if returncode != 0:
+ return returncode, stdout, stderr
+ if stdout.strip() == '1': # already root
+ return 0, "", ""
+
+ argv = shlex.split(adb + ' root')
+ proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ (stdout, stderr) = proc.communicate()
+ if proc.returncode != 0:
+ return proc.returncode, stdout, stderr
+
+ argv = shlex.split(adb + ' wait-for-device')
+ proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ (stdout, stderr) = proc.communicate()
+ return proc.returncode, stdout, stderr
+
+class RemountTask:
+ def get_type(self):
+ return TASK_REMOUNT
+
+ def get_name(self):
+ return ""
+
+ def execute(self):
+ argv = shlex.split(adb + ' remount')
+ proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ (stdout, stderr) = proc.communicate()
+ # adb remount returns 0 even if the operation failed, so check stdout
+ if stdout.startswith('remount failed:'):
+ return 1, stdout, stderr
+ return proc.returncode, stdout, stderr
+
+class CompoundTask:
+ def __init__(self, type, tasks):
+ self.type = type
+ self.tasks = tasks
+
+ def get_type(self):
+ return self.type
+
+ def get_name(self):
+ return ""
+
+ def execute(self):
+ for t in self.tasks:
+ (returncode, stdout, stderr) = t.execute()
+ if returncode != 0:
+ return returncode, stdout, stderr
+ return 0, "", ""
+
+def _create_disable_overlays_task():
+ tasks = [
+ RmTask("/vendor/overlay/framework_a.apk"),
+ RmTask("/vendor/overlay/framework_b.apk"),
+ RmTask("/data/resource-cache/vendor@overlay@framework_a.apk@idmap"),
+ RmTask("/data/resource-cache/vendor@overlay@framework_b.apk@idmap"),
+ RmTask("/vendor/overlay/app_a.apk"),
+ RmTask("/vendor/overlay/app_b.apk"),
+ RmTask("/data/resource-cache/vendor@overlay@app_a.apk@idmap"),
+ RmTask("/data/resource-cache/vendor@overlay@app_b.apk@idmap"),
+ ]
+ return CompoundTask(TASK_DISABLE_OVERLAYS, tasks)
+
+def _create_enable_single_overlay_task():
+ tasks = [
+ _create_disable_overlays_task(),
+ MkdirTask('/system/vendor'),
+ MkdirTask('/vendor/overlay'),
+ PushTask('/data/app/com.android.overlaytest.overlay.apk', '/vendor/overlay/framework_a.apk'),
+ PushTask('/data/app/com.android.overlaytest.first_app_overlay.apk', '/vendor/overlay/app_a.apk'),
+ ]
+ return CompoundTask(TASK_ENABLE_SINGLE_OVERLAY, tasks)
+
+def _create_enable_multiple_overlays_task():
+ tasks = [
+ _create_disable_overlays_task(),
+ MkdirTask('/system/vendor'),
+ MkdirTask('/vendor/overlay'),
+
+ PushTask('/data/app/com.android.overlaytest.overlay.apk', '/vendor/overlay/framework_b.apk'),
+ PushTask('/data/app/com.android.overlaytest.first_app_overlay.apk', '/vendor/overlay/app_a.apk'),
+ PushTask('/data/app/com.android.overlaytest.second_app_overlay.apk', '/vendor/overlay/app_b.apk'),
+ ]
+ return CompoundTask(TASK_ENABLE_MULTIPLE_OVERLAYS, tasks)
+
+def _create_setup_idmap_path_task(idmaps, symlinks):
+ tasks = [
+ _create_enable_single_overlay_task(),
+ RmTask(symlinks),
+ RmTask(idmaps),
+ MkdirTask(idmaps),
+ MkdirTask(symlinks),
+ ]
+ return CompoundTask(TASK_SETUP_IDMAP_PATH, tasks)
+
+def _create_setup_idmap_scan_task(idmaps, symlinks):
+ tasks = [
+ _create_enable_single_overlay_task(),
+ RmTask(symlinks),
+ RmTask(idmaps),
+ MkdirTask(idmaps),
+ MkdirTask(symlinks),
+ _create_enable_multiple_overlays_task(),
+ ]
+ return CompoundTask(TASK_SETUP_IDMAP_SCAN, tasks)
+
+def _handle_instrumentation_task_output(stdout, printer):
+ regex_status_code = re.compile(r'^INSTRUMENTATION_STATUS_CODE: -?(\d+)')
+ regex_name = re.compile(r'^INSTRUMENTATION_STATUS: test=(.*)')
+ regex_begin_stack = re.compile(r'^INSTRUMENTATION_STATUS: stack=(.*)')
+ regex_end_stack = re.compile(r'^$')
+
+ failed_tests = 0
+ current_test = None
+ current_stack = []
+ mode_stack = False
+ for line in stdout.split("\n"):
+ line = line.rstrip() # strip \r from adb output
+ m = regex_status_code.match(line)
+ if m:
+ c = int(m.group(1))
+ if c == 1:
+ printer.begin(TASK_INSTRUMENTATION_TEST, current_test)
+ elif c == 0:
+ printer.end_pass(TASK_INSTRUMENTATION_TEST, current_test)
+ else:
+ failed_tests += 1
+ current_stack.append("\n")
+ msg = "\n".join(current_stack)
+ printer.end_fail(TASK_INSTRUMENTATION_TEST, current_test, msg.rstrip() + '\n')
+ continue
+
+ m = regex_name.match(line)
+ if m:
+ current_test = m.group(1)
+ continue
+
+ m = regex_begin_stack.match(line)
+ if m:
+ mode_stack = True
+ current_stack = []
+ current_stack.append(" " + m.group(1))
+ continue
+
+ m = regex_end_stack.match(line)
+ if m:
+ mode_stack = False
+ continue
+
+ if mode_stack:
+ current_stack.append(" " + line.strip())
+
+ return failed_tests
+
+def _set_adb_device(option, opt, value, parser):
+ global adb
+ if opt == '-d' or opt == '--device':
+ adb = 'adb -d'
+ if opt == '-e' or opt == '--emulator':
+ adb = 'adb -e'
+ if opt == '-s' or opt == '--serial':
+ adb = 'adb -s ' + value
+
+def _create_opt_parser():
+ parser = optparse.OptionParser()
+ parser.add_option('-d', '--device', action='callback', callback=_set_adb_device,
+ help='pass -d to adb')
+ parser.add_option('-e', '--emulator', action='callback', callback=_set_adb_device,
+ help='pass -e to adb')
+ parser.add_option('-s', '--serial', type="str", action='callback', callback=_set_adb_device,
+ help='pass -s <serical> to adb')
+ parser.add_option('-C', '--no-color', action='store_false',
+ dest='use_color', default=True,
+ help='disable color escape sequences in output')
+ parser.add_option('-q', '--quiet', action='store_true',
+ dest='quiet_mode', default=False,
+ help='quiet mode, output only results')
+ parser.add_option('-b', '--no-build', action='store_false',
+ dest='do_build', default=True,
+ help='do not rebuild test projects')
+ parser.add_option('-k', '--continue', action='store_true',
+ dest='do_continue', default=False,
+ help='do not rebuild test projects')
+ parser.add_option('-i', '--test-idmap', action='store_true',
+ dest='test_idmap', default=False,
+ help='run tests for single overlay')
+ parser.add_option('-0', '--test-no-overlay', action='store_true',
+ dest='test_no_overlay', default=False,
+ help='run tests without any overlay')
+ parser.add_option('-1', '--test-single-overlay', action='store_true',
+ dest='test_single_overlay', default=False,
+ help='run tests for single overlay')
+ parser.add_option('-2', '--test-multiple-overlays', action='store_true',
+ dest='test_multiple_overlays', default=False,
+ help='run tests for multiple overlays')
+ return parser
+
+if __name__ == '__main__':
+ opt_parser = _create_opt_parser()
+ opts, args = opt_parser.parse_args(sys.argv[1:])
+ if not opts.test_idmap and not opts.test_no_overlay and not opts.test_single_overlay and not opts.test_multiple_overlays:
+ opts.test_idmap = True
+ opts.test_no_overlay = True
+ opts.test_single_overlay = True
+ opts.test_multiple_overlays = True
+ if len(args) > 0:
+ opt_parser.error("unexpected arguments: %s" % " ".join(args))
+ # will never reach this: opt_parser.error will call sys.exit
+
+ if opts.quiet_mode:
+ printer = QuietPrinter()
+ else:
+ printer = VerbosePrinter(opts.use_color)
+ tasks = []
+
+ # must be in the same directory as this script for compilation tasks to work
+ script = sys.argv[0]
+ dirname = os.path.dirname(script)
+ wd = os.path.realpath(dirname)
+ os.chdir(wd)
+
+ # build test cases
+ if opts.do_build:
+ tasks.append(CompilationTask('OverlayTest/Android.mk'))
+ tasks.append(CompilationTask('OverlayTestOverlay/Android.mk'))
+ tasks.append(CompilationTask('OverlayAppFirst/Android.mk'))
+ tasks.append(CompilationTask('OverlayAppSecond/Android.mk'))
+
+ # remount filesystem, install test project
+ tasks.append(RootTask())
+ tasks.append(RemountTask())
+ tasks.append(PushTask('/system/app/OverlayTest.apk', '/system/app/OverlayTest.apk'))
+
+ # test idmap
+ if opts.test_idmap:
+ idmaps='/data/local/tmp/idmaps'
+ symlinks='/data/local/tmp/symlinks'
+
+ # idmap --path
+ tasks.append(StopTask())
+ tasks.append(_create_setup_idmap_path_task(idmaps, symlinks))
+ tasks.append(StartTask())
+ tasks.append(IdmapPathTask('/vendor/overlay/framework_a.apk', '/system/framework/framework-res.apk', idmaps + '/a.idmap'))
+ tasks.append(FileExistsTest(idmaps + '/a.idmap'))
+ tasks.append(GrepIdmapTest(idmaps + '/a.idmap', 'bool/config_annoy_dianne', 1))
+
+ # idmap --scan
+ idmap = idmaps + '/vendor@overlay@framework_b.apk@idmap'
+ tasks.append(StopTask())
+ tasks.append(_create_setup_idmap_scan_task(idmaps, symlinks))
+ tasks.append(StartTask())
+ tasks.append(IdmapScanTask('/vendor/overlay', 'android', '/system/framework/framework-res.apk', idmaps, symlinks))
+ tasks.append(FileExistsTest(idmap))
+ tasks.append(GrepIdmapTest(idmap, 'bool/config_annoy_dianne', 1))
+
+ # overlays.list
+ overlays_list_path = '/data/resource-cache/overlays.list'
+ expected_content = '''\
+/vendor/overlay/framework_b.apk /data/resource-cache/vendor@overlay@framework_b.apk@idmap
+'''
+ tasks.append(FileExistsTest(overlays_list_path))
+ tasks.append(Md5Test(overlays_list_path, expected_content))
+
+ # idmap cleanup
+ tasks.append(RmTask(symlinks))
+ tasks.append(RmTask(idmaps))
+
+ # test no overlay
+ if opts.test_no_overlay:
+ tasks.append(StopTask())
+ tasks.append(_create_disable_overlays_task())
+ tasks.append(StartTask())
+ tasks.append(InstrumentationTask('com.android.overlaytest.WithoutOverlayTest'))
+
+ # test single overlay
+ if opts.test_single_overlay:
+ tasks.append(StopTask())
+ tasks.append(_create_enable_single_overlay_task())
+ tasks.append(StartTask())
+ tasks.append(InstrumentationTask('com.android.overlaytest.WithOverlayTest'))
+
+ # test multiple overlays
+ if opts.test_multiple_overlays:
+ tasks.append(StopTask())
+ tasks.append(_create_enable_multiple_overlays_task())
+ tasks.append(StartTask())
+ tasks.append(InstrumentationTask('com.android.overlaytest.WithMultipleOverlaysTest'))
+
+ ignored_errors = 0
+ for t in tasks:
+ type = t.get_type()
+ name = t.get_name()
+ if type == TASK_INSTRUMENTATION:
+ # InstrumentationTask will run several tests, but we want it
+ # to appear as if each test was run individually. Calling
+ # "am instrument" with a single test method is prohibitively
+ # expensive, so let's instead post-process the output to
+ # emulate individual calls.
+ retcode, stdout, stderr = t.execute()
+ if retcode != 0:
+ printer.begin(TASK_INSTRUMENTATION, name)
+ printer.end_fail(TASK_INSTRUMENTATION, name, stderr)
+ sys.exit(retcode)
+ retcode = _handle_instrumentation_task_output(stdout, printer)
+ if retcode != 0:
+ if not opts.do_continue:
+ sys.exit(retcode)
+ else:
+ ignored_errors += retcode
+ else:
+ printer.begin(type, name)
+ retcode, stdout, stderr = t.execute()
+ if retcode == 0:
+ printer.end_pass(type, name)
+ if retcode != 0:
+ if len(stderr) == 0:
+ # hope for output from stdout instead (true for eg adb shell rm)
+ stderr = stdout
+ printer.end_fail(type, name, stderr)
+ if not opts.do_continue:
+ sys.exit(retcode)
+ else:
+ ignored_errors += retcode
+ sys.exit(ignored_errors)
diff --git a/docs/html/guide/topics/renderscript/compute.jd b/docs/html/guide/topics/renderscript/compute.jd
index c62510b..297a2dc 100644
--- a/docs/html/guide/topics/renderscript/compute.jd
+++ b/docs/html/guide/topics/renderscript/compute.jd
@@ -56,7 +56,9 @@
RenderScript kernel language used in this script. Currently, 1 is the only valid value.</li>
<li>A pragma declaration (<code>#pragma rs java_package_name(com.example.app)</code>) that
-declares the package name of the Java classes reflected from this script.</li>
+declares the package name of the Java classes reflected from this script.
+Note that your .rs file must be part of your application package, and not in a
+library project.</li>
<li>Some number of invokable functions. An invokable function is a single-threaded RenderScript
function that you can call from your Java code with arbitrary arguments. These are often useful for
@@ -308,4 +310,4 @@
<li><strong>Tear down the RenderScript context.</strong> The RenderScript context can be destroyed
with {@link android.renderscript.RenderScript#destroy} or by allowing the RenderScript context
object to be garbage collected. This will cause any further use of any object belonging to that
-context to throw an exception.</li> </ol>
\ No newline at end of file
+context to throw an exception.</li> </ol>
diff --git a/graphics/java/android/graphics/pdf/PdfDocument.java b/graphics/java/android/graphics/pdf/PdfDocument.java
index 29d14a2..f5b07c1 100644
--- a/graphics/java/android/graphics/pdf/PdfDocument.java
+++ b/graphics/java/android/graphics/pdf/PdfDocument.java
@@ -82,7 +82,7 @@
private final List<PageInfo> mPages = new ArrayList<PageInfo>();
- private int mNativeDocument;
+ private long mNativeDocument;
private Page mCurrentPage;
@@ -235,20 +235,20 @@
}
}
- private native int nativeCreateDocument();
+ private native long nativeCreateDocument();
- private native void nativeClose(int document);
+ private native void nativeClose(long nativeDocument);
- private native void nativeFinishPage(int document);
+ private native void nativeFinishPage(long nativeDocument);
- private native void nativeWriteTo(int document, OutputStream out, byte[] chunk);
+ private native void nativeWriteTo(long nativeDocument, OutputStream out, byte[] chunk);
- private static native int nativeStartPage(int documentPtr, int pageWidth, int pageHeight,
+ private static native long nativeStartPage(long nativeDocument, int pageWidth, int pageHeight,
int contentLeft, int contentTop, int contentRight, int contentBottom);
private final class PdfCanvas extends Canvas {
- public PdfCanvas(int nativeCanvas) {
+ public PdfCanvas(long nativeCanvas) {
super(nativeCanvas);
}
diff --git a/include/androidfw/AssetManager.h b/include/androidfw/AssetManager.h
index a010957..a13dd16 100644
--- a/include/androidfw/AssetManager.h
+++ b/include/androidfw/AssetManager.h
@@ -69,6 +69,13 @@
*/
class AssetManager : public AAssetManager {
public:
+ static const char* RESOURCES_FILENAME;
+ static const char* IDMAP_BIN;
+ static const char* OVERLAY_DIR;
+ static const char* TARGET_PACKAGE_NAME;
+ static const char* TARGET_APK_PATH;
+ static const char* IDMAP_DIR;
+
typedef enum CacheMode {
CACHE_UNKNOWN = 0,
CACHE_OFF, // don't try to cache file locations
@@ -93,6 +100,7 @@
* newly-added asset source.
*/
bool addAssetPath(const String8& path, int32_t* cookie);
+ bool addOverlayPath(const String8& path, int32_t* cookie);
/*
* Convenience for adding the standard system assets. Uses the
@@ -218,6 +226,13 @@
*/
void getLocales(Vector<String8>* locales) const;
+ /**
+ * Generate idmap data to translate resources IDs between a package and a
+ * corresponding overlay package.
+ */
+ bool createIdmap(const char* targetApkPath, const char* overlayApkPath,
+ uint32_t targetCrc, uint32_t overlayCrc, uint32_t** outData, size_t* outSize);
+
private:
struct asset_path
{
@@ -264,19 +279,14 @@
void setLocaleLocked(const char* locale);
void updateResourceParamsLocked() const;
- bool createIdmapFileLocked(const String8& originalPath, const String8& overlayPath,
- const String8& idmapPath);
-
- bool isIdmapStaleLocked(const String8& originalPath, const String8& overlayPath,
- const String8& idmapPath);
-
Asset* openIdmapLocked(const struct asset_path& ap) const;
- bool getZipEntryCrcLocked(const String8& zipPath, const char* entryFilename, uint32_t* pCrc);
+ void addSystemOverlays(const char* pathOverlaysList, const String8& targetPackagePath,
+ ResTable* sharedRes, size_t offset) const;
class SharedZip : public RefBase {
public:
- static sp<SharedZip> get(const String8& path);
+ static sp<SharedZip> get(const String8& path, bool createIfNotPresent = true);
ZipFileRO* getZip();
@@ -287,6 +297,9 @@
ResTable* setResourceTable(ResTable* res);
bool isUpToDate();
+
+ void addOverlay(const asset_path& ap);
+ bool getOverlay(size_t idx, asset_path* out) const;
protected:
~SharedZip();
@@ -302,6 +315,8 @@
Asset* mResourceTableAsset;
ResTable* mResourceTable;
+ Vector<asset_path> mOverlays;
+
static Mutex gLock;
static DefaultKeyedVector<String8, wp<SharedZip> > gOpen;
};
@@ -334,6 +349,9 @@
static String8 getPathName(const char* path);
bool isUpToDate();
+
+ void addOverlay(const String8& path, const asset_path& overlay);
+ bool getOverlay(const String8& path, size_t idx, asset_path* out) const;
private:
void closeZip(int idx);
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index 6799766..05411ea 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -1284,7 +1284,7 @@
~ResTable();
status_t add(Asset* asset, const int32_t cookie, bool copyData,
- const void* idmap);
+ const void* idmap = NULL);
status_t add(const void *data, size_t size);
status_t add(ResTable* src);
@@ -1545,18 +1545,21 @@
// Return value: on success: NO_ERROR; caller is responsible for free-ing
// outData (using free(3)). On failure, any status_t value other than
// NO_ERROR; the caller should not free outData.
- status_t createIdmap(const ResTable& overlay, uint32_t originalCrc, uint32_t overlayCrc,
- void** outData, size_t* outSize) const;
+ status_t createIdmap(const ResTable& overlay,
+ uint32_t targetCrc, uint32_t overlayCrc,
+ const char* targetPath, const char* overlayPath,
+ void** outData, size_t* outSize) const;
enum {
- IDMAP_HEADER_SIZE_BYTES = 3 * sizeof(uint32_t),
+ IDMAP_HEADER_SIZE_BYTES = 3 * sizeof(uint32_t) + 2 * 256,
};
// Retrieve idmap meta-data.
//
// This function only requires the idmap header (the first
// IDMAP_HEADER_SIZE_BYTES) bytes of an idmap file.
static bool getIdmapInfo(const void* idmap, size_t size,
- uint32_t* pOriginalCrc, uint32_t* pOverlayCrc);
+ uint32_t* pTargetCrc, uint32_t* pOverlayCrc,
+ String8* pTargetPath, String8* pOverlayPath);
void print(bool inclValues) const;
static String8 normalizeForOutput(const char* input);
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 08328d0..5069958 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -41,10 +41,8 @@
#include <assert.h>
#include <dirent.h>
#include <errno.h>
-#include <fcntl.h>
+#include <string.h> // strerror
#include <strings.h>
-#include <sys/stat.h>
-#include <unistd.h>
#ifndef TEMP_FAILURE_RETRY
/* Used to retry syscalls that can return EINTR. */
@@ -75,7 +73,7 @@
static const char* kAssetsRoot = "assets";
static const char* kAppZipName = NULL; //"classes.jar";
static const char* kSystemAssets = "framework/framework-res.apk";
-static const char* kIdmapCacheDir = "resource-cache";
+static const char* kResourceCache = "resource-cache";
static const char* kExcludeExtension = ".EXCLUDE";
@@ -83,14 +81,20 @@
static volatile int32_t gCount = 0;
+const char* AssetManager::RESOURCES_FILENAME = "resources.arsc";
+const char* AssetManager::IDMAP_BIN = "/system/bin/idmap";
+const char* AssetManager::OVERLAY_DIR = "/vendor/overlay";
+const char* AssetManager::TARGET_PACKAGE_NAME = "android";
+const char* AssetManager::TARGET_APK_PATH = "/system/framework/framework-res.apk";
+const char* AssetManager::IDMAP_DIR = "/data/resource-cache";
+
namespace {
- // Transform string /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap
String8 idmapPathForPackagePath(const String8& pkgPath)
{
const char* root = getenv("ANDROID_DATA");
LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_DATA not set");
String8 path(root);
- path.appendPath(kIdmapCacheDir);
+ path.appendPath(kResourceCache);
char buf[256]; // 256 chars should be enough for anyone...
strncpy(buf, pkgPath.string(), 255);
@@ -208,180 +212,99 @@
*cookie = static_cast<int32_t>(mAssetPaths.size());
}
- // add overlay packages for /system/framework; apps are handled by the
- // (Java) package manager
- if (strncmp(path.string(), "/system/framework/", 18) == 0) {
- // When there is an environment variable for /vendor, this
- // should be changed to something similar to how ANDROID_ROOT
- // and ANDROID_DATA are used in this file.
- String8 overlayPath("/vendor/overlay/framework/");
- overlayPath.append(path.getPathLeaf());
- if (TEMP_FAILURE_RETRY(access(overlayPath.string(), R_OK)) == 0) {
- asset_path oap;
- oap.path = overlayPath;
- oap.type = ::getFileType(overlayPath.string());
- bool addOverlay = (oap.type == kFileTypeRegular); // only .apks supported as overlay
- if (addOverlay) {
- oap.idmap = idmapPathForPackagePath(overlayPath);
-
- if (isIdmapStaleLocked(ap.path, oap.path, oap.idmap)) {
- addOverlay = createIdmapFileLocked(ap.path, oap.path, oap.idmap);
- }
- }
- if (addOverlay) {
- mAssetPaths.add(oap);
- } else {
- ALOGW("failed to add overlay package %s\n", overlayPath.string());
- }
- }
+#ifdef HAVE_ANDROID_OS
+ // Load overlays, if any
+ asset_path oap;
+ for (size_t idx = 0; mZipSet.getOverlay(ap.path, idx, &oap); idx++) {
+ mAssetPaths.add(oap);
}
+#endif
return true;
}
-bool AssetManager::isIdmapStaleLocked(const String8& originalPath, const String8& overlayPath,
- const String8& idmapPath)
+bool AssetManager::addOverlayPath(const String8& packagePath, int32_t* cookie)
{
- struct stat st;
- if (TEMP_FAILURE_RETRY(stat(idmapPath.string(), &st)) == -1) {
- if (errno == ENOENT) {
- return true; // non-existing idmap is always stale
- } else {
- ALOGW("failed to stat file %s: %s\n", idmapPath.string(), strerror(errno));
- return false;
- }
- }
- if (st.st_size < ResTable::IDMAP_HEADER_SIZE_BYTES) {
- ALOGW("file %s has unexpectedly small size=%zd\n", idmapPath.string(), (size_t)st.st_size);
- return false;
- }
- int fd = TEMP_FAILURE_RETRY(::open(idmapPath.string(), O_RDONLY));
- if (fd == -1) {
- ALOGW("failed to open file %s: %s\n", idmapPath.string(), strerror(errno));
- return false;
- }
- char buf[ResTable::IDMAP_HEADER_SIZE_BYTES];
- ssize_t bytesLeft = ResTable::IDMAP_HEADER_SIZE_BYTES;
- for (;;) {
- ssize_t r = TEMP_FAILURE_RETRY(read(fd, buf + ResTable::IDMAP_HEADER_SIZE_BYTES - bytesLeft,
- bytesLeft));
- if (r < 0) {
- TEMP_FAILURE_RETRY(close(fd));
- return false;
- }
- bytesLeft -= r;
- if (bytesLeft == 0) {
- break;
- }
- }
- TEMP_FAILURE_RETRY(close(fd));
+ const String8 idmapPath = idmapPathForPackagePath(packagePath);
- uint32_t cachedOriginalCrc, cachedOverlayCrc;
- if (!ResTable::getIdmapInfo(buf, ResTable::IDMAP_HEADER_SIZE_BYTES,
- &cachedOriginalCrc, &cachedOverlayCrc)) {
+ AutoMutex _l(mLock);
+
+ for (size_t i = 0; i < mAssetPaths.size(); ++i) {
+ if (mAssetPaths[i].idmap == idmapPath) {
+ *cookie = static_cast<int32_t>(i + 1);
+ return true;
+ }
+ }
+
+ Asset* idmap = NULL;
+ if ((idmap = openAssetFromFileLocked(idmapPath, Asset::ACCESS_BUFFER)) == NULL) {
+ ALOGW("failed to open idmap file %s\n", idmapPath.string());
return false;
}
- uint32_t actualOriginalCrc, actualOverlayCrc;
- if (!getZipEntryCrcLocked(originalPath, "resources.arsc", &actualOriginalCrc)) {
+ String8 targetPath;
+ String8 overlayPath;
+ if (!ResTable::getIdmapInfo(idmap->getBuffer(false), idmap->getLength(),
+ NULL, NULL, &targetPath, &overlayPath)) {
+ ALOGW("failed to read idmap file %s\n", idmapPath.string());
+ delete idmap;
return false;
}
- if (!getZipEntryCrcLocked(overlayPath, "resources.arsc", &actualOverlayCrc)) {
- return false;
- }
- return cachedOriginalCrc != actualOriginalCrc || cachedOverlayCrc != actualOverlayCrc;
-}
+ delete idmap;
-bool AssetManager::getZipEntryCrcLocked(const String8& zipPath, const char* entryFilename,
- uint32_t* pCrc)
+ if (overlayPath != packagePath) {
+ ALOGW("idmap file %s inconcistent: expected path %s does not match actual path %s\n",
+ idmapPath.string(), packagePath.string(), overlayPath.string());
+ return false;
+ }
+ if (access(targetPath.string(), R_OK) != 0) {
+ ALOGW("failed to access file %s: %s\n", targetPath.string(), strerror(errno));
+ return false;
+ }
+ if (access(idmapPath.string(), R_OK) != 0) {
+ ALOGW("failed to access file %s: %s\n", idmapPath.string(), strerror(errno));
+ return false;
+ }
+ if (access(overlayPath.string(), R_OK) != 0) {
+ ALOGW("failed to access file %s: %s\n", overlayPath.string(), strerror(errno));
+ return false;
+ }
+
+ asset_path oap;
+ oap.path = overlayPath;
+ oap.type = ::getFileType(overlayPath.string());
+ oap.idmap = idmapPath;
+#if 0
+ ALOGD("Overlay added: targetPath=%s overlayPath=%s idmapPath=%s\n",
+ targetPath.string(), overlayPath.string(), idmapPath.string());
+#endif
+ mAssetPaths.add(oap);
+ *cookie = static_cast<int32_t>(mAssetPaths.size());
+
+ return true;
+ }
+
+bool AssetManager::createIdmap(const char* targetApkPath, const char* overlayApkPath,
+ uint32_t targetCrc, uint32_t overlayCrc, uint32_t** outData, size_t* outSize)
{
- asset_path ap;
- ap.path = zipPath;
- const ZipFileRO* zip = getZipFileLocked(ap);
- if (zip == NULL) {
- return false;
- }
- const ZipEntryRO entry = zip->findEntryByName(entryFilename);
- if (entry == NULL) {
- return false;
- }
-
- const bool gotInfo = zip->getEntryInfo(entry, NULL, NULL, NULL, NULL, NULL, (long*)pCrc);
- zip->releaseEntry(entry);
-
- return gotInfo;
-}
-
-bool AssetManager::createIdmapFileLocked(const String8& originalPath, const String8& overlayPath,
- const String8& idmapPath)
-{
- ALOGD("%s: originalPath=%s overlayPath=%s idmapPath=%s\n",
- __FUNCTION__, originalPath.string(), overlayPath.string(), idmapPath.string());
+ AutoMutex _l(mLock);
+ const String8 paths[2] = { String8(targetApkPath), String8(overlayApkPath) };
ResTable tables[2];
- const String8* paths[2] = { &originalPath, &overlayPath };
- uint32_t originalCrc, overlayCrc;
- bool retval = false;
- ssize_t offset = 0;
- int fd = 0;
- uint32_t* data = NULL;
- size_t size;
for (int i = 0; i < 2; ++i) {
asset_path ap;
ap.type = kFileTypeRegular;
- ap.path = *paths[i];
+ ap.path = paths[i];
Asset* ass = openNonAssetInPathLocked("resources.arsc", Asset::ACCESS_BUFFER, ap);
if (ass == NULL) {
ALOGW("failed to find resources.arsc in %s\n", ap.path.string());
- goto error;
+ return false;
}
tables[i].add(ass, 1, false /* copyData */, NULL /* idMap */);
}
- if (!getZipEntryCrcLocked(originalPath, "resources.arsc", &originalCrc)) {
- ALOGW("failed to retrieve crc for resources.arsc in %s\n", originalPath.string());
- goto error;
- }
- if (!getZipEntryCrcLocked(overlayPath, "resources.arsc", &overlayCrc)) {
- ALOGW("failed to retrieve crc for resources.arsc in %s\n", overlayPath.string());
- goto error;
- }
-
- if (tables[0].createIdmap(tables[1], originalCrc, overlayCrc,
- (void**)&data, &size) != NO_ERROR) {
- ALOGW("failed to generate idmap data for file %s\n", idmapPath.string());
- goto error;
- }
-
- // This should be abstracted (eg replaced by a stand-alone
- // application like dexopt, triggered by something equivalent to
- // installd).
- fd = TEMP_FAILURE_RETRY(::open(idmapPath.string(), O_WRONLY | O_CREAT | O_TRUNC, 0644));
- if (fd == -1) {
- ALOGW("failed to write idmap file %s (open: %s)\n", idmapPath.string(), strerror(errno));
- goto error_free;
- }
- for (;;) {
- ssize_t written = TEMP_FAILURE_RETRY(write(fd, data + offset, size));
- if (written < 0) {
- ALOGW("failed to write idmap file %s (write: %s)\n", idmapPath.string(),
- strerror(errno));
- goto error_close;
- }
- size -= (size_t)written;
- offset += written;
- if (size == 0) {
- break;
- }
- }
-
- retval = true;
-error_close:
- TEMP_FAILURE_RETRY(close(fd));
-error_free:
- free(data);
-error:
- return retval;
+ return tables[0].createIdmap(tables[1], targetCrc, overlayCrc,
+ targetApkPath, overlayApkPath, (void**)outData, outSize) == NO_ERROR;
}
bool AssetManager::addDefaultAssets()
@@ -660,6 +583,10 @@
// which we want to avoid parsing every time.
sharedRes = const_cast<AssetManager*>(this)->
mZipSet.getZipResourceTable(ap.path);
+ if (sharedRes != NULL) {
+ // skip ahead the number of system overlay packages preloaded
+ i += sharedRes->getTableCount() - 1;
+ }
}
if (sharedRes == NULL) {
ass = const_cast<AssetManager*>(this)->
@@ -683,6 +610,14 @@
ALOGV("Creating shared resources for %s", ap.path.string());
sharedRes = new ResTable();
sharedRes->add(ass, i + 1, false, idmap);
+#ifdef HAVE_ANDROID_OS
+ const char* data = getenv("ANDROID_DATA");
+ LOG_ALWAYS_FATAL_IF(data == NULL, "ANDROID_DATA not set");
+ String8 overlaysListPath(data);
+ overlaysListPath.appendPath(kResourceCache);
+ overlaysListPath.appendPath("overlays.list");
+ addSystemOverlays(overlaysListPath.string(), ap.path, sharedRes, i);
+#endif
sharedRes = const_cast<AssetManager*>(this)->
mZipSet.setZipResourceTable(ap.path, sharedRes);
}
@@ -766,6 +701,46 @@
return ass;
}
+void AssetManager::addSystemOverlays(const char* pathOverlaysList,
+ const String8& targetPackagePath, ResTable* sharedRes, size_t offset) const
+{
+ FILE* fin = fopen(pathOverlaysList, "r");
+ if (fin == NULL) {
+ return;
+ }
+
+ char buf[1024];
+ while (fgets(buf, sizeof(buf), fin)) {
+ // format of each line:
+ // <path to apk><space><path to idmap><newline>
+ char* space = strchr(buf, ' ');
+ char* newline = strchr(buf, '\n');
+ asset_path oap;
+
+ if (space == NULL || newline == NULL || newline < space) {
+ continue;
+ }
+
+ oap.path = String8(buf, space - buf);
+ oap.type = kFileTypeRegular;
+ oap.idmap = String8(space + 1, newline - space - 1);
+
+ Asset* oass = const_cast<AssetManager*>(this)->
+ openNonAssetInPathLocked("resources.arsc",
+ Asset::ACCESS_BUFFER,
+ oap);
+
+ if (oass != NULL) {
+ Asset* oidmap = openIdmapLocked(oap);
+ offset++;
+ sharedRes->add(oass, offset + 1, false, oidmap);
+ const_cast<AssetManager*>(this)->mAssetPaths.add(oap);
+ const_cast<AssetManager*>(this)->mZipSet.addOverlay(targetPackagePath, oap);
+ }
+ }
+ fclose(fin);
+}
+
const ResTable& AssetManager::getResources(bool required) const
{
const ResTable* rt = getResTable(required);
@@ -1824,7 +1799,8 @@
}
}
-sp<AssetManager::SharedZip> AssetManager::SharedZip::get(const String8& path)
+sp<AssetManager::SharedZip> AssetManager::SharedZip::get(const String8& path,
+ bool createIfNotPresent)
{
AutoMutex _l(gLock);
time_t modWhen = getFileModDate(path);
@@ -1832,6 +1808,9 @@
if (zip != NULL && zip->mModWhen == modWhen) {
return zip;
}
+ if (zip == NULL && !createIfNotPresent) {
+ return NULL;
+ }
zip = new SharedZip(path, modWhen);
gOpen.add(path, zip);
return zip;
@@ -1890,6 +1869,20 @@
return mModWhen == modWhen;
}
+void AssetManager::SharedZip::addOverlay(const asset_path& ap)
+{
+ mOverlays.add(ap);
+}
+
+bool AssetManager::SharedZip::getOverlay(size_t idx, asset_path* out) const
+{
+ if (idx >= mOverlays.size()) {
+ return false;
+ }
+ *out = mOverlays[idx];
+ return true;
+}
+
AssetManager::SharedZip::~SharedZip()
{
//ALOGI("Destroying SharedZip %p %s\n", this, (const char*)mPath);
@@ -2013,6 +2006,22 @@
return true;
}
+void AssetManager::ZipSet::addOverlay(const String8& path, const asset_path& overlay)
+{
+ int idx = getIndex(path);
+ sp<SharedZip> zip = mZipFile[idx];
+ zip->addOverlay(overlay);
+}
+
+bool AssetManager::ZipSet::getOverlay(const String8& path, size_t idx, asset_path* out) const
+{
+ sp<SharedZip> zip = SharedZip::get(path, false);
+ if (zip == NULL) {
+ return false;
+ }
+ return zip->getOverlay(idx, out);
+}
+
/*
* Compute the zip file's index.
*
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 72d331c..8cc98af 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -284,11 +284,37 @@
if (!assertIdmapHeader(map, mapSize)) {
return UNKNOWN_ERROR;
}
+ if (mapSize <= IDMAP_HEADER_SIZE + 1) {
+ ALOGW("corrupt idmap: map size %d too short\n", mapSize);
+ return UNKNOWN_ERROR;
+ }
+ uint32_t typeCount = *(map + IDMAP_HEADER_SIZE);
+ if (typeCount == 0) {
+ ALOGW("corrupt idmap: no types\n");
+ return UNKNOWN_ERROR;
+ }
+ if (IDMAP_HEADER_SIZE + 1 + typeCount > mapSize) {
+ ALOGW("corrupt idmap: number of types %d extends past idmap size %d\n", typeCount, mapSize);
+ return UNKNOWN_ERROR;
+ }
const uint32_t* p = map + IDMAP_HEADER_SIZE + 1;
+ // find first defined type
while (*p == 0) {
++p;
+ if (--typeCount == 0) {
+ ALOGW("corrupt idmap: types declared, none found\n");
+ return UNKNOWN_ERROR;
+ }
}
- *outId = (map[*p + IDMAP_HEADER_SIZE + 2] >> 24) & 0x000000ff;
+
+ // determine package id from first entry of first type
+ const uint32_t offset = *p + IDMAP_HEADER_SIZE + 2;
+ if (offset > mapSize) {
+ ALOGW("corrupt idmap: entry offset %d points outside map size %d\n", offset, mapSize);
+ return UNKNOWN_ERROR;
+ }
+ *outId = (map[offset] >> 24) & 0x000000ff;
+
return NO_ERROR;
}
@@ -5334,23 +5360,30 @@
return NO_ERROR;
}
-status_t ResTable::createIdmap(const ResTable& overlay, uint32_t originalCrc, uint32_t overlayCrc,
- void** outData, size_t* outSize) const
+status_t ResTable::createIdmap(const ResTable& overlay,
+ uint32_t targetCrc, uint32_t overlayCrc,
+ const char* targetPath, const char* overlayPath,
+ void** outData, size_t* outSize) const
{
// see README for details on the format of map
if (mPackageGroups.size() == 0) {
+ ALOGW("idmap: target package has no package groups, cannot create idmap\n");
return UNKNOWN_ERROR;
}
if (mPackageGroups[0]->packages.size() == 0) {
+ ALOGW("idmap: target package has no packages in its first package group, "
+ "cannot create idmap\n");
return UNKNOWN_ERROR;
}
Vector<Vector<uint32_t> > map;
+ // overlaid packages are assumed to contain only one package group
const PackageGroup* pg = mPackageGroups[0];
const Package* pkg = pg->packages[0];
size_t typeCount = pkg->types.size();
// starting size is header + first item (number of types in map)
*outSize = (IDMAP_HEADER_SIZE + 1) * sizeof(uint32_t);
+ // overlay packages are assumed to contain only one package group
const String16 overlayPackage(overlay.mPackageGroups[0]->packages[0]->package->name);
const uint32_t pkg_id = pkg->package->id << 24;
@@ -5368,7 +5401,7 @@
| (0x00ff0000 & ((typeIndex+1)<<16))
| (0x0000ffff & (entryIndex));
resource_name resName;
- if (!this->getResourceName(resID, true, &resName)) {
+ if (!this->getResourceName(resID, false, &resName)) {
ALOGW("idmap: resource 0x%08x has spec but lacks values, skipping\n", resID);
// add dummy value, or trimming leading/trailing zeroes later will fail
vector.push(0);
@@ -5426,8 +5459,22 @@
}
uint32_t* data = (uint32_t*)*outData;
*data++ = htodl(IDMAP_MAGIC);
- *data++ = htodl(originalCrc);
+ *data++ = htodl(targetCrc);
*data++ = htodl(overlayCrc);
+ const char* paths[] = { targetPath, overlayPath };
+ for (int j = 0; j < 2; ++j) {
+ char* p = (char*)data;
+ const char* path = paths[j];
+ const size_t I = strlen(path);
+ if (I > 255) {
+ ALOGV("path exceeds expected 255 characters: %s\n", path);
+ return UNKNOWN_ERROR;
+ }
+ for (size_t i = 0; i < 256; ++i) {
+ *p++ = i < I ? path[i] : '\0';
+ }
+ data += 256 / sizeof(uint32_t);
+ }
const size_t mapSize = map.size();
*data++ = htodl(mapSize);
size_t offset = mapSize;
@@ -5442,6 +5489,10 @@
offset += N;
}
}
+ if (offset == mapSize) {
+ ALOGW("idmap: no resources in overlay package present in base package\n");
+ return UNKNOWN_ERROR;
+ }
for (size_t i = 0; i < mapSize; ++i) {
const Vector<uint32_t>& vector = map.itemAt(i);
const size_t N = vector.size();
@@ -5463,14 +5514,25 @@
}
bool ResTable::getIdmapInfo(const void* idmap, size_t sizeBytes,
- uint32_t* pOriginalCrc, uint32_t* pOverlayCrc)
+ uint32_t* pTargetCrc, uint32_t* pOverlayCrc,
+ String8* pTargetPath, String8* pOverlayPath)
{
const uint32_t* map = (const uint32_t*)idmap;
if (!assertIdmapHeader(map, sizeBytes)) {
return false;
}
- *pOriginalCrc = map[1];
- *pOverlayCrc = map[2];
+ if (pTargetCrc) {
+ *pTargetCrc = map[1];
+ }
+ if (pOverlayCrc) {
+ *pOverlayCrc = map[2];
+ }
+ if (pTargetPath) {
+ pTargetPath->setTo(reinterpret_cast<const char*>(map + 3));
+ }
+ if (pOverlayPath) {
+ pOverlayPath->setTo(reinterpret_cast<const char*>(map + 3 + 256 / sizeof(uint32_t)));
+ }
return true;
}
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index 18983d8..8f5beb8 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -404,10 +404,10 @@
// If it's still not valid, we couldn't cache it, so we shouldn't
// draw garbage; also skip empty glyphs (spaces)
if (cachedGlyph->mIsValid && cachedGlyph->mCacheTexture) {
- float penX = x + positions[(glyphsCount << 1)];
- float penY = y + positions[(glyphsCount << 1) + 1];
+ int penX = x + (int) roundf(positions[(glyphsCount << 1)]);
+ int penY = y + (int) roundf(positions[(glyphsCount << 1) + 1]);
- (*this.*render)(cachedGlyph, roundf(penX), roundf(penY),
+ (*this.*render)(cachedGlyph, penX, penY,
bitmap, bitmapW, bitmapH, bounds, positions);
}
diff --git a/libs/hwui/utils/TinyHashMap.h b/libs/hwui/utils/TinyHashMap.h
index 8855140..4ff9a42 100644
--- a/libs/hwui/utils/TinyHashMap.h
+++ b/libs/hwui/utils/TinyHashMap.h
@@ -24,8 +24,6 @@
/**
* A very simple hash map that doesn't allow duplicate keys, overwriting the older entry.
- *
- * Currently, expects simple keys that are handled by hash_t()
*/
template <typename TKey, typename TValue>
class TinyHashMap {
@@ -36,7 +34,7 @@
* Puts an entry in the hash, removing any existing entry with the same key
*/
void put(TKey key, TValue value) {
- hash_t hash = hash_t(key);
+ hash_t hash = android::hash_type(key);
ssize_t index = mTable.find(-1, hash, key);
if (index != -1) {
@@ -51,7 +49,7 @@
* Return true if key is in the map, in which case stores the value in the output ref
*/
bool get(TKey key, TValue& outValue) {
- hash_t hash = hash_t(key);
+ hash_t hash = android::hash_type(key);
ssize_t index = mTable.find(-1, hash, key);
if (index == -1) {
return false;
diff --git a/media/jni/android_media_MediaMuxer.cpp b/media/jni/android_media_MediaMuxer.cpp
index 2c16a05..3561b06 100644
--- a/media/jni/android_media_MediaMuxer.cpp
+++ b/media/jni/android_media_MediaMuxer.cpp
@@ -132,7 +132,7 @@
}
// Constructor counterpart.
-static jint android_media_MediaMuxer_native_setup(
+static jlong android_media_MediaMuxer_native_setup(
JNIEnv *env, jclass clazz, jobject fileDescriptor,
jint format) {
int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
@@ -142,7 +142,7 @@
static_cast<MediaMuxer::OutputFormat>(format);
sp<MediaMuxer> muxer = new MediaMuxer(fd, fileFormat);
muxer->incStrong(clazz);
- return int(muxer.get());
+ return reinterpret_cast<jlong>(muxer.get());
}
static void android_media_MediaMuxer_setOrientationHint(
diff --git a/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java b/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java
index c2f4400..1902a40 100644
--- a/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLConfigImpl.java
@@ -19,13 +19,13 @@
import javax.microedition.khronos.egl.*;
public class EGLConfigImpl extends EGLConfig {
- private int mEGLConfig;
+ private long mEGLConfig;
- EGLConfigImpl(int config) {
+ EGLConfigImpl(long config) {
mEGLConfig = config;
}
- int get() {
+ long get() {
return mEGLConfig;
}
}
diff --git a/opengl/java/com/google/android/gles_jni/EGLContextImpl.java b/opengl/java/com/google/android/gles_jni/EGLContextImpl.java
index cd36099..47369ac 100644
--- a/opengl/java/com/google/android/gles_jni/EGLContextImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLContextImpl.java
@@ -21,13 +21,13 @@
public class EGLContextImpl extends EGLContext {
private GLImpl mGLContext;
- int mEGLContext;
-
- public EGLContextImpl(int ctx) {
+ long mEGLContext;
+
+ public EGLContextImpl(long ctx) {
mEGLContext = ctx;
mGLContext = new GLImpl();
}
-
+
@Override
public GL getGL() {
return mGLContext;
@@ -45,6 +45,12 @@
@Override
public int hashCode() {
- return mEGLContext;
+ /*
+ * Based on the algorithm suggested in
+ * http://developer.android.com/reference/java/lang/Object.html
+ */
+ int result = 17;
+ result = 31 * result + (int) (mEGLContext ^ (mEGLContext >>> 32));
+ return result;
}
}
diff --git a/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java b/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java
index e6c9817..9b932fc 100644
--- a/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLDisplayImpl.java
@@ -19,9 +19,9 @@
import javax.microedition.khronos.egl.*;
public class EGLDisplayImpl extends EGLDisplay {
- int mEGLDisplay;
+ long mEGLDisplay;
- public EGLDisplayImpl(int dpy) {
+ public EGLDisplayImpl(long dpy) {
mEGLDisplay = dpy;
}
@@ -38,6 +38,12 @@
@Override
public int hashCode() {
- return mEGLDisplay;
+ /*
+ * Based on the algorithm suggested in
+ * http://developer.android.com/reference/java/lang/Object.html
+ */
+ int result = 17;
+ result = 31 * result + (int) (mEGLDisplay ^ (mEGLDisplay >>> 32));
+ return result;
}
}
diff --git a/opengl/java/com/google/android/gles_jni/EGLImpl.java b/opengl/java/com/google/android/gles_jni/EGLImpl.java
index 64a54c2..41fb072 100644
--- a/opengl/java/com/google/android/gles_jni/EGLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLImpl.java
@@ -51,7 +51,7 @@
public static native int getInitCount(EGLDisplay display);
public EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list) {
- int eglContextId = _eglCreateContext(display, config, share_context, attrib_list);
+ long eglContextId = _eglCreateContext(display, config, share_context, attrib_list);
if (eglContextId == 0) {
return EGL10.EGL_NO_CONTEXT;
}
@@ -59,7 +59,7 @@
}
public EGLSurface eglCreatePbufferSurface(EGLDisplay display, EGLConfig config, int[] attrib_list) {
- int eglSurfaceId = _eglCreatePbufferSurface(display, config, attrib_list);
+ long eglSurfaceId = _eglCreatePbufferSurface(display, config, attrib_list);
if (eglSurfaceId == 0) {
return EGL10.EGL_NO_SURFACE;
}
@@ -87,7 +87,7 @@
sur = (Surface) native_window;
}
- int eglSurfaceId;
+ long eglSurfaceId;
if (sur != null) {
eglSurfaceId = _eglCreateWindowSurface(display, config, sur, attrib_list);
} else if (native_window instanceof SurfaceTexture) {
@@ -106,7 +106,7 @@
}
public synchronized EGLDisplay eglGetDisplay(Object native_display) {
- int value = _eglGetDisplay(native_display);
+ long value = _eglGetDisplay(native_display);
if (value == 0) {
return EGL10.EGL_NO_DISPLAY;
}
@@ -116,7 +116,7 @@
}
public synchronized EGLContext eglGetCurrentContext() {
- int value = _eglGetCurrentContext();
+ long value = _eglGetCurrentContext();
if (value == 0) {
return EGL10.EGL_NO_CONTEXT;
}
@@ -126,7 +126,7 @@
}
public synchronized EGLDisplay eglGetCurrentDisplay() {
- int value = _eglGetCurrentDisplay();
+ long value = _eglGetCurrentDisplay();
if (value == 0) {
return EGL10.EGL_NO_DISPLAY;
}
@@ -136,7 +136,7 @@
}
public synchronized EGLSurface eglGetCurrentSurface(int readdraw) {
- int value = _eglGetCurrentSurface(readdraw);
+ long value = _eglGetCurrentSurface(readdraw);
if (value == 0) {
return EGL10.EGL_NO_SURFACE;
}
@@ -145,15 +145,15 @@
return mSurface;
}
- private native int _eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list);
- private native int _eglCreatePbufferSurface(EGLDisplay display, EGLConfig config, int[] attrib_list);
+ private native long _eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list);
+ private native long _eglCreatePbufferSurface(EGLDisplay display, EGLConfig config, int[] attrib_list);
private native void _eglCreatePixmapSurface(EGLSurface sur, EGLDisplay display, EGLConfig config, Object native_pixmap, int[] attrib_list);
- private native int _eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list);
- private native int _eglCreateWindowSurfaceTexture(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list);
- private native int _eglGetDisplay(Object native_display);
- private native int _eglGetCurrentContext();
- private native int _eglGetCurrentDisplay();
- private native int _eglGetCurrentSurface(int readdraw);
+ private native long _eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list);
+ private native long _eglCreateWindowSurfaceTexture(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list);
+ private native long _eglGetDisplay(Object native_display);
+ private native long _eglGetCurrentContext();
+ private native long _eglGetCurrentDisplay();
+ private native long _eglGetCurrentSurface(int readdraw);
native private static void _nativeClassInit();
static { _nativeClassInit(); }
diff --git a/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java b/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
index e7f15dc..7a3ed24 100644
--- a/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
+++ b/opengl/java/com/google/android/gles_jni/EGLSurfaceImpl.java
@@ -19,13 +19,13 @@
import javax.microedition.khronos.egl.*;
public class EGLSurfaceImpl extends EGLSurface {
- int mEGLSurface;
- private int mNativePixelRef;
+ long mEGLSurface;
+ private long mNativePixelRef;
public EGLSurfaceImpl() {
mEGLSurface = 0;
mNativePixelRef = 0;
}
- public EGLSurfaceImpl(int surface) {
+ public EGLSurfaceImpl(long surface) {
mEGLSurface = surface;
mNativePixelRef = 0;
}
@@ -43,6 +43,12 @@
@Override
public int hashCode() {
- return mEGLSurface;
+ /*
+ * Based on the algorithm suggested in
+ * http://developer.android.com/reference/java/lang/Object.html
+ */
+ int result = 17;
+ result = 31 * result + (int) (mEGLSurface ^ (mEGLSurface >>> 32));
+ return result;
}
}
diff --git a/rs/java/android/renderscript/Allocation.java b/rs/java/android/renderscript/Allocation.java
index 67d94f9..c2bab91 100644
--- a/rs/java/android/renderscript/Allocation.java
+++ b/rs/java/android/renderscript/Allocation.java
@@ -81,6 +81,65 @@
new HashMap<Long, Allocation>();
OnBufferAvailableListener mBufferNotifier;
+ private Element.DataType validateObjectIsPrimitiveArray(Object d, boolean checkType) {
+ final Class c = d.getClass();
+ if (!c.isArray()) {
+ throw new RSIllegalArgumentException("Object passed is not an array of primitives.");
+ }
+ final Class cmp = c.getComponentType();
+ if (!cmp.isPrimitive()) {
+ throw new RSIllegalArgumentException("Object passed is not an Array of primitives.");
+ }
+
+ if (cmp == Long.TYPE) {
+ if (checkType) {
+ validateIsInt64();
+ return mType.mElement.mType;
+ }
+ return Element.DataType.SIGNED_64;
+ }
+
+ if (cmp == Integer.TYPE) {
+ if (checkType) {
+ validateIsInt32();
+ return mType.mElement.mType;
+ }
+ return Element.DataType.SIGNED_32;
+ }
+
+ if (cmp == Short.TYPE) {
+ if (checkType) {
+ validateIsInt16();
+ return mType.mElement.mType;
+ }
+ return Element.DataType.SIGNED_16;
+ }
+
+ if (cmp == Byte.TYPE) {
+ if (checkType) {
+ validateIsInt8();
+ return mType.mElement.mType;
+ }
+ return Element.DataType.SIGNED_8;
+ }
+
+ if (cmp == Float.TYPE) {
+ if (checkType) {
+ validateIsFloat32();
+ }
+ return Element.DataType.FLOAT_32;
+ }
+
+ if (cmp == Double.TYPE) {
+ if (checkType) {
+ validateIsFloat64();
+ }
+ return Element.DataType.FLOAT_64;
+ }
+ return null;
+ }
+
+
/**
* The usage of the Allocation. These signal to RenderScript where to place
* the Allocation in memory.
@@ -292,6 +351,15 @@
super.finalize();
}
+ private void validateIsInt64() {
+ if ((mType.mElement.mType == Element.DataType.SIGNED_64) ||
+ (mType.mElement.mType == Element.DataType.UNSIGNED_64)) {
+ return;
+ }
+ throw new RSIllegalArgumentException(
+ "64 bit integer source does not match allocation type " + mType.mElement.mType);
+ }
+
private void validateIsInt32() {
if ((mType.mElement.mType == Element.DataType.SIGNED_32) ||
(mType.mElement.mType == Element.DataType.UNSIGNED_32)) {
@@ -327,6 +395,14 @@
"32 bit float source does not match allocation type " + mType.mElement.mType);
}
+ private void validateIsFloat64() {
+ if (mType.mElement.mType == Element.DataType.FLOAT_64) {
+ return;
+ }
+ throw new RSIllegalArgumentException(
+ "64 bit float source does not match allocation type " + mType.mElement.mType);
+ }
+
private void validateIsObject() {
if ((mType.mElement.mType == Element.DataType.RS_ELEMENT) ||
(mType.mElement.mType == Element.DataType.RS_TYPE) ||
@@ -507,6 +583,34 @@
}
}
+ private void copyFromUnchecked(Object array, Element.DataType dt, int arrayLen) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
+ mRS.validate();
+ if (mCurrentDimZ > 0) {
+ copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, array, dt, arrayLen);
+ } else if (mCurrentDimY > 0) {
+ copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, array, dt, arrayLen);
+ } else {
+ copy1DRangeFromUnchecked(0, mCurrentCount, array, dt, arrayLen);
+ }
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * Copy into this Allocation from an array. This method does not guarantee
+ * that the Allocation is compatible with the input buffer; it copies memory
+ * without reinterpretation.
+ *
+ * @param array The source data array
+ * @hide
+ */
+ public void copyFromUnchecked(Object array) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
+ copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, false),
+ java.lang.reflect.Array.getLength(array));
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
/**
* Copy into this Allocation from an array. This method does not guarantee
* that the Allocation is compatible with the input buffer; it copies memory
@@ -515,16 +619,7 @@
* @param d the source data array
*/
public void copyFromUnchecked(int[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
- mRS.validate();
- if (mCurrentDimZ > 0) {
- copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d);
- } else if (mCurrentDimY > 0) {
- copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d);
- } else {
- copy1DRangeFromUnchecked(0, mCurrentCount, d);
- }
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copyFromUnchecked(d, Element.DataType.SIGNED_32, d.length);
}
/**
@@ -535,16 +630,7 @@
* @param d the source data array
*/
public void copyFromUnchecked(short[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
- mRS.validate();
- if (mCurrentDimZ > 0) {
- copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d);
- } else if (mCurrentDimY > 0) {
- copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d);
- } else {
- copy1DRangeFromUnchecked(0, mCurrentCount, d);
- }
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length);
}
/**
@@ -555,16 +641,7 @@
* @param d the source data array
*/
public void copyFromUnchecked(byte[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
- mRS.validate();
- if (mCurrentDimZ > 0) {
- copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d);
- } else if (mCurrentDimY > 0) {
- copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d);
- } else {
- copy1DRangeFromUnchecked(0, mCurrentCount, d);
- }
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copyFromUnchecked(d, Element.DataType.SIGNED_8, d.length);
}
/**
@@ -575,37 +652,36 @@
* @param d the source data array
*/
public void copyFromUnchecked(float[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copyFromUnchecked");
- mRS.validate();
- if (mCurrentDimZ > 0) {
- copy3DRangeFromUnchecked(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d);
- } else if (mCurrentDimY > 0) {
- copy2DRangeFromUnchecked(0, 0, mCurrentDimX, mCurrentDimY, d);
- } else {
- copy1DRangeFromUnchecked(0, mCurrentCount, d);
- }
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copyFromUnchecked(d, Element.DataType.FLOAT_32, d.length);
}
/**
* Copy into this Allocation from an array. This variant is type checked
* and will generate exceptions if the Allocation's {@link
+ * android.renderscript.Element} does not match the array's
+ * primitive type.
+ *
+ * @param d the source data array
+ * @hide
+ */
+ public void copyFrom(Object array) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
+ copyFromUnchecked(array, validateObjectIsPrimitiveArray(array, true),
+ java.lang.reflect.Array.getLength(array));
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * Copy into this Allocation from an array. This variant is type checked
+ * and will generate exceptions if the Allocation's {@link
* android.renderscript.Element} is not a 32 bit integer type.
*
* @param d the source data array
*/
public void copyFrom(int[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
- mRS.validate();
- if (mCurrentDimZ > 0) {
- copy3DRangeFrom(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d);
- } else if (mCurrentDimY > 0) {
- copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d);
- } else {
- copy1DRangeFrom(0, mCurrentCount, d);
- }
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ validateIsInt32();
+ copyFromUnchecked(d, Element.DataType.SIGNED_32, d.length);
}
/**
@@ -616,16 +692,8 @@
* @param d the source data array
*/
public void copyFrom(short[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
- mRS.validate();
- if (mCurrentDimZ > 0) {
- copy3DRangeFrom(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d);
- } else if (mCurrentDimY > 0) {
- copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d);
- } else {
- copy1DRangeFrom(0, mCurrentCount, d);
- }
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ validateIsInt16();
+ copyFromUnchecked(d, Element.DataType.SIGNED_16, d.length);
}
/**
@@ -636,16 +704,8 @@
* @param d the source data array
*/
public void copyFrom(byte[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
- mRS.validate();
- if (mCurrentDimZ > 0) {
- copy3DRangeFrom(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d);
- } else if (mCurrentDimY > 0) {
- copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d);
- } else {
- copy1DRangeFrom(0, mCurrentCount, d);
- }
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ validateIsInt8();
+ copyFromUnchecked(d, Element.DataType.SIGNED_8, d.length);
}
/**
@@ -656,16 +716,8 @@
* @param d the source data array
*/
public void copyFrom(float[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copyFrom");
- mRS.validate();
- if (mCurrentDimZ > 0) {
- copy3DRangeFrom(0, 0, 0, mCurrentDimX, mCurrentDimY, mCurrentDimZ, d);
- } else if (mCurrentDimY > 0) {
- copy2DRangeFrom(0, 0, mCurrentDimX, mCurrentDimY, d);
- } else {
- copy1DRangeFrom(0, mCurrentCount, d);
- }
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ validateIsFloat32();
+ copyFromUnchecked(d, Element.DataType.FLOAT_32, d.length);
}
/**
@@ -794,6 +846,30 @@
mRS.nAllocationGenerateMipmaps(getID(mRS));
}
+ private void copy1DRangeFromUnchecked(int off, int count, Object array,
+ Element.DataType dt, int arrayLen) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked");
+ final int dataSize = mType.mElement.getBytesSize() * count;
+ data1DChecks(off, count, arrayLen * dt.mSize, dataSize);
+ mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, array, dataSize, dt);
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * Copy an array into part of this Allocation. This method does not
+ * guarantee that the Allocation is compatible with the input buffer.
+ *
+ * @param off The offset of the first element to be copied.
+ * @param count The number of elements to be copied.
+ * @param array The source data array
+ * @hide
+ */
+ public void copy1DRangeFromUnchecked(int off, int count, Object array) {
+ copy1DRangeFromUnchecked(off, count, array,
+ validateObjectIsPrimitiveArray(array, false),
+ java.lang.reflect.Array.getLength(array));
+ }
+
/**
* Copy an array into part of this Allocation. This method does not
* guarantee that the Allocation is compatible with the input buffer.
@@ -803,11 +879,7 @@
* @param d the source data array
*/
public void copy1DRangeFromUnchecked(int off, int count, int[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked");
- int dataSize = mType.mElement.getBytesSize() * count;
- data1DChecks(off, count, d.length * 4, dataSize);
- mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize, Element.DataType.SIGNED_32);
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_32, d.length);
}
/**
@@ -819,11 +891,7 @@
* @param d the source data array
*/
public void copy1DRangeFromUnchecked(int off, int count, short[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked");
- int dataSize = mType.mElement.getBytesSize() * count;
- data1DChecks(off, count, d.length * 2, dataSize);
- mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize, Element.DataType.SIGNED_16);
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_16, d.length);
}
/**
@@ -835,11 +903,7 @@
* @param d the source data array
*/
public void copy1DRangeFromUnchecked(int off, int count, byte[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked");
- int dataSize = mType.mElement.getBytesSize() * count;
- data1DChecks(off, count, d.length, dataSize);
- mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize, Element.DataType.SIGNED_8);
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.SIGNED_8, d.length);
}
/**
@@ -851,11 +915,24 @@
* @param d the source data array
*/
public void copy1DRangeFromUnchecked(int off, int count, float[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFromUnchecked");
- int dataSize = mType.mElement.getBytesSize() * count;
- data1DChecks(off, count, d.length * 4, dataSize);
- mRS.nAllocationData1D(getIDSafe(), off, mSelectedLOD, count, d, dataSize, Element.DataType.FLOAT_32);
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copy1DRangeFromUnchecked(off, count, (Object)d, Element.DataType.FLOAT_32, d.length);
+ }
+
+
+ /**
+ * Copy an array into part of this Allocation. This variant is type checked
+ * and will generate exceptions if the Allocation type does not
+ * match the component type of the array passed in.
+ *
+ * @param off The offset of the first element to be copied.
+ * @param count The number of elements to be copied.
+ * @param array The source data array.
+ * @hide
+ */
+ public void copy1DRangeFrom(int off, int count, Object array) {
+ copy1DRangeFromUnchecked(off, count, array,
+ validateObjectIsPrimitiveArray(array, true),
+ java.lang.reflect.Array.getLength(array));
}
/**
@@ -868,10 +945,8 @@
* @param d the source data array
*/
public void copy1DRangeFrom(int off, int count, int[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom");
validateIsInt32();
- copy1DRangeFromUnchecked(off, count, d);
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_32, d.length);
}
/**
@@ -884,10 +959,8 @@
* @param d the source data array
*/
public void copy1DRangeFrom(int off, int count, short[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom");
validateIsInt16();
- copy1DRangeFromUnchecked(off, count, d);
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_16, d.length);
}
/**
@@ -900,10 +973,8 @@
* @param d the source data array
*/
public void copy1DRangeFrom(int off, int count, byte[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom");
validateIsInt8();
- copy1DRangeFromUnchecked(off, count, d);
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copy1DRangeFromUnchecked(off, count, d, Element.DataType.SIGNED_8, d.length);
}
/**
@@ -916,11 +987,10 @@
* @param d the source data array.
*/
public void copy1DRangeFrom(int off, int count, float[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copy1DRangeFrom");
validateIsFloat32();
- copy1DRangeFromUnchecked(off, count, d);
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copy1DRangeFromUnchecked(off, count, d, Element.DataType.FLOAT_32, d.length);
}
+
/**
* Copy part of an Allocation into this Allocation.
*
@@ -955,39 +1025,32 @@
}
}
- void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, byte[] data) {
+ void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, Object array,
+ Element.DataType dt, int arrayLen) {
Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked");
mRS.validate();
validate2DRange(xoff, yoff, w, h);
- mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
- w, h, data, data.length, Element.DataType.SIGNED_8);
+ mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID, w, h,
+ array, arrayLen * dt.mSize, dt);
Trace.traceEnd(RenderScript.TRACE_TAG);
}
- void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, short[] data) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked");
- mRS.validate();
- validate2DRange(xoff, yoff, w, h);
- mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
- w, h, data, data.length * 2, Element.DataType.SIGNED_16);
- Trace.traceEnd(RenderScript.TRACE_TAG);
- }
-
- void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, int[] data) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked");
- mRS.validate();
- validate2DRange(xoff, yoff, w, h);
- mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
- w, h, data, data.length * 4, Element.DataType.SIGNED_32);
- Trace.traceEnd(RenderScript.TRACE_TAG);
- }
-
- void copy2DRangeFromUnchecked(int xoff, int yoff, int w, int h, float[] data) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFromUnchecked");
- mRS.validate();
- validate2DRange(xoff, yoff, w, h);
- mRS.nAllocationData2D(getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace.mID,
- w, h, data, data.length * 4, Element.DataType.FLOAT_32);
+ /**
+ * Copy from an array into a rectangular region in this Allocation. The
+ * array is assumed to be tightly packed.
+ *
+ * @param xoff X offset of the region to update in this Allocation
+ * @param yoff Y offset of the region to update in this Allocation
+ * @param w Width of the region to update
+ * @param h Height of the region to update
+ * @param data to be placed into the Allocation
+ * @hide
+ */
+ public void copy2DRangeFrom(int xoff, int yoff, int w, int h, Object array) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
+ copy2DRangeFromUnchecked(xoff, yoff, w, h, array,
+ validateObjectIsPrimitiveArray(array, true),
+ java.lang.reflect.Array.getLength(array));
Trace.traceEnd(RenderScript.TRACE_TAG);
}
@@ -1002,10 +1065,9 @@
* @param data to be placed into the Allocation
*/
public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
validateIsInt8();
- copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+ Element.DataType.SIGNED_8, data.length);
}
/**
@@ -1019,10 +1081,9 @@
* @param data to be placed into the Allocation
*/
public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
validateIsInt16();
- copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+ Element.DataType.SIGNED_16, data.length);
}
/**
@@ -1036,10 +1097,9 @@
* @param data to be placed into the Allocation
*/
public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
validateIsInt32();
- copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+ Element.DataType.SIGNED_32, data.length);
}
/**
@@ -1053,10 +1113,9 @@
* @param data to be placed into the Allocation
*/
public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copy2DRangeFrom");
validateIsFloat32();
- copy2DRangeFromUnchecked(xoff, yoff, w, h, data);
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copy2DRangeFromUnchecked(xoff, yoff, w, h, data,
+ Element.DataType.FLOAT_32, data.length);
}
/**
@@ -1129,49 +1188,18 @@
* @hide
*
*/
- void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, byte[] data) {
+ private void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d,
+ Object array, Element.DataType dt, int arrayLen) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFromUnchecked");
mRS.validate();
validate3DRange(xoff, yoff, zoff, w, h, d);
- mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
- w, h, d, data, data.length, Element.DataType.SIGNED_8);
+ mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD, w, h, d,
+ array, arrayLen * dt.mSize, dt);
+ Trace.traceEnd(RenderScript.TRACE_TAG);
}
/**
* @hide
- *
- */
- void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, short[] data) {
- mRS.validate();
- validate3DRange(xoff, yoff, zoff, w, h, d);
- mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
- w, h, d, data, data.length * 2, Element.DataType.SIGNED_16);
- }
-
- /**
- * @hide
- *
- */
- void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, int[] data) {
- mRS.validate();
- validate3DRange(xoff, yoff, zoff, w, h, d);
- mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
- w, h, d, data, data.length * 4, Element.DataType.SIGNED_32);
- }
-
- /**
- * @hide
- *
- */
- void copy3DRangeFromUnchecked(int xoff, int yoff, int zoff, int w, int h, int d, float[] data) {
- mRS.validate();
- validate3DRange(xoff, yoff, zoff, w, h, d);
- mRS.nAllocationData3D(getIDSafe(), xoff, yoff, zoff, mSelectedLOD,
- w, h, d, data, data.length * 4, Element.DataType.FLOAT_32);
- }
-
-
- /**
- * @hide
* Copy a rectangular region from the array into the allocation.
* The array is assumed to be tightly packed.
*
@@ -1183,36 +1211,12 @@
* @param d Depth of the region to update
* @param data to be placed into the allocation
*/
- public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, byte[] data) {
- validateIsInt8();
- copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, data);
- }
-
- /**
- * @hide
- *
- */
- public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, short[] data) {
- validateIsInt16();
- copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, data);
- }
-
- /**
- * @hide
- *
- */
- public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, int[] data) {
- validateIsInt32();
- copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, data);
- }
-
- /**
- * @hide
- *
- */
- public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, float[] data) {
- validateIsFloat32();
- copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, data);
+ public void copy3DRangeFrom(int xoff, int yoff, int zoff, int w, int h, int d, Object array) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copy3DRangeFrom");
+ copy3DRangeFromUnchecked(xoff, yoff, zoff, w, h, d, array,
+ validateObjectIsPrimitiveArray(array, true),
+ java.lang.reflect.Array.getLength(array));
+ Trace.traceEnd(RenderScript.TRACE_TAG);
}
/**
@@ -1256,6 +1260,27 @@
Trace.traceEnd(RenderScript.TRACE_TAG);
}
+ private void copyTo(Object array, Element.DataType dt, int arrayLen) {
+ Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
+ mRS.validate();
+ mRS.nAllocationRead(getID(mRS), array, dt);
+ Trace.traceEnd(RenderScript.TRACE_TAG);
+ }
+
+ /**
+ * Copy from the Allocation into an array. The array must be at
+ * least as large as the Allocation. The
+ * {@link android.renderscript.Element} must match the component
+ * type of the array passed in.
+ *
+ * @param array The array to be set from the Allocation.
+ * @hide
+ */
+ public void copyTo(Object array) {
+ copyTo(array, validateObjectIsPrimitiveArray(array, true),
+ java.lang.reflect.Array.getLength(array));
+ }
+
/**
* Copy from the Allocation into a byte array. The array must be at least
* as large as the Allocation. The allocation must be of an 8 bit integer
@@ -1264,11 +1289,8 @@
* @param d The array to be set from the Allocation.
*/
public void copyTo(byte[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
validateIsInt8();
- mRS.validate();
- mRS.nAllocationRead(getID(mRS), d, Element.DataType.SIGNED_8);
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copyTo(d, Element.DataType.SIGNED_8, d.length);
}
/**
@@ -1279,11 +1301,8 @@
* @param d The array to be set from the Allocation.
*/
public void copyTo(short[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
validateIsInt16();
- mRS.validate();
- mRS.nAllocationRead(getID(mRS), d, Element.DataType.SIGNED_16);
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copyTo(d, Element.DataType.SIGNED_16, d.length);
}
/**
@@ -1294,11 +1313,8 @@
* @param d The array to be set from the Allocation.
*/
public void copyTo(int[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
validateIsInt32();
- mRS.validate();
- mRS.nAllocationRead(getID(mRS), d, Element.DataType.SIGNED_32);
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copyTo(d, Element.DataType.SIGNED_32, d.length);
}
/**
@@ -1309,11 +1325,8 @@
* @param d The array to be set from the Allocation.
*/
public void copyTo(float[] d) {
- Trace.traceBegin(RenderScript.TRACE_TAG, "copyTo");
validateIsFloat32();
- mRS.validate();
- mRS.nAllocationRead(getID(mRS), d, Element.DataType.FLOAT_32);
- Trace.traceEnd(RenderScript.TRACE_TAG);
+ copyTo(d, Element.DataType.FLOAT_32, d.length);
}
/**
diff --git a/rs/java/android/renderscript/BaseObj.java b/rs/java/android/renderscript/BaseObj.java
index eee4936..842aa23 100644
--- a/rs/java/android/renderscript/BaseObj.java
+++ b/rs/java/android/renderscript/BaseObj.java
@@ -32,7 +32,7 @@
mDestroyed = false;
}
- void setID(int id) {
+ void setID(long id) {
if (mID != 0) {
throw new RSRuntimeException("Internal Error, reset of object ID.");
}
diff --git a/rs/java/android/renderscript/FileA3D.java b/rs/java/android/renderscript/FileA3D.java
index cdcaff7..04bc7c6 100644
--- a/rs/java/android/renderscript/FileA3D.java
+++ b/rs/java/android/renderscript/FileA3D.java
@@ -141,7 +141,7 @@
return null;
}
- int objectID = rs.nFileA3DGetEntryByIndex(entry.mID, entry.mIndex);
+ long objectID = rs.nFileA3DGetEntryByIndex(entry.mID, entry.mIndex);
if(objectID == 0) {
return null;
}
@@ -297,7 +297,7 @@
long fileId = 0;
if (is instanceof AssetManager.AssetInputStream) {
- int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
+ long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();
fileId = rs.nFileA3DCreateFromAssetStream(asset);
} else {
throw new RSRuntimeException("Unsupported asset stream");
diff --git a/rs/java/android/renderscript/Font.java b/rs/java/android/renderscript/Font.java
index 0375d2b..cfd11c0 100644
--- a/rs/java/android/renderscript/Font.java
+++ b/rs/java/android/renderscript/Font.java
@@ -151,7 +151,7 @@
return "DroidSans.ttf";
}
- Font(int id, RenderScript rs) {
+ Font(long id, RenderScript rs) {
super(id, rs);
}
@@ -162,7 +162,7 @@
static public Font createFromFile(RenderScript rs, Resources res, String path, float pointSize) {
rs.validate();
int dpi = res.getDisplayMetrics().densityDpi;
- int fontId = rs.nFontCreateFromFile(path, pointSize, dpi);
+ long fontId = rs.nFontCreateFromFile(path, pointSize, dpi);
if(fontId == 0) {
throw new RSRuntimeException("Unable to create font from file " + path);
@@ -187,7 +187,7 @@
AssetManager mgr = res.getAssets();
int dpi = res.getDisplayMetrics().densityDpi;
- int fontId = rs.nFontCreateFromAsset(mgr, path, pointSize, dpi);
+ long fontId = rs.nFontCreateFromAsset(mgr, path, pointSize, dpi);
if(fontId == 0) {
throw new RSRuntimeException("Unable to create font from asset " + path);
}
@@ -211,9 +211,9 @@
int dpi = res.getDisplayMetrics().densityDpi;
- int fontId = 0;
+ long fontId = 0;
if (is instanceof AssetManager.AssetInputStream) {
- int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
+ long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();
fontId = rs.nFontCreateFromAssetStream(name, pointSize, dpi, asset);
} else {
throw new RSRuntimeException("Unsupported asset stream created");
diff --git a/rs/java/android/renderscript/Long4.java b/rs/java/android/renderscript/Long4.java
index 757b910..1a1ad74 100644
--- a/rs/java/android/renderscript/Long4.java
+++ b/rs/java/android/renderscript/Long4.java
@@ -505,7 +505,7 @@
* @param data
* @param offset
*/
- public void copyTo(Long[] data, int offset) {
+ public void copyTo(long[] data, int offset) {
data[offset] = (long)(x);
data[offset + 1] = (long)(y);
data[offset + 2] = (long)(z);
diff --git a/rs/java/android/renderscript/ProgramStore.java b/rs/java/android/renderscript/ProgramStore.java
index dac9e76..969cc25 100644
--- a/rs/java/android/renderscript/ProgramStore.java
+++ b/rs/java/android/renderscript/ProgramStore.java
@@ -146,7 +146,7 @@
BlendDstFunc mBlendDst;
boolean mDither;
- ProgramStore(int id, RenderScript rs) {
+ ProgramStore(long id, RenderScript rs) {
super(id, rs);
}
@@ -421,7 +421,7 @@
*/
public ProgramStore create() {
mRS.validate();
- int id = mRS.nProgramStoreCreate(mColorMaskR, mColorMaskG, mColorMaskB, mColorMaskA,
+ long id = mRS.nProgramStoreCreate(mColorMaskR, mColorMaskG, mColorMaskB, mColorMaskA,
mDepthMask, mDither,
mBlendSrc.mID, mBlendDst.mID, mDepthFunc.mID);
ProgramStore programStore = new ProgramStore(id, mRS);
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 9c8775a..8618764 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -506,8 +506,8 @@
rsnAllocationResize1D(mContext, id, dimX);
}
- native long rsnFileA3DCreateFromAssetStream(long con, int assetStream);
- synchronized long nFileA3DCreateFromAssetStream(int assetStream) {
+ native long rsnFileA3DCreateFromAssetStream(long con, long assetStream);
+ synchronized long nFileA3DCreateFromAssetStream(long assetStream) {
validate();
return rsnFileA3DCreateFromAssetStream(mContext, assetStream);
}
@@ -531,24 +531,24 @@
validate();
rsnFileA3DGetIndexEntries(mContext, fileA3D, numEntries, IDs, names);
}
- native int rsnFileA3DGetEntryByIndex(long con, long fileA3D, int index);
- synchronized int nFileA3DGetEntryByIndex(long fileA3D, int index) {
+ native long rsnFileA3DGetEntryByIndex(long con, long fileA3D, int index);
+ synchronized long nFileA3DGetEntryByIndex(long fileA3D, int index) {
validate();
return rsnFileA3DGetEntryByIndex(mContext, fileA3D, index);
}
- native int rsnFontCreateFromFile(long con, String fileName, float size, int dpi);
- synchronized int nFontCreateFromFile(String fileName, float size, int dpi) {
+ native long rsnFontCreateFromFile(long con, String fileName, float size, int dpi);
+ synchronized long nFontCreateFromFile(String fileName, float size, int dpi) {
validate();
return rsnFontCreateFromFile(mContext, fileName, size, dpi);
}
- native int rsnFontCreateFromAssetStream(long con, String name, float size, int dpi, int assetStream);
- synchronized int nFontCreateFromAssetStream(String name, float size, int dpi, int assetStream) {
+ native long rsnFontCreateFromAssetStream(long con, String name, float size, int dpi, long assetStream);
+ synchronized long nFontCreateFromAssetStream(String name, float size, int dpi, long assetStream) {
validate();
return rsnFontCreateFromAssetStream(mContext, name, size, dpi, assetStream);
}
- native int rsnFontCreateFromAsset(long con, AssetManager mgr, String path, float size, int dpi);
- synchronized int nFontCreateFromAsset(AssetManager mgr, String path, float size, int dpi) {
+ native long rsnFontCreateFromAsset(long con, AssetManager mgr, String path, float size, int dpi);
+ synchronized long nFontCreateFromAsset(AssetManager mgr, String path, float size, int dpi) {
validate();
return rsnFontCreateFromAsset(mContext, mgr, path, size, dpi);
}
@@ -665,9 +665,9 @@
rsnScriptSetVarObj(mContext, id, slot, val);
}
- native int rsnScriptCCreate(long con, String resName, String cacheDir,
+ native long rsnScriptCCreate(long con, String resName, String cacheDir,
byte[] script, int length);
- synchronized int nScriptCCreate(String resName, String cacheDir, byte[] script, int length) {
+ synchronized long nScriptCCreate(String resName, String cacheDir, byte[] script, int length) {
validate();
return rsnScriptCCreate(mContext, resName, cacheDir, script, length);
}
@@ -714,18 +714,18 @@
rsnScriptGroupExecute(mContext, group);
}
- native int rsnSamplerCreate(long con, int magFilter, int minFilter,
+ native long rsnSamplerCreate(long con, int magFilter, int minFilter,
int wrapS, int wrapT, int wrapR, float aniso);
- synchronized int nSamplerCreate(int magFilter, int minFilter,
+ synchronized long nSamplerCreate(int magFilter, int minFilter,
int wrapS, int wrapT, int wrapR, float aniso) {
validate();
return rsnSamplerCreate(mContext, magFilter, minFilter, wrapS, wrapT, wrapR, aniso);
}
- native int rsnProgramStoreCreate(long con, boolean r, boolean g, boolean b, boolean a,
+ native long rsnProgramStoreCreate(long con, boolean r, boolean g, boolean b, boolean a,
boolean depthMask, boolean dither,
int srcMode, int dstMode, int depthFunc);
- synchronized int nProgramStoreCreate(boolean r, boolean g, boolean b, boolean a,
+ synchronized long nProgramStoreCreate(boolean r, boolean g, boolean b, boolean a,
boolean depthMask, boolean dither,
int srcMode, int dstMode, int depthFunc) {
validate();
@@ -791,8 +791,8 @@
rsnMeshGetIndices(mContext, id, idxIds, primitives, vtxIdCount);
}
- native long rsnPathCreate(long con, int prim, boolean isStatic, long vtx, int loop, float q);
- synchronized long nPathCreate(int prim, boolean isStatic, long vtx, int loop, float q) {
+ native long rsnPathCreate(long con, int prim, boolean isStatic, long vtx, long loop, float q);
+ synchronized long nPathCreate(int prim, boolean isStatic, long vtx, long loop, float q) {
validate();
return rsnPathCreate(mContext, prim, isStatic, vtx, loop, q);
}
diff --git a/rs/java/android/renderscript/Sampler.java b/rs/java/android/renderscript/Sampler.java
index 623055fe..8d0e29e 100644
--- a/rs/java/android/renderscript/Sampler.java
+++ b/rs/java/android/renderscript/Sampler.java
@@ -60,7 +60,7 @@
Value mWrapR;
float mAniso;
- Sampler(int id, RenderScript rs) {
+ Sampler(long id, RenderScript rs) {
super(id, rs);
}
@@ -347,7 +347,7 @@
public Sampler create() {
mRS.validate();
- int id = mRS.nSamplerCreate(mMag.mID, mMin.mID,
+ long id = mRS.nSamplerCreate(mMag.mID, mMin.mID,
mWrapS.mID, mWrapT.mID, mWrapR.mID, mAniso);
Sampler sampler = new Sampler(id, mRS);
sampler.mMin = mMin;
diff --git a/rs/java/android/renderscript/ScriptC.java b/rs/java/android/renderscript/ScriptC.java
index b0a5759..cdb2b08 100644
--- a/rs/java/android/renderscript/ScriptC.java
+++ b/rs/java/android/renderscript/ScriptC.java
@@ -45,7 +45,17 @@
protected ScriptC(int id, RenderScript rs) {
super(id, rs);
}
-
+ /**
+ * Only intended for use by the generated derived classes.
+ *
+ * @param id
+ * @param rs
+ *
+ * @hide
+ */
+ protected ScriptC(long id, RenderScript rs) {
+ super(id, rs);
+ }
/**
* Only intended for use by the generated derived classes.
*
@@ -56,7 +66,7 @@
*/
protected ScriptC(RenderScript rs, Resources resources, int resourceID) {
super(0, rs);
- int id = internalCreate(rs, resources, resourceID);
+ long id = internalCreate(rs, resources, resourceID);
if (id == 0) {
throw new RSRuntimeException("Loading of ScriptC script failed.");
}
@@ -70,7 +80,7 @@
static String mCachePath;
- private static synchronized int internalCreate(RenderScript rs, Resources resources, int resourceID) {
+ private static synchronized long internalCreate(RenderScript rs, Resources resources, int resourceID) {
byte[] pgm;
int pgmLength;
InputStream is = resources.openRawResource(resourceID);
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 024d0c3..80a5da2 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -220,7 +220,7 @@
nDeviceCreate(JNIEnv *_env, jobject _this)
{
LOG_API("nDeviceCreate");
- return (jint)rsDeviceCreate();
+ return (jlong)rsDeviceCreate();
}
static void
@@ -241,17 +241,17 @@
nContextCreate(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer, jint ct)
{
LOG_API("nContextCreate");
- return (jint)rsContextCreate((RsDevice)dev, ver, sdkVer, (RsContextType)ct, 0);
+ return (jlong)rsContextCreate((RsDevice)dev, ver, sdkVer, (RsContextType)ct, 0);
}
static jlong
nContextCreateGL(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer,
- int colorMin, int colorPref,
- int alphaMin, int alphaPref,
- int depthMin, int depthPref,
- int stencilMin, int stencilPref,
- int samplesMin, int samplesPref, float samplesQ,
- int dpi)
+ jint colorMin, jint colorPref,
+ jint alphaMin, jint alphaPref,
+ jint depthMin, jint depthPref,
+ jint stencilMin, jint stencilPref,
+ jint samplesMin, jint samplesPref, jfloat samplesQ,
+ jint dpi)
{
RsSurfaceConfig sc;
sc.alphaMin = alphaMin;
@@ -265,7 +265,7 @@
sc.samplesQ = samplesQ;
LOG_API("nContextCreateGL");
- return (jint)rsContextCreateGL((RsDevice)dev, ver, sdkVer, sc, dpi);
+ return (jlong)rsContextCreateGL((RsDevice)dev, ver, sdkVer, sc, dpi);
}
static void
@@ -355,7 +355,7 @@
ALOGV("message receive buffer too small. %i", receiveLen);
}
_env->ReleaseIntArrayElements(data, ptr, 0);
- return id;
+ return (jint)id;
}
static jint
@@ -370,7 +370,7 @@
auxDataPtr[0] = (jint)subID;
auxDataPtr[1] = (jint)receiveLen;
_env->ReleaseIntArrayElements(auxData, auxDataPtr, 0);
- return id;
+ return (jint)id;
}
static void nContextInitToClient(JNIEnv *_env, jobject _this, jlong con)
@@ -432,7 +432,7 @@
_env->ReleaseIntArrayElements(_ids, ids, JNI_ABORT);
_env->ReleaseIntArrayElements(_arraySizes, arraySizes, JNI_ABORT);
- return (jint)id;
+ return (jlong)id;
}
static void
@@ -499,7 +499,7 @@
int elementCount = _env->GetArrayLength(_typeData);
assert(elementCount == 6);
- LOG_API("nTypeCreate, con(%p)", (RsContext)con);
+ LOG_API("nTypeGetNativeData, con(%p)", (RsContext)con);
uint32_t typeData[6];
rsaTypeGetNativeData((RsContext)con, (RsType)id, typeData, 6);
@@ -515,7 +515,7 @@
nAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mips, jint usage, jint pointer)
{
LOG_API("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)", (RsContext)con, (RsElement)type, mips, usage, (void *)pointer);
- return (jint) rsAllocationCreateTyped((RsContext)con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage, (uint32_t)pointer);
+ return (jlong) rsAllocationCreateTyped((RsContext)con, (RsType)type, (RsAllocationMipmapControl)mips, (uint32_t)usage, (uint32_t)pointer);
}
static void
@@ -662,7 +662,7 @@
static void
nAllocationData1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
- jint count, jobject data, int sizeBytes, int dataType)
+ jint count, jobject data, jint sizeBytes, jint dataType)
{
RsAllocation *alloc = (RsAllocation *)_alloc;
LOG_API("nAllocation1DData, con(%p), adapter(%p), offset(%i), count(%i), sizeBytes(%i), dataType(%i)",
@@ -671,8 +671,8 @@
}
static void
-// native void rsnAllocationElementData1D(int con, int id, int xoff, int compIdx, byte[] d, int sizeBytes);
-nAllocationElementData1D(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint offset, jint lod, jint compIdx, jbyteArray data, int sizeBytes)
+// native void rsnAllocationElementData1D(long con, long id, int xoff, int compIdx, byte[] d, int sizeBytes);
+nAllocationElementData1D(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint offset, jint lod, jint compIdx, jbyteArray data, jint sizeBytes)
{
jint len = _env->GetArrayLength(data);
LOG_API("nAllocationElementData1D, con(%p), alloc(%p), offset(%i), comp(%i), len(%i), sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, offset, compIdx, len, sizeBytes);
@@ -683,7 +683,7 @@
static void
nAllocationData2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face,
- jint w, jint h, jobject data, int sizeBytes, int dataType)
+ jint w, jint h, jobject data, jint sizeBytes, jint dataType)
{
RsAllocation *alloc = (RsAllocation *)_alloc;
RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face;
@@ -797,9 +797,8 @@
static jlong
nFileA3DCreateFromAssetStream(JNIEnv *_env, jobject _this, jlong con, jlong native_asset)
{
- ALOGV("______nFileA3D %u", (uint32_t) native_asset);
-
Asset* asset = reinterpret_cast<Asset*>(native_asset);
+ ALOGV("______nFileA3D %p", asset);
jlong id = (jlong)rsaFileA3DCreateFromMemory((RsContext)con, asset->getBuffer(false), asset->getLength());
return id;
@@ -837,13 +836,13 @@
{
int32_t numEntries = 0;
rsaFileA3DGetNumIndexEntries((RsContext)con, &numEntries, (RsFile)fileA3D);
- return numEntries;
+ return (jint)numEntries;
}
static void
nFileA3DGetIndexEntries(JNIEnv *_env, jobject _this, jlong con, jlong fileA3D, jint numEntries, jintArray _ids, jobjectArray _entries)
{
- ALOGV("______nFileA3D %u", (uint32_t) fileA3D);
+ ALOGV("______nFileA3D %p", (RsFile) fileA3D);
RsFileIndexEntry *fileEntries = (RsFileIndexEntry*)malloc((uint32_t)numEntries * sizeof(RsFileIndexEntry));
rsaFileA3DGetIndexEntries((RsContext)con, fileEntries, (uint32_t)numEntries, (RsFile)fileA3D);
@@ -856,43 +855,43 @@
free(fileEntries);
}
-static int
+static jlong
nFileA3DGetEntryByIndex(JNIEnv *_env, jobject _this, jlong con, jlong fileA3D, jint index)
{
- ALOGV("______nFileA3D %u", (uint32_t) fileA3D);
- jint id = (jint)rsaFileA3DGetEntryByIndex((RsContext)con, (uint32_t)index, (RsFile)fileA3D);
+ ALOGV("______nFileA3D %p", (RsFile) fileA3D);
+ jlong id = (jlong)rsaFileA3DGetEntryByIndex((RsContext)con, (uint32_t)index, (RsFile)fileA3D);
return id;
}
// -----------------------------------
-static int
+static jlong
nFontCreateFromFile(JNIEnv *_env, jobject _this, jlong con,
jstring fileName, jfloat fontSize, jint dpi)
{
AutoJavaStringToUTF8 fileNameUTF(_env, fileName);
- jint id = (jint)rsFontCreateFromFile((RsContext)con,
+ jlong id = (jlong)rsFontCreateFromFile((RsContext)con,
fileNameUTF.c_str(), fileNameUTF.length(),
fontSize, dpi);
return id;
}
-static int
+static jlong
nFontCreateFromAssetStream(JNIEnv *_env, jobject _this, jlong con,
- jstring name, jfloat fontSize, jint dpi, jint native_asset)
+ jstring name, jfloat fontSize, jint dpi, jlong native_asset)
{
Asset* asset = reinterpret_cast<Asset*>(native_asset);
AutoJavaStringToUTF8 nameUTF(_env, name);
- jint id = (jint)rsFontCreateFromMemory((RsContext)con,
+ jlong id = (jlong)rsFontCreateFromMemory((RsContext)con,
nameUTF.c_str(), nameUTF.length(),
fontSize, dpi,
asset->getBuffer(false), asset->getLength());
return id;
}
-static int
+static jlong
nFontCreateFromAsset(JNIEnv *_env, jobject _this, jlong con, jobject _assetMgr, jstring _path,
jfloat fontSize, jint dpi)
{
@@ -907,7 +906,7 @@
return 0;
}
- jint id = (jint)rsFontCreateFromMemory((RsContext)con,
+ jlong id = (jlong)rsFontCreateFromMemory((RsContext)con,
str.c_str(), str.length(),
fontSize, dpi,
asset->getBuffer(false), asset->getLength());
@@ -1126,7 +1125,7 @@
// -----------------------------------
-static jint
+static jlong
nScriptCCreate(JNIEnv *_env, jobject _this, jlong con,
jstring resName, jstring cacheDir,
jbyteArray scriptRef, jint length)
@@ -1135,7 +1134,7 @@
AutoJavaStringToUTF8 resNameUTF(_env, resName);
AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir);
- jint ret = 0;
+ jlong ret = 0;
jbyte* script_ptr = NULL;
jint _exception = 0;
jint remaining;
@@ -1161,7 +1160,7 @@
//rsScriptCSetText((RsContext)con, (const char *)script_ptr, length);
- ret = (jint)rsScriptCCreate((RsContext)con,
+ ret = (jlong)rsScriptCCreate((RsContext)con,
resNameUTF.c_str(), resNameUTF.length(),
cacheDirUTF.c_str(), cacheDirUTF.length(),
(const char *)script_ptr, length);
@@ -1172,7 +1171,7 @@
_exception ? JNI_ABORT: 0);
}
- return ret;
+ return (jlong)ret;
}
static jlong
@@ -1186,14 +1185,14 @@
nScriptKernelIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot, jint sig)
{
LOG_API("nScriptKernelIDCreate, con(%p) script(%p), slot(%i), sig(%i)", (RsContext)con, (void *)sid, slot, sig);
- return (jint)rsScriptKernelIDCreate((RsContext)con, (RsScript)sid, slot, sig);
+ return (jlong)rsScriptKernelIDCreate((RsContext)con, (RsScript)sid, slot, sig);
}
static jlong
nScriptFieldIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot)
{
LOG_API("nScriptFieldIDCreate, con(%p) script(%p), slot(%i)", (RsContext)con, (void *)sid, slot);
- return (jint)rsScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
+ return (jlong)rsScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot);
}
static jlong
@@ -1253,7 +1252,7 @@
// ---------------------------------------------------------------------------
-static jint
+static jlong
nProgramStoreCreate(JNIEnv *_env, jobject _this, jlong con,
jboolean colorMaskR, jboolean colorMaskG, jboolean colorMaskB, jboolean colorMaskA,
jboolean depthMask, jboolean ditherEnable,
@@ -1261,7 +1260,7 @@
jint depthFunc)
{
LOG_API("nProgramStoreCreate, con(%p)", (RsContext)con);
- return (jint)rsProgramStoreCreate((RsContext)con, colorMaskR, colorMaskG, colorMaskB, colorMaskA,
+ return (jlong)rsProgramStoreCreate((RsContext)con, colorMaskR, colorMaskG, colorMaskB, colorMaskA,
depthMask, ditherEnable, (RsBlendSrcFunc)srcFunc,
(RsBlendDstFunc)destFunc, (RsDepthFunc)depthFunc);
}
@@ -1346,7 +1345,7 @@
nProgramRasterCreate(JNIEnv *_env, jobject _this, jlong con, jboolean pointSprite, jint cull)
{
LOG_API("nProgramRasterCreate, con(%p), pointSprite(%i), cull(%i)", (RsContext)con, pointSprite, cull);
- return (jint)rsProgramRasterCreate((RsContext)con, pointSprite, (RsCullMode)cull);
+ return (jlong)rsProgramRasterCreate((RsContext)con, pointSprite, (RsCullMode)cull);
}
@@ -1390,12 +1389,12 @@
// ---------------------------------------------------------------------------
-static jint
+static jlong
nSamplerCreate(JNIEnv *_env, jobject _this, jlong con, jint magFilter, jint minFilter,
jint wrapS, jint wrapT, jint wrapR, jfloat aniso)
{
LOG_API("nSamplerCreate, con(%p)", (RsContext)con);
- return (jint)rsSamplerCreate((RsContext)con,
+ return (jlong)rsSamplerCreate((RsContext)con,
(RsSamplerValue)magFilter,
(RsSamplerValue)minFilter,
(RsSamplerValue)wrapS,
@@ -1407,7 +1406,7 @@
// ---------------------------------------------------------------------------
static jlong
-nPathCreate(JNIEnv *_env, jobject _this, jlong con, jint prim, jboolean isStatic, jlong _vtx, jint _loop, jfloat q) {
+nPathCreate(JNIEnv *_env, jobject _this, jlong con, jint prim, jboolean isStatic, jlong _vtx, jlong _loop, jfloat q) {
LOG_API("nPathCreate, con(%p)", (RsContext)con);
jlong id = (jlong)rsPathCreate((RsContext)con, (RsPathPrimitive)prim, isStatic,
@@ -1526,15 +1525,15 @@
{"rsnObjDestroy", "(JJ)V", (void*)nObjDestroy },
{"rsnFileA3DCreateFromFile", "(JLjava/lang/String;)J", (void*)nFileA3DCreateFromFile },
-{"rsnFileA3DCreateFromAssetStream", "(JI)J", (void*)nFileA3DCreateFromAssetStream },
+{"rsnFileA3DCreateFromAssetStream", "(JJ)J", (void*)nFileA3DCreateFromAssetStream },
{"rsnFileA3DCreateFromAsset", "(JLandroid/content/res/AssetManager;Ljava/lang/String;)J", (void*)nFileA3DCreateFromAsset },
{"rsnFileA3DGetNumIndexEntries", "(JJ)I", (void*)nFileA3DGetNumIndexEntries },
{"rsnFileA3DGetIndexEntries", "(JJI[I[Ljava/lang/String;)V", (void*)nFileA3DGetIndexEntries },
-{"rsnFileA3DGetEntryByIndex", "(JJI)I", (void*)nFileA3DGetEntryByIndex },
+{"rsnFileA3DGetEntryByIndex", "(JJI)J", (void*)nFileA3DGetEntryByIndex },
-{"rsnFontCreateFromFile", "(JLjava/lang/String;FI)I", (void*)nFontCreateFromFile },
-{"rsnFontCreateFromAssetStream", "(JLjava/lang/String;FII)I", (void*)nFontCreateFromAssetStream },
-{"rsnFontCreateFromAsset", "(JLandroid/content/res/AssetManager;Ljava/lang/String;FI)I", (void*)nFontCreateFromAsset },
+{"rsnFontCreateFromFile", "(JLjava/lang/String;FI)J", (void*)nFontCreateFromFile },
+{"rsnFontCreateFromAssetStream", "(JLjava/lang/String;FIJ)J", (void*)nFontCreateFromAssetStream },
+{"rsnFontCreateFromAsset", "(JLandroid/content/res/AssetManager;Ljava/lang/String;FI)J", (void*)nFontCreateFromAsset },
{"rsnElementCreate", "(JJIZI)J", (void*)nElementCreate },
{"rsnElementCreate2", "(J[I[Ljava/lang/String;[I)J", (void*)nElementCreate2 },
@@ -1591,7 +1590,7 @@
{"rsnScriptSetVarVE", "(JJI[BJ[I)V", (void*)nScriptSetVarVE },
{"rsnScriptSetVarObj", "(JJIJ)V", (void*)nScriptSetVarObj },
-{"rsnScriptCCreate", "(JLjava/lang/String;Ljava/lang/String;[BI)I", (void*)nScriptCCreate },
+{"rsnScriptCCreate", "(JLjava/lang/String;Ljava/lang/String;[BI)J", (void*)nScriptCCreate },
{"rsnScriptIntrinsicCreate", "(JIJ)J", (void*)nScriptIntrinsicCreate },
{"rsnScriptKernelIDCreate", "(JJII)J", (void*)nScriptKernelIDCreate },
{"rsnScriptFieldIDCreate", "(JJI)J", (void*)nScriptFieldIDCreate },
@@ -1600,7 +1599,7 @@
{"rsnScriptGroupSetOutput", "(JJJJ)V", (void*)nScriptGroupSetOutput },
{"rsnScriptGroupExecute", "(JJ)V", (void*)nScriptGroupExecute },
-{"rsnProgramStoreCreate", "(JZZZZZZIII)I", (void*)nProgramStoreCreate },
+{"rsnProgramStoreCreate", "(JZZZZZZIII)J", (void*)nProgramStoreCreate },
{"rsnProgramBindConstants", "(JJIJ)V", (void*)nProgramBindConstants },
{"rsnProgramBindTexture", "(JJIJ)V", (void*)nProgramBindTexture },
@@ -1616,9 +1615,9 @@
{"rsnContextBindProgramVertex", "(JI)V", (void*)nContextBindProgramVertex },
{"rsnContextBindProgramRaster", "(JI)V", (void*)nContextBindProgramRaster },
-{"rsnSamplerCreate", "(JIIIIIF)I", (void*)nSamplerCreate },
+{"rsnSamplerCreate", "(JIIIIIF)J", (void*)nSamplerCreate },
-{"rsnPathCreate", "(JIZJIF)J", (void*)nPathCreate },
+{"rsnPathCreate", "(JIZJJF)J", (void*)nPathCreate },
{"rsnMeshCreate", "(J[I[I[I)J", (void*)nMeshCreate },
{"rsnMeshGetVertexBufferCount", "(JJ)I", (void*)nMeshGetVertexBufferCount },
@@ -1648,7 +1647,7 @@
assert(env != NULL);
if (registerFuncs(env) < 0) {
- ALOGE("ERROR: MediaPlayer native registration failed\n");
+ ALOGE("ERROR: Renderscript native registration failed\n");
goto bail;
}
diff --git a/services/java/com/android/server/ConsumerIrService.java b/services/java/com/android/server/ConsumerIrService.java
index 783dff1..583f1bc 100644
--- a/services/java/com/android/server/ConsumerIrService.java
+++ b/services/java/com/android/server/ConsumerIrService.java
@@ -49,13 +49,13 @@
private static final int MAX_XMIT_TIME = 2000000; /* in microseconds */
- private static native int halOpen();
- private static native int halTransmit(int halObject, int carrierFrequency, int[] pattern);
- private static native int[] halGetCarrierFrequencies(int halObject);
+ private static native long halOpen();
+ private static native int halTransmit(long halObject, int carrierFrequency, int[] pattern);
+ private static native int[] halGetCarrierFrequencies(long halObject);
private final Context mContext;
private final PowerManager.WakeLock mWakeLock;
- private final int mHal;
+ private final long mNativeHal;
private final Object mHalLock = new Object();
ConsumerIrService(Context context) {
@@ -65,23 +65,23 @@
mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mWakeLock.setReferenceCounted(true);
- mHal = halOpen();
+ mNativeHal = halOpen();
if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CONSUMER_IR)) {
- if (mHal == 0) {
+ if (mNativeHal == 0) {
throw new RuntimeException("FEATURE_CONSUMER_IR present, but no IR HAL loaded!");
}
- } else if (mHal != 0) {
+ } else if (mNativeHal != 0) {
throw new RuntimeException("IR HAL present, but FEATURE_CONSUMER_IR is not set!");
}
}
@Override
public boolean hasIrEmitter() {
- return mHal != 0;
+ return mNativeHal != 0;
}
private void throwIfNoIrEmitter() {
- if (mHal == 0) {
+ if (mNativeHal == 0) {
throw new UnsupportedOperationException("IR emitter not available");
}
}
@@ -111,7 +111,7 @@
// Right now there is no mechanism to ensure fair queing of IR requests
synchronized (mHalLock) {
- int err = halTransmit(mHal, carrierFrequency, pattern);
+ int err = halTransmit(mNativeHal, carrierFrequency, pattern);
if (err < 0) {
Slog.e(TAG, "Error transmitting: " + err);
@@ -129,7 +129,7 @@
throwIfNoIrEmitter();
synchronized(mHalLock) {
- return halGetCarrierFrequencies(mHal);
+ return halGetCarrierFrequencies(mNativeHal);
}
}
}
diff --git a/services/java/com/android/server/LightsService.java b/services/java/com/android/server/LightsService.java
index a1d655b..e99a3a4 100644
--- a/services/java/com/android/server/LightsService.java
+++ b/services/java/com/android/server/LightsService.java
@@ -96,6 +96,7 @@
synchronized (this) {
if (mColor == 0 && !mFlashing) {
setLightLocked(color, LIGHT_FLASH_HARDWARE, onMS, 1000, BRIGHTNESS_MODE_USER);
+ mColor = 0;
mH.sendMessageDelayed(Message.obtain(mH, 1, this), onMS);
}
}
diff --git a/services/java/com/android/server/pm/Installer.java b/services/java/com/android/server/pm/Installer.java
index 0d2b503..11a6498 100644
--- a/services/java/com/android/server/pm/Installer.java
+++ b/services/java/com/android/server/pm/Installer.java
@@ -211,6 +211,17 @@
return execute(builder.toString());
}
+ public int idmap(String targetApkPath, String overlayApkPath, int uid) {
+ StringBuilder builder = new StringBuilder("idmap");
+ builder.append(' ');
+ builder.append(targetApkPath);
+ builder.append(' ');
+ builder.append(overlayApkPath);
+ builder.append(' ');
+ builder.append(uid);
+ return execute(builder.toString());
+ }
+
public int movedex(String srcPath, String dstPath) {
StringBuilder builder = new StringBuilder("movedex");
builder.append(' ');
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 7e244b9..74a66d6 100755
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -217,6 +217,7 @@
static final int SCAN_UPDATE_TIME = 1<<6;
static final int SCAN_DEFER_DEX = 1<<7;
static final int SCAN_BOOTING = 1<<8;
+ static final int SCAN_TRUSTED_OVERLAY = 1<<9;
static final int REMOVE_CHATTY = 1<<16;
@@ -257,8 +258,13 @@
private static final String LIB_DIR_NAME = "lib";
+ private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay";
+
static final String mTempContainerPrefix = "smdl2tmp";
+ private static final String IDMAP_PREFIX = "/data/resource-cache/";
+ private static final String IDMAP_SUFFIX = "@idmap";
+
final HandlerThread mHandlerThread = new HandlerThread("PackageManager",
Process.THREAD_PRIORITY_BACKGROUND);
final PackageHandler mHandler;
@@ -296,6 +302,9 @@
// This is the object monitoring the system app dir.
final FileObserver mVendorInstallObserver;
+ // This is the object monitoring the vendor overlay package dir.
+ final FileObserver mVendorOverlayInstallObserver;
+
// This is the object monitoring mAppInstallDir.
final FileObserver mAppInstallObserver;
@@ -343,6 +352,10 @@
final HashMap<String, PackageParser.Package> mPackages =
new HashMap<String, PackageParser.Package>();
+ // Tracks available target package names -> overlay package paths.
+ final HashMap<String, HashMap<String, PackageParser.Package>> mOverlays =
+ new HashMap<String, HashMap<String, PackageParser.Package>>();
+
final Settings mSettings;
boolean mRestoredSettings;
@@ -1273,6 +1286,17 @@
}
}
+ // Collect vendor overlay packages.
+ // (Do this before scanning any apps.)
+ // For security and version matching reason, only consider
+ // overlay packages if they reside in VENDOR_OVERLAY_DIR.
+ File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
+ mVendorOverlayInstallObserver = new AppDirObserver(
+ vendorOverlayDir.getPath(), OBSERVER_EVENTS, true, false);
+ mVendorOverlayInstallObserver.startWatching();
+ scanDirLI(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM
+ | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode | SCAN_TRUSTED_OVERLAY, 0);
+
// Find base frameworks (resource packages without code).
mFrameworkInstallObserver = new AppDirObserver(
frameworkDir.getPath(), OBSERVER_EVENTS, true, false);
@@ -1301,6 +1325,11 @@
// Collect all vendor packages.
File vendorAppDir = new File("/vendor/app");
+ try {
+ vendorAppDir = vendorAppDir.getCanonicalFile();
+ } catch (IOException e) {
+ // failed to look up canonical path, continue with original one
+ }
mVendorInstallObserver = new AppDirObserver(
vendorAppDir.getPath(), OBSERVER_EVENTS, true, false);
mVendorInstallObserver.startWatching();
@@ -3470,6 +3499,56 @@
return finalList;
}
+ private void createIdmapsForPackageLI(PackageParser.Package pkg) {
+ HashMap<String, PackageParser.Package> overlays = mOverlays.get(pkg.packageName);
+ if (overlays == null) {
+ Slog.w(TAG, "Unable to create idmap for " + pkg.packageName + ": no overlay packages");
+ return;
+ }
+ for (PackageParser.Package opkg : overlays.values()) {
+ // Not much to do if idmap fails: we already logged the error
+ // and we certainly don't want to abort installation of pkg simply
+ // because an overlay didn't fit properly. For these reasons,
+ // ignore the return value of createIdmapForPackagePairLI.
+ createIdmapForPackagePairLI(pkg, opkg);
+ }
+ }
+
+ private boolean createIdmapForPackagePairLI(PackageParser.Package pkg,
+ PackageParser.Package opkg) {
+ if (!opkg.mTrustedOverlay) {
+ Slog.w(TAG, "Skipping target and overlay pair " + pkg.mScanPath + " and " +
+ opkg.mScanPath + ": overlay not trusted");
+ return false;
+ }
+ HashMap<String, PackageParser.Package> overlaySet = mOverlays.get(pkg.packageName);
+ if (overlaySet == null) {
+ Slog.e(TAG, "was about to create idmap for " + pkg.mScanPath + " and " +
+ opkg.mScanPath + " but target package has no known overlays");
+ return false;
+ }
+ final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
+ if (mInstaller.idmap(pkg.mScanPath, opkg.mScanPath, sharedGid) != 0) {
+ Slog.e(TAG, "Failed to generate idmap for " + pkg.mScanPath + " and " + opkg.mScanPath);
+ return false;
+ }
+ PackageParser.Package[] overlayArray =
+ overlaySet.values().toArray(new PackageParser.Package[0]);
+ Comparator<PackageParser.Package> cmp = new Comparator<PackageParser.Package>() {
+ public int compare(PackageParser.Package p1, PackageParser.Package p2) {
+ return p1.mOverlayPriority - p2.mOverlayPriority;
+ }
+ };
+ Arrays.sort(overlayArray, cmp);
+
+ pkg.applicationInfo.resourceDirs = new String[overlayArray.length];
+ int i = 0;
+ for (PackageParser.Package p : overlayArray) {
+ pkg.applicationInfo.resourceDirs[i++] = p.applicationInfo.sourceDir;
+ }
+ return true;
+ }
+
private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
String[] files = dir.list();
if (files == null) {
@@ -3567,7 +3646,7 @@
pp.setSeparateProcesses(mSeparateProcesses);
pp.setOnlyCoreApps(mOnlyCore);
final PackageParser.Package pkg = pp.parsePackage(scanFile,
- scanPath, mMetrics, parseFlags);
+ scanPath, mMetrics, parseFlags, (scanMode & SCAN_TRUSTED_OVERLAY) != 0);
if (pkg == null) {
mLastScanError = pp.getParseError();
@@ -5076,6 +5155,29 @@
}
pkgSetting.setTimeStamp(scanFileTime);
+
+ // Create idmap files for pairs of (packages, overlay packages).
+ // Note: "android", ie framework-res.apk, is handled by native layers.
+ if (pkg.mOverlayTarget != null) {
+ // This is an overlay package.
+ if (pkg.mOverlayTarget != null && !pkg.mOverlayTarget.equals("android")) {
+ if (!mOverlays.containsKey(pkg.mOverlayTarget)) {
+ mOverlays.put(pkg.mOverlayTarget,
+ new HashMap<String, PackageParser.Package>());
+ }
+ HashMap<String, PackageParser.Package> map = mOverlays.get(pkg.mOverlayTarget);
+ map.put(pkg.packageName, pkg);
+ PackageParser.Package orig = mPackages.get(pkg.mOverlayTarget);
+ if (orig != null && !createIdmapForPackagePairLI(orig, pkg)) {
+ mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
+ return null;
+ }
+ }
+ } else if (mOverlays.containsKey(pkg.packageName) &&
+ !pkg.packageName.equals("android")) {
+ // This is a regular package, with one or more known overlay packages.
+ createIdmapsForPackageLI(pkg);
+ }
}
return pkg;
diff --git a/services/jni/com_android_server_ConsumerIrService.cpp b/services/jni/com_android_server_ConsumerIrService.cpp
index 004c0aa..3a50ff7 100644
--- a/services/jni/com_android_server_ConsumerIrService.cpp
+++ b/services/jni/com_android_server_ConsumerIrService.cpp
@@ -29,7 +29,7 @@
namespace android {
-static jint halOpen(JNIEnv *env, jobject obj) {
+static jlong halOpen(JNIEnv *env, jobject obj) {
hw_module_t const* module;
consumerir_device_t *dev;
int err;
@@ -47,10 +47,10 @@
return 0;
}
- return reinterpret_cast<jint>(dev);
+ return reinterpret_cast<jlong>(dev);
}
-static jint halTransmit(JNIEnv *env, jobject obj, jint halObject,
+static jint halTransmit(JNIEnv *env, jobject obj, jlong halObject,
jint carrierFrequency, jintArray pattern) {
int ret;
@@ -67,8 +67,8 @@
}
static jintArray halGetCarrierFrequencies(JNIEnv *env, jobject obj,
- jint halObject) {
- consumerir_device_t *dev = (consumerir_device_t *) halObject;
+ jlong halObject) {
+ consumerir_device_t *dev = reinterpret_cast<consumerir_device_t*>(halObject);
consumerir_freq_range_t *ranges;
int len;
@@ -101,9 +101,9 @@
}
static JNINativeMethod method_table[] = {
- { "halOpen", "()I", (void *)halOpen },
- { "halTransmit", "(II[I)I", (void *)halTransmit },
- { "halGetCarrierFrequencies", "(I)[I", (void *)halGetCarrierFrequencies},
+ { "halOpen", "()J", (void *)halOpen },
+ { "halTransmit", "(JI[I)I", (void *)halTransmit },
+ { "halGetCarrierFrequencies", "(J)[I", (void *)halGetCarrierFrequencies},
};
int register_android_server_ConsumerIrService(JNIEnv *env) {
diff --git a/tests/SystemUIDemoModeController/Android.mk b/tests/SystemUIDemoModeController/Android.mk
new file mode 100644
index 0000000..64ea63c
--- /dev/null
+++ b/tests/SystemUIDemoModeController/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := DemoModeController
+
+include $(BUILD_PACKAGE)
diff --git a/tests/SystemUIDemoModeController/AndroidManifest.xml b/tests/SystemUIDemoModeController/AndroidManifest.xml
new file mode 100644
index 0000000..2e97932
--- /dev/null
+++ b/tests/SystemUIDemoModeController/AndroidManifest.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.demomodecontroller"
+ android:versionCode="1"
+ android:versionName="0.1" >
+
+ <uses-sdk
+ android:minSdkVersion="19"
+ android:targetSdkVersion="19" />
+
+ <application
+ android:allowBackup="false"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".DemoModeController" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/tests/SystemUIDemoModeController/res/values/strings.xml b/tests/SystemUIDemoModeController/res/values/strings.xml
new file mode 100644
index 0000000..257a353
--- /dev/null
+++ b/tests/SystemUIDemoModeController/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<resources>
+
+ <string name="app_name">Demo Mode Controller</string>
+ <string name="help_text">"Drag: control icon states\nLong-press + drag: control background color\nDouble-tap: toggle bar mode</string>
+
+</resources>
diff --git a/tests/SystemUIDemoModeController/src/com/example/android/demomodecontroller/DemoModeController.java b/tests/SystemUIDemoModeController/src/com/example/android/demomodecontroller/DemoModeController.java
new file mode 100644
index 0000000..b177d7e
--- /dev/null
+++ b/tests/SystemUIDemoModeController/src/com/example/android/demomodecontroller/DemoModeController.java
@@ -0,0 +1,340 @@
+/*
+ * Copyright (C) 2014 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.example.android.demomodecontroller;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Color;
+import android.graphics.PointF;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.SystemClock;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnTouchListener;
+import android.view.ViewConfiguration;
+import android.view.WindowManager;
+import android.widget.Toast;
+
+public class DemoModeController extends Activity implements OnTouchListener {
+ private static final String TAG = DemoModeController.class.getSimpleName();
+ private static final boolean DEBUG = false;
+
+ private final Context mContext = this;
+ private final Handler mHandler = new Handler();
+ private final PointF mLastDown = new PointF();
+
+ private View mContent;
+ private Handler mBackground;
+ private int mTouchSlop;
+ private long mLastDownTime;
+ private boolean mControllingColor;
+ private Toast mToast;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS // so WM gives us enough room
+ | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+ getActionBar().hide();
+ mContent = new View(mContext);
+ mContent.setBackgroundColor(0xff33b5e5);
+ mContent.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+ | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+ mContent.setOnTouchListener(this);
+ setContentView(mContent);
+ mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+
+ final HandlerThread background = new HandlerThread("background");
+ background.start();
+ mBackground = new Handler(background.getLooper());
+ updateMode();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ exitDemoMode();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ exitDemoMode();
+ mToast = Toast.makeText(mContext, R.string.help_text, Toast.LENGTH_LONG);
+ mToast.show();
+ }
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ if (mToast != null) {
+ mToast.cancel();
+ mToast = null;
+ }
+ final int action = event.getAction();
+ if (action == MotionEvent.ACTION_DOWN) {
+ if (DEBUG) Log.d(TAG, "down");
+ mHandler.postDelayed(mLongPressCheck, 500);
+ final long now = SystemClock.uptimeMillis();
+ if (now - mLastDownTime < 200) {
+ toggleMode();
+ }
+ mLastDownTime = now;
+ mLastDown.x = event.getX();
+ mLastDown.y = event.getY();
+ return true;
+ }
+ if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
+ if (DEBUG) Log.d(TAG, "upOrCancel");
+ mControllingColor = false;
+ mHandler.removeCallbacks(mLongPressCheck);
+ }
+ if (action != MotionEvent.ACTION_MOVE) return false;
+
+ float x = event.getX();
+ float y = event.getY();
+ if (Math.abs(mLastDown.x - x) > mTouchSlop || Math.abs(mLastDown.y - y) > mTouchSlop) {
+ mHandler.removeCallbacks(mLongPressCheck);
+ }
+ x = Math.max(x, 0);
+ y = Math.max(y, 0);
+ final int h = mContent.getMeasuredHeight();
+ final int w = mContent.getMeasuredWidth();
+ x = Math.min(x, w);
+ y = Math.min(y, h);
+
+ y = h - y;
+ x = w - x;
+
+ if (mControllingColor) {
+ final float hue = y / (h / 360);
+ final float sat = 1 - (x / (float)w);
+ final float val = x / (float)w;
+ final int color = Color.HSVToColor(new float[]{hue, sat, val});
+ if (DEBUG) Log.d(TAG, String.format("hsv=(%s,%s,%s) argb=#%08x", hue, sat, val, color));
+ mContent.setBackgroundColor(color);
+ return true;
+ }
+
+ final int hh = (int)x / (w / 12);
+ if (hh != mHH) {
+ mHH = hh;
+ mBackground.removeCallbacks(mUpdateClock);
+ mBackground.post(mUpdateClock);
+ }
+
+ final int mm = (int)y / (h / 60);
+ if (mm != mMM) {
+ mMM = mm;
+ mBackground.removeCallbacks(mUpdateClock);
+ mBackground.post(mUpdateClock);
+ }
+
+ final int batteryLevel = (int)y / (h / 101);
+ if (batteryLevel != mBatteryLevel) {
+ mBatteryLevel = batteryLevel;
+ mBackground.removeCallbacks(mUpdateBattery);
+ mBackground.post(mUpdateBattery);
+ }
+
+ final boolean batteryPlugged = x >= w / 2;
+ if (batteryPlugged != mBatteryPlugged) {
+ mBatteryPlugged = batteryPlugged;
+ mBackground.removeCallbacks(mUpdateBattery);
+ mBackground.post(mUpdateBattery);
+ }
+
+ final int mobileLevel = (int)y / (h / 10);
+ if (mobileLevel != mMobileLevel) {
+ mMobileLevel = mobileLevel;
+ mBackground.removeCallbacks(mUpdateMobile);
+ mBackground.post(mUpdateMobile);
+ }
+
+ final int wifiLevel = (int)y / (h / 10);
+ if (wifiLevel != mWifiLevel) {
+ mWifiLevel = wifiLevel;
+ mBackground.removeCallbacks(mUpdateWifi);
+ mBackground.post(mUpdateWifi);
+ }
+
+ final int statusSlots = (int)x / (w / 13);
+ if (statusSlots != mStatusSlots) {
+ mStatusSlots = statusSlots;
+ mBackground.removeCallbacks(mUpdateStatus);
+ mBackground.post(mUpdateStatus);
+ }
+
+ final int networkIcons = (int)x / (w / 4);
+ if (networkIcons != mNetworkIcons) {
+ mNetworkIcons = networkIcons;
+ mBackground.removeCallbacks(mUpdateNetwork);
+ mBackground.post(mUpdateNetwork);
+ }
+
+ final int mobileDataType = (int)y / (h / 9);
+ if (mobileDataType != mMobileDataType) {
+ mMobileDataType = mobileDataType;
+ mBackground.removeCallbacks(mUpdateMobile);
+ mBackground.post(mUpdateMobile);
+ }
+ return true;
+ }
+
+ private void toggleMode() {
+ if (DEBUG) Log.d(TAG, "toggleMode");
+ mBarMode = (mBarMode + 1) % 3;
+ updateMode();
+ }
+
+ private void updateMode() {
+ mBackground.removeCallbacks(mUpdateBarMode);
+ mBackground.post(mUpdateBarMode);
+ }
+
+ private final Runnable mLongPressCheck = new Runnable() {
+ @Override
+ public void run() {
+ if (DEBUG) Log.d(TAG, "mControllingColor = true");
+ mControllingColor = true;
+
+ }
+ };
+
+ private void exitDemoMode() {
+ if (DEBUG) Log.d(TAG, "exitDemoMode");
+ final Intent intent = new Intent("com.android.systemui.demo");
+ intent.putExtra("command", "exit");
+ mContext.sendBroadcast(intent);
+ }
+
+ private int mStatusSlots; // 0 - 12
+ private final Runnable mUpdateStatus = new Runnable() {
+ @Override
+ public void run() {
+ final Intent intent = new Intent("com.android.systemui.demo");
+ intent.putExtra("command", "status");
+ intent.putExtra("volume", mStatusSlots < 1 ? "hide"
+ : mStatusSlots < 2 ? "silent" : "vibrate");
+ intent.putExtra("bluetooth", mStatusSlots < 3 ? "hide"
+ : mStatusSlots < 4 ? "disconnected" : "connected");
+ intent.putExtra("location", mStatusSlots < 5 ? "hide" : "show");
+ intent.putExtra("alarm", mStatusSlots < 6 ? "hide" : "show");
+ intent.putExtra("sync", mStatusSlots < 7 ? "hide" : "show");
+ intent.putExtra("tty", mStatusSlots < 8 ? "hide" : "show");
+ intent.putExtra("eri", mStatusSlots < 9 ? "hide" : "show");
+ intent.putExtra("secure", mStatusSlots < 10 ? "hide" : "show");
+ intent.putExtra("mute", mStatusSlots < 11 ? "hide" : "show");
+ intent.putExtra("speakerphone", mStatusSlots < 12 ? "hide" : "show");
+ mContext.sendBroadcast(intent);
+ }
+ };
+
+ private int mNetworkIcons; // 0:airplane 1:mobile 2:airplane+wifi 3:mobile+wifi
+ private final Runnable mUpdateNetwork = new Runnable() {
+ @Override
+ public void run() {
+ final Intent intent = new Intent("com.android.systemui.demo");
+ intent.putExtra("command", "network");
+ intent.putExtra("airplane", mNetworkIcons % 2 == 0 ? "show" : "hide");
+ intent.putExtra("wifi", mNetworkIcons >= 2 ? "show" : "hide");
+ intent.putExtra("mobile", mNetworkIcons % 2 == 1 ? "show" : "hide");
+ mContext.sendBroadcast(intent);
+ }
+ };
+
+ private int mWifiLevel; // 0 - 4, 5 - 9, fully
+ private final Runnable mUpdateWifi = new Runnable() {
+ @Override
+ public void run() {
+ final Intent intent = new Intent("com.android.systemui.demo");
+ intent.putExtra("command", "network");
+ intent.putExtra("wifi", mNetworkIcons >= 2 ? "show" : "hide");
+ intent.putExtra("level", Integer.toString(mWifiLevel % 5));
+ intent.putExtra("fully", Boolean.toString(mWifiLevel > 4));
+ mContext.sendBroadcast(intent);
+ }
+ };
+
+ private int mMobileLevel; // 0 - 4, 5 - 9, fully
+ private int mMobileDataType; // 0 - 8
+ private static final String getDataType(int dataType) {
+ if (dataType == 1) return "1x";
+ if (dataType == 2) return "3g";
+ if (dataType == 3) return "4g";
+ if (dataType == 4) return "e";
+ if (dataType == 5) return "g";
+ if (dataType == 6) return "h";
+ if (dataType == 7) return "lte";
+ if (dataType == 8) return "roam";
+ return "";
+ }
+ private final Runnable mUpdateMobile = new Runnable() {
+ @Override
+ public void run() {
+ final Intent intent = new Intent("com.android.systemui.demo");
+ intent.putExtra("command", "network");
+ intent.putExtra("mobile", mNetworkIcons % 2 == 1 ? "show" : "hide");
+ intent.putExtra("level", Integer.toString(mMobileLevel % 5));
+ intent.putExtra("fully", Boolean.toString(mMobileLevel > 4));
+ intent.putExtra("datatype", getDataType(mMobileDataType));
+ mContext.sendBroadcast(intent);
+ }
+ };
+
+ private boolean mBatteryPlugged;
+ private int mBatteryLevel; // 0 - 100
+ private final Runnable mUpdateBattery = new Runnable() {
+ @Override
+ public void run() {
+ final Intent intent = new Intent("com.android.systemui.demo");
+ intent.putExtra("command", "battery");
+ intent.putExtra("level", Integer.toString(mBatteryLevel));
+ intent.putExtra("plugged", Boolean.toString(mBatteryPlugged));
+ mContext.sendBroadcast(intent);
+ }
+ };
+
+ private int mHH; // 0 - 11
+ private int mMM; // 0 - 59
+ private final Runnable mUpdateClock = new Runnable() {
+ @Override
+ public void run() {
+ final Intent intent = new Intent("com.android.systemui.demo");
+ intent.putExtra("command", "clock");
+ intent.putExtra("hhmm", String.format("%02d%02d", mHH + 1, mMM));
+ mContext.sendBroadcast(intent);
+ }
+ };
+
+ private int mBarMode; // 0 - 2 (opaque, semi-transparent, translucent)
+ private final Runnable mUpdateBarMode = new Runnable() {
+ @Override
+ public void run() {
+ final Intent intent = new Intent("com.android.systemui.demo");
+ intent.putExtra("command", "bars");
+ intent.putExtra("mode", mBarMode == 1 ? "semi-transparent"
+ : mBarMode == 2 ? "translucent" : "opaque");
+ mContext.sendBroadcast(intent);
+ }
+ };
+}