diff options
20 files changed, 413 insertions, 93 deletions
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java index 359cdac4560c..906361c3bcb5 100644 --- a/core/java/android/app/SearchDialog.java +++ b/core/java/android/app/SearchDialog.java @@ -139,8 +139,8 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS // A weak map of drawables we've gotten from other packages, so we don't load them // more than once. - private final WeakHashMap<String, Drawable> mOutsideDrawablesCache = - new WeakHashMap<String, Drawable>(); + private final WeakHashMap<String, Drawable.ConstantState> mOutsideDrawablesCache = + new WeakHashMap<String, Drawable.ConstantState>(); // Last known IME options value for the search edit text. private int mSearchAutoCompleteImeOptions; diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java index f2325d020772..593b7b736cfa 100644 --- a/core/java/android/app/SuggestionsAdapter.java +++ b/core/java/android/app/SuggestionsAdapter.java @@ -61,8 +61,8 @@ class SuggestionsAdapter extends ResourceCursorAdapter { private SearchDialog mSearchDialog; private SearchableInfo mSearchable; private Context mProviderContext; - private WeakHashMap<String, Drawable> mOutsideDrawablesCache; - private SparseArray<Drawable> mBackgroundsCache; + private WeakHashMap<String, Drawable.ConstantState> mOutsideDrawablesCache; + private SparseArray<Drawable.ConstantState> mBackgroundsCache; private boolean mGlobalSearchMode; // Cached column indexes, updated when the cursor changes. @@ -97,8 +97,10 @@ class SuggestionsAdapter extends ResourceCursorAdapter { */ private static final long DELETE_KEY_POST_DELAY = 500L; - public SuggestionsAdapter(Context context, SearchDialog searchDialog, SearchableInfo searchable, - WeakHashMap<String, Drawable> outsideDrawablesCache, boolean globalSearchMode) { + public SuggestionsAdapter(Context context, SearchDialog searchDialog, + SearchableInfo searchable, + WeakHashMap<String, Drawable.ConstantState> outsideDrawablesCache, + boolean globalSearchMode) { super(context, com.android.internal.R.layout.search_dropdown_item_icons_2line, null, // no initial cursor @@ -112,7 +114,7 @@ class SuggestionsAdapter extends ResourceCursorAdapter { mProviderContext = mSearchable.getProviderContext(mContext, activityContext); mOutsideDrawablesCache = outsideDrawablesCache; - mBackgroundsCache = new SparseArray<Drawable>(); + mBackgroundsCache = new SparseArray<Drawable.ConstantState>(); mGlobalSearchMode = globalSearchMode; mStartSpinnerRunnable = new Runnable() { @@ -345,11 +347,10 @@ class SuggestionsAdapter extends ResourceCursorAdapter { if (backgroundColor == 0) { return null; } else { - Drawable cachedBg = mBackgroundsCache.get(backgroundColor); + Drawable.ConstantState cachedBg = mBackgroundsCache.get(backgroundColor); if (cachedBg != null) { if (DBG) Log.d(LOG_TAG, "Background cache hit for color " + backgroundColor); - // copy the drawable so that they don't share states - return cachedBg.getConstantState().newDrawable(); + return cachedBg.newDrawable(); } if (DBG) Log.d(LOG_TAG, "Creating new background for color " + backgroundColor); ColorDrawable transparent = new ColorDrawable(0); @@ -358,7 +359,7 @@ class SuggestionsAdapter extends ResourceCursorAdapter { newBg.addState(new int[]{android.R.attr.state_selected}, transparent); newBg.addState(new int[]{android.R.attr.state_pressed}, transparent); newBg.addState(new int[]{}, background); - mBackgroundsCache.put(backgroundColor, newBg); + mBackgroundsCache.put(backgroundColor, newBg.getConstantState()); return newBg; } } @@ -523,12 +524,13 @@ class SuggestionsAdapter extends ResourceCursorAdapter { } // First, check the cache. - Drawable drawable = mOutsideDrawablesCache.get(drawableId); - if (drawable != null) { + Drawable.ConstantState cached = mOutsideDrawablesCache.get(drawableId); + if (cached != null) { if (DBG) Log.d(LOG_TAG, "Found icon in cache: " + drawableId); - return drawable; + return cached.newDrawable(); } + Drawable drawable = null; try { // Not cached, try using it as a plain resource ID in the provider's context. int resourceId = Integer.parseInt(drawableId); @@ -560,7 +562,7 @@ class SuggestionsAdapter extends ResourceCursorAdapter { // If we got a drawable for this resource id, then stick it in the // map so we don't do this lookup again. if (drawable != null) { - mOutsideDrawablesCache.put(drawableId, drawable); + mOutsideDrawablesCache.put(drawableId, drawable.getConstantState()); } } catch (Resources.NotFoundException nfe) { if (DBG) Log.d(LOG_TAG, "Icon resource not found: " + drawableId); @@ -615,12 +617,14 @@ class SuggestionsAdapter extends ResourceCursorAdapter { String componentIconKey = component.flattenToShortString(); // Using containsKey() since we also store null values. if (mOutsideDrawablesCache.containsKey(componentIconKey)) { - return mOutsideDrawablesCache.get(componentIconKey); + Drawable.ConstantState cached = mOutsideDrawablesCache.get(componentIconKey); + return cached == null ? null : cached.newDrawable(); } // Then try the activity or application icon Drawable drawable = getActivityIcon(component); // Stick it in the cache so we don't do this lookup again. - mOutsideDrawablesCache.put(componentIconKey, drawable); + Drawable.ConstantState toCache = drawable == null ? null : drawable.getConstantState(); + mOutsideDrawablesCache.put(componentIconKey, toCache); return drawable; } diff --git a/core/java/android/appwidget/AppWidgetProvider.java b/core/java/android/appwidget/AppWidgetProvider.java index 26712a10f0ce..f1bbedef9024 100755 --- a/core/java/android/appwidget/AppWidgetProvider.java +++ b/core/java/android/appwidget/AppWidgetProvider.java @@ -64,11 +64,9 @@ public class AppWidgetProvider extends BroadcastReceiver { } else if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) { Bundle extras = intent.getExtras(); - if (extras != null) { - int[] appWidgetIds = extras.getIntArray(AppWidgetManager.EXTRA_APPWIDGET_IDS); - if (appWidgetIds != null && appWidgetIds.length > 0) { - this.onDeleted(context, appWidgetIds); - } + if (extras != null && extras.containsKey(AppWidgetManager.EXTRA_APPWIDGET_ID)) { + final int appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID); + this.onDeleted(context, new int[] { appWidgetId }); } } else if (AppWidgetManager.ACTION_APPWIDGET_ENABLED.equals(action)) { diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java index ebe556e3cd65..08e3a40e66a0 100644 --- a/core/java/android/content/res/CompatibilityInfo.java +++ b/core/java/android/content/res/CompatibilityInfo.java @@ -38,7 +38,12 @@ public class CompatibilityInfo { private static final String TAG = "CompatibilityInfo"; /** default compatibility info object for compatible applications */ - public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo(); + public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo() { + @Override + public void setExpandable(boolean expandable) { + throw new UnsupportedOperationException("trying to change default compatibility info"); + } + }; /** * The default width of the screen in portrait mode. @@ -191,7 +196,7 @@ public class CompatibilityInfo { @Override public String toString() { return "CompatibilityInfo{scale=" + applicationScale + - ", compatibility flag=" + mCompatibilityFlags + "}"; + ", supports screen=" + supportsScreen() + "}"; } /** diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index ff1eb532dff0..28c1fe1fefb5 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -17,7 +17,6 @@ package android.view; import android.content.Context; -import android.content.res.CompatibilityInfo; import android.content.res.CompatibilityInfo.Translator; import android.graphics.Canvas; import android.graphics.PixelFormat; @@ -256,7 +255,7 @@ public class SurfaceView extends View { public boolean dispatchTouchEvent(MotionEvent event) { // SurfaceView uses pre-scaled size unless fixed size is requested. This hook // scales the event back to the pre-scaled coordinates for such surface. - if (mRequestedWidth < 0 && mTranslator != null) { + if (mScaled) { MotionEvent scaledBack = MotionEvent.obtain(event); scaledBack.scale(mTranslator.applicationScale); try { @@ -290,6 +289,8 @@ public class SurfaceView extends View { public void setWindowType(int type) { mWindowType = type; } + + boolean mScaled = false; private void updateWindow(boolean force) { if (!mHaveFrame) { @@ -309,6 +310,9 @@ public class SurfaceView extends View { if (mRequestedWidth <= 0 && mTranslator != null) { myWidth *= appScale; myHeight *= appScale; + mScaled = true; + } else { + mScaled = false; } getLocationInWindow(mLocation); @@ -533,6 +537,7 @@ public class SurfaceView extends View { private SurfaceHolder mSurfaceHolder = new SurfaceHolder() { private static final String LOG_TAG = "SurfaceHolder"; + private int mSaveCount; public boolean isCreating() { return mIsCreating; @@ -627,6 +632,10 @@ public class SurfaceView extends View { if (localLOGV) Log.i(TAG, "Returned canvas: " + c); if (c != null) { mLastLockTime = SystemClock.uptimeMillis(); + if (mScaled) { + mSaveCount = c.save(); + mTranslator.translateCanvas(c); + } return c; } @@ -649,6 +658,9 @@ public class SurfaceView extends View { } public void unlockCanvasAndPost(Canvas canvas) { + if (mScaled) { + canvas.restoreToCount(mSaveCount); + } mSurface.unlockCanvasAndPost(canvas); mSurfaceLock.unlock(); } diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index eab3799a9059..301d604bac76 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -497,8 +497,12 @@ public final class ViewRoot extends Handler implements ViewParent, void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) { synchronized (this) { int oldSoftInputMode = mWindowAttributes.softInputMode; + // preserve compatible window flag if exists. + int compatibleWindowFlag = + mWindowAttributes.flags & WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW; mWindowAttributes.copyFrom(attrs); - + mWindowAttributes.flags |= compatibleWindowFlag; + if (newView) { mSoftInputMode = attrs.softInputMode; requestLayout(); @@ -1301,7 +1305,8 @@ public final class ViewRoot extends Handler implements ViewParent, if (DEBUG_DRAW) { Context cxt = mView.getContext(); Log.i(TAG, "Drawing: package:" + cxt.getPackageName() + - ", metrics=" + mView.getContext().getResources().getDisplayMetrics()); + ", metrics=" + cxt.getResources().getDisplayMetrics() + + ", compatibilityInfo=" + cxt.getResources().getCompatibilityInfo()); } int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG); try { diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index e96a15ba05f2..ba3bfa76f5c2 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -986,6 +986,9 @@ public interface WindowManager extends ViewManager { sb.append(" or="); sb.append(screenOrientation); } + if ((flags & FLAG_COMPATIBLE_WINDOW) != 0) { + sb.append(" compatible=true"); + } sb.append('}'); return sb.toString(); } diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp index af8ecf5cccc3..3fb07a74a6f6 100644 --- a/core/jni/android/graphics/Bitmap.cpp +++ b/core/jni/android/graphics/Bitmap.cpp @@ -224,7 +224,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors, SkBitmap bitmap;
bitmap.setConfig(config, width, height);
- if (!GraphicsJNI::setJavaPixelRef(env, &bitmap, NULL)) {
+ if (!GraphicsJNI::setJavaPixelRef(env, &bitmap, NULL, true)) {
return NULL;
}
@@ -240,7 +240,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors, static jobject Bitmap_copy(JNIEnv* env, jobject, const SkBitmap* src,
SkBitmap::Config dstConfig, jboolean isMutable) {
SkBitmap result;
- JavaPixelAllocator allocator(env);
+ JavaPixelAllocator allocator(env, true);
if (!src->copyTo(&result, dstConfig, &allocator)) {
return NULL;
@@ -356,7 +356,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) { }
}
- if (!GraphicsJNI::setJavaPixelRef(env, bitmap, ctable)) {
+ if (!GraphicsJNI::setJavaPixelRef(env, bitmap, ctable, true)) {
ctable->safeUnref();
delete bitmap;
return NULL;
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp index 137707fa93bf..0c842650962f 100644 --- a/core/jni/android/graphics/BitmapFactory.cpp +++ b/core/jni/android/graphics/BitmapFactory.cpp @@ -23,6 +23,7 @@ static jfieldID gOptions_configFieldID; static jfieldID gOptions_ditherFieldID; static jfieldID gOptions_purgeableFieldID; static jfieldID gOptions_shareableFieldID; +static jfieldID gOptions_nativeAllocFieldID; static jfieldID gOptions_widthFieldID; static jfieldID gOptions_heightFieldID; static jfieldID gOptions_mimeFieldID; @@ -300,6 +301,11 @@ static bool optionsShareable(JNIEnv* env, jobject options) { env->GetBooleanField(options, gOptions_shareableFieldID); } +static bool optionsReportSizeToVM(JNIEnv* env, jobject options) { + return NULL == options || + !env->GetBooleanField(options, gOptions_nativeAllocFieldID); +} + static jobject nullObjectReturn(const char msg[]) { if (msg) { SkDebugf("--- %s\n", msg); @@ -330,6 +336,7 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, SkBitmap::Config prefConfig = SkBitmap::kNo_Config; bool doDither = true; bool isPurgeable = allowPurgeable && optionsPurgeable(env, options); + bool reportSizeToVM = optionsReportSizeToVM(env, options); if (NULL != options) { sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID); @@ -355,7 +362,7 @@ static jobject doDecode(JNIEnv* env, SkStream* stream, jobject padding, decoder->setDitherImage(doDither); NinePatchPeeker peeker; - JavaPixelAllocator javaAllocator(env); + JavaPixelAllocator javaAllocator(env, reportSizeToVM); SkBitmap* bitmap = new SkBitmap; Res_png_9patch dummy9Patch; @@ -699,6 +706,7 @@ int register_android_graphics_BitmapFactory(JNIEnv* env) { gOptions_ditherFieldID = getFieldIDCheck(env, gOptions_class, "inDither", "Z"); gOptions_purgeableFieldID = getFieldIDCheck(env, gOptions_class, "inPurgeable", "Z"); gOptions_shareableFieldID = getFieldIDCheck(env, gOptions_class, "inInputShareable", "Z"); + gOptions_nativeAllocFieldID = getFieldIDCheck(env, gOptions_class, "inNativeAlloc", "Z"); gOptions_widthFieldID = getFieldIDCheck(env, gOptions_class, "outWidth", "I"); gOptions_heightFieldID = getFieldIDCheck(env, gOptions_class, "outHeight", "I"); gOptions_mimeFieldID = getFieldIDCheck(env, gOptions_class, "outMimeType", "Ljava/lang/String;"); diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp index 6eebbdcfb563..6e159a8853d5 100644 --- a/core/jni/android/graphics/Graphics.cpp +++ b/core/jni/android/graphics/Graphics.cpp @@ -5,6 +5,7 @@ #include "SkRegion.h" #include <android_runtime/AndroidRuntime.h> +//#define REPORT_SIZE_TO_JVM //#define TRACK_LOCK_COUNT void doThrow(JNIEnv* env, const char* exc, const char* msg) { @@ -444,7 +445,7 @@ private: }; bool GraphicsJNI::setJavaPixelRef(JNIEnv* env, SkBitmap* bitmap, - SkColorTable* ctable) { + SkColorTable* ctable, bool reportSizeToVM) { Sk64 size64 = bitmap->getSize64(); if (size64.isNeg() || !size64.is32()) { doThrow(env, "java/lang/IllegalArgumentException", @@ -453,35 +454,41 @@ bool GraphicsJNI::setJavaPixelRef(JNIEnv* env, SkBitmap* bitmap, } size_t size = size64.get32(); - // SkDebugf("-------------- inform VM we've allocated %d bytes\n", size); jlong jsize = size; // the VM wants longs for the size - bool r = env->CallBooleanMethod(gVMRuntime_singleton, - gVMRuntime_trackExternalAllocationMethodID, - jsize); - if (GraphicsJNI::hasException(env)) { - return false; - } - if (!r) { - LOGE("VM won't let us allocate %zd bytes\n", size); - doThrowOOME(env, "bitmap size exceeds VM budget"); - return false; + if (reportSizeToVM) { + // SkDebugf("-------------- inform VM we've allocated %d bytes\n", size); + bool r = env->CallBooleanMethod(gVMRuntime_singleton, + gVMRuntime_trackExternalAllocationMethodID, + jsize); + if (GraphicsJNI::hasException(env)) { + return false; + } + if (!r) { + LOGE("VM won't let us allocate %zd bytes\n", size); + doThrowOOME(env, "bitmap size exceeds VM budget"); + return false; + } } - // call the version of malloc that returns null on failure void* addr = sk_malloc_flags(size, 0); if (NULL == addr) { - // SkDebugf("-------------- inform VM we're releasing %d bytes which we couldn't allocate\n", size); - // we didn't actually allocate it, so inform the VM - env->CallVoidMethod(gVMRuntime_singleton, - gVMRuntime_trackExternalFreeMethodID, - jsize); - if (!GraphicsJNI::hasException(env)) { - doThrowOOME(env, "bitmap size too large for malloc"); + if (reportSizeToVM) { + // SkDebugf("-------------- inform VM we're releasing %d bytes which we couldn't allocate\n", size); + // we didn't actually allocate it, so inform the VM + env->CallVoidMethod(gVMRuntime_singleton, + gVMRuntime_trackExternalFreeMethodID, + jsize); + if (!GraphicsJNI::hasException(env)) { + doThrowOOME(env, "bitmap size too large for malloc"); + } } return false; } - bitmap->setPixelRef(new AndroidPixelRef(env, addr, size, ctable))->unref(); + SkPixelRef* pr = reportSizeToVM ? + new AndroidPixelRef(env, addr, size, ctable) : + new SkMallocPixelRef(addr, size, ctable); + bitmap->setPixelRef(pr)->unref(); // since we're already allocated, we lockPixels right away // HeapAllocator behaves this way too bitmap->lockPixels(); @@ -490,12 +497,11 @@ bool GraphicsJNI::setJavaPixelRef(JNIEnv* env, SkBitmap* bitmap, /////////////////////////////////////////////////////////////////////////////// -JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env) : fEnv(env) -{ -} +JavaPixelAllocator::JavaPixelAllocator(JNIEnv* env, bool reportSizeToVM) + : fEnv(env), fReportSizeToVM(reportSizeToVM) {} bool JavaPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) { - return GraphicsJNI::setJavaPixelRef(fEnv, bitmap, ctable); + return GraphicsJNI::setJavaPixelRef(fEnv, bitmap, ctable, fReportSizeToVM); } //////////////////////////////////////////////////////////////////////////////// diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h index e2dc9acf1beb..16925e41ab4f 100644 --- a/core/jni/android/graphics/GraphicsJNI.h +++ b/core/jni/android/graphics/GraphicsJNI.h @@ -59,7 +59,8 @@ public: Returns true on success. If it returns false, then it failed, and the appropriate exception will have been raised. */ - static bool setJavaPixelRef(JNIEnv*, SkBitmap*, SkColorTable* ctable); + static bool setJavaPixelRef(JNIEnv*, SkBitmap*, SkColorTable* ctable, + bool reportSizeToVM); /** Copy the colors in colors[] to the bitmap, convert to the correct format along the way. @@ -71,12 +72,13 @@ public: class JavaPixelAllocator : public SkBitmap::Allocator { public: - JavaPixelAllocator(JNIEnv* env); + JavaPixelAllocator(JNIEnv* env, bool reportSizeToVM); // overrides virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable); private: JNIEnv* fEnv; + bool fReportSizeToVM; }; class AutoJavaFloatArray { diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp index e71e3481862e..44a9e8cbcc58 100644 --- a/core/jni/android_media_AudioRecord.cpp +++ b/core/jni/android_media_AudioRecord.cpp @@ -212,8 +212,10 @@ android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this, // failure: native_init_failure: + env->DeleteGlobalRef(lpCallbackData->audioRecord_class); + env->DeleteGlobalRef(lpCallbackData->audioRecord_ref); delete lpCallbackData; - + native_track_failure: delete lpRecorder; @@ -274,6 +276,8 @@ static void android_media_AudioRecord_finalize(JNIEnv *env, jobject thiz) { thiz, javaAudioRecordFields.nativeCallbackCookie); if (lpCookie) { LOGV("deleting lpCookie: %x\n", (int)lpCookie); + env->DeleteGlobalRef(lpCookie->audioRecord_class); + env->DeleteGlobalRef(lpCookie->audioRecord_ref); delete lpCookie; } diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java index e5a9aab7ad63..082e0c069c0e 100644 --- a/graphics/java/android/graphics/BitmapFactory.java +++ b/graphics/java/android/graphics/BitmapFactory.java @@ -129,6 +129,19 @@ public class BitmapFactory { public boolean inInputShareable; /** + * Normally bitmap allocations count against the dalvik heap, which + * means they help trigger GCs when a lot have been allocated. However, + * in rare cases, the caller may want to allocate the bitmap outside of + * that heap. To request that, set inNativeAlloc to true. In these + * rare instances, it is solely up to the caller to ensure that OOM is + * managed explicitly by calling bitmap.recycle() as soon as such a + * bitmap is no longer needed. + * + * @hide pending API council approval + */ + public boolean inNativeAlloc; + + /** * The resulting width of the bitmap, set independent of the state of * inJustDecodeBounds. However, if there is an error trying to decode, * outWidth will be set to -1. diff --git a/keystore/java/android/security/CertTool.java b/keystore/java/android/security/CertTool.java index 26d22aec57fb..c96cd4f4d907 100644 --- a/keystore/java/android/security/CertTool.java +++ b/keystore/java/android/security/CertTool.java @@ -16,11 +16,19 @@ package android.security; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; + import android.content.Context; import android.content.Intent; import android.security.Keystore; import android.text.TextUtils; - +import android.util.Log; /** * The CertTool class provides the functions to list the certs/keys, @@ -41,12 +49,12 @@ public class CertTool { public static final String KEY_NAMESPACE = "namespace"; public static final String KEY_DESCRIPTION = "description"; - private static final String TAG = "CertTool"; + public static final String TITLE_CA_CERT = "CA Certificate"; + public static final String TITLE_USER_CERT = "User Certificate"; + public static final String TITLE_PKCS12_KEYSTORE = "PKCS12 Keystore"; + public static final String TITLE_PRIVATE_KEY = "Private Key"; - private static final String TITLE_CA_CERT = "CA Certificate"; - private static final String TITLE_USER_CERT = "User Certificate"; - private static final String TITLE_PKCS12_KEYSTORE = "PKCS12 Keystore"; - private static final String TITLE_PRIVATE_KEY = "Private Key"; + private static final String TAG = "CertTool"; private static final String UNKNOWN = "Unknown"; private static final String ISSUER_NAME = "Issuer Name:"; private static final String DISTINCT_NAME = "Distinct Name:"; @@ -58,6 +66,11 @@ public class CertTool { private static final String KEYNAME_DELIMITER = "_"; private static final Keystore sKeystore = Keystore.getInstance(); + private native int getPkcs12Handle(byte[] data, String password); + private native String getPkcs12Certificate(int handle); + private native String getPkcs12PrivateKey(int handle); + private native String popPkcs12CertificateStack(int handle); + private native void freePkcs12Handle(int handle); private native String generateCertificateRequest(int bits, String subject); private native boolean isPkcs12Keystore(byte[] data); private native int generateX509Certificate(byte[] data); @@ -130,10 +143,35 @@ public class CertTool { intent.putExtra(KEY_NAMESPACE + "1", namespace); } + public int addPkcs12Keystore(byte[] p12Data, String password, + String keyname) { + int handle, i = 0; + String pemData; + Log.i("CertTool", "addPkcs12Keystore()"); + + if ((handle = getPkcs12Handle(p12Data, password)) == 0) return -1; + if ((pemData = getPkcs12Certificate(handle)) != null) { + sKeystore.put(USER_CERTIFICATE, keyname, pemData); + } + if ((pemData = getPkcs12PrivateKey(handle)) != null) { + sKeystore.put(USER_KEY, keyname, pemData); + } + while ((pemData = this.popPkcs12CertificateStack(handle)) != null) { + if (i++ > 0) { + sKeystore.put(CA_CERTIFICATE, keyname + i, pemData); + } else { + sKeystore.put(CA_CERTIFICATE, keyname, pemData); + } + } + freePkcs12Handle(handle); + return 0; + } + public synchronized void addCertificate(byte[] data, Context context) { int handle; Intent intent = null; + Log.i("CertTool", "addCertificate()"); if (isPkcs12Keystore(data)) { intent = prepareIntent(TITLE_PKCS12_KEYSTORE, data, USER_KEY, UNKNOWN, UNKNOWN); diff --git a/keystore/jni/cert.c b/keystore/jni/cert.c index cc36b84e99a3..0db28fd0e822 100644 --- a/keystore/jni/cert.c +++ b/keystore/jni/cert.c @@ -136,30 +136,126 @@ err: return ret_code; } -int is_pkcs12(const char *buf, int bufLen) +PKCS12 *get_p12_handle(const char *buf, int bufLen) { - int ret = 0; BIO *bp = NULL; PKCS12 *p12 = NULL; - if (!buf || bufLen < 1) goto err; + if (!buf || (bufLen < 1) || (buf[0] != 48)) goto err; bp = BIO_new(BIO_s_mem()); if (!bp) goto err; - if (buf[0] != 48) goto err; // it is not DER. - if (!BIO_write(bp, buf, bufLen)) goto err; - if ((p12 = d2i_PKCS12_bio(bp, NULL)) != NULL) { - PKCS12_free(p12); - ret = 1; - } + p12 = d2i_PKCS12_bio(bp, NULL); + err: if (bp) BIO_free(bp); + return p12; +} + +PKCS12_KEYSTORE *get_pkcs12_keystore_handle(const char *buf, int bufLen, + const char *passwd) +{ + PKCS12_KEYSTORE *p12store = NULL; + EVP_PKEY *pkey = NULL; + X509 *cert = NULL; + STACK_OF(X509) *certs = NULL; + PKCS12 *p12 = get_p12_handle(buf, bufLen); + + if (p12 == NULL) return NULL; + if (!PKCS12_parse(p12, passwd, &pkey, &cert, &certs)) { + LOGE("Can not parse PKCS12 content"); + PKCS12_free(p12); + return NULL; + } + if ((p12store = malloc(sizeof(PKCS12_KEYSTORE))) == NULL) { + if (cert) X509_free(cert); + if (pkey) EVP_PKEY_free(pkey); + if (certs) sk_X509_free(certs); + } + p12store->p12 = p12; + p12store->pkey = pkey; + p12store->cert = cert; + p12store->certs = certs; + return p12store; +} + +void free_pkcs12_keystore(PKCS12_KEYSTORE *p12store) +{ + if (p12store != NULL) { + if (p12store->cert) X509_free(p12store->cert); + if (p12store->pkey) EVP_PKEY_free(p12store->pkey); + if (p12store->certs) sk_X509_free(p12store->certs); + free(p12store); + } +} + +int is_pkcs12(const char *buf, int bufLen) +{ + int ret = 0; + PKCS12 *p12 = get_p12_handle(buf, bufLen); + if (p12 != NULL) ret = 1; + PKCS12_free(p12); return ret; } +static int convert_to_pem(void *data, int is_cert, char *buf, int size) +{ + int len = 0; + BIO *bio = NULL; + + if (data == NULL) return -1; + + if ((bio = BIO_new(BIO_s_mem())) == NULL) goto err; + if (is_cert) { + if ((len = PEM_write_bio_X509(bio, (X509*)data)) == 0) { + goto err; + } + } else { + if ((len = PEM_write_bio_PrivateKey(bio, (EVP_PKEY *)data, NULL, + NULL, 0, NULL, NULL)) == 0) { + goto err; + } + } + if (len < size && (len = BIO_read(bio, buf, size - 1)) > 0) { + buf[len] = 0; + } +err: + if (bio) BIO_free(bio); + return (len == 0) ? -1 : 0; +} + +int get_pkcs12_certificate(PKCS12_KEYSTORE *p12store, char *buf, int size) +{ + if ((p12store != NULL) && (p12store->cert != NULL)) { + return convert_to_pem((void*)p12store->cert, 1, buf, size); + } + return -1; +} + +int get_pkcs12_private_key(PKCS12_KEYSTORE *p12store, char *buf, int size) +{ + if ((p12store != NULL) && (p12store->pkey != NULL)) { + return convert_to_pem((void*)p12store->pkey, 0, buf, size); + } + return -1; +} + +int pop_pkcs12_certs_stack(PKCS12_KEYSTORE *p12store, char *buf, int size) +{ + X509 *cert = NULL; + + if ((p12store != NULL) && (p12store->certs != NULL) && + ((cert = sk_X509_pop(p12store->certs)) != NULL)) { + int ret = convert_to_pem((void*)cert, 1, buf, size); + X509_free(cert); + return ret; + } + return -1; +} + X509* parse_cert(const char *buf, int bufLen) { X509 *cert = NULL; diff --git a/keystore/jni/cert.h b/keystore/jni/cert.h index a9807b1b20f0..aaa7602d8126 100644 --- a/keystore/jni/cert.h +++ b/keystore/jni/cert.h @@ -41,6 +41,13 @@ typedef struct { int key_len; } PKEY_STORE; +typedef struct { + PKCS12 *p12; + EVP_PKEY *pkey; + X509 *cert; + STACK_OF(X509) *certs; +} PKCS12_KEYSTORE; + #define PKEY_STORE_free(x) { \ if(x.pkey) EVP_PKEY_free(x.pkey); \ if(x.public_key) free(x.public_key); \ @@ -49,8 +56,14 @@ typedef struct { #define nelem(x) (sizeof (x) / sizeof *(x)) int gen_csr(int bits, const char *organizations, char reply[REPLY_MAX]); +PKCS12_KEYSTORE *get_pkcs12_keystore_handle(const char *buf, int bufLen, + const char *passwd); +int get_pkcs12_certificate(PKCS12_KEYSTORE *p12store, char *buf, int size); +int get_pkcs12_private_key(PKCS12_KEYSTORE *p12store, char *buf, int size); +int pop_pkcs12_certs_stack(PKCS12_KEYSTORE *p12store, char *buf, int size); +void free_pkcs12_keystore(PKCS12_KEYSTORE *p12store); int is_pkcs12(const char *buf, int bufLen); -X509* parse_cert(const char *buf, int bufLen); +X509 *parse_cert(const char *buf, int bufLen); int get_cert_name(X509 *cert, char *buf, int size); int get_issuer_name(X509 *cert, char *buf, int size); int is_ca_cert(X509 *cert); diff --git a/keystore/jni/certtool.c b/keystore/jni/certtool.c index fabf5cdf3fb7..1ae8dab4281f 100644 --- a/keystore/jni/certtool.c +++ b/keystore/jni/certtool.c @@ -19,10 +19,13 @@ #include <string.h> #include <jni.h> #include <cutils/log.h> +#include <openssl/pkcs12.h> #include <openssl/x509v3.h> #include "cert.h" +typedef int PKCS12_KEYSTORE_FUNC(PKCS12_KEYSTORE *store, char *buf, int size); + jstring android_security_CertTool_generateCertificateRequest(JNIEnv* env, jobject thiz, @@ -42,12 +45,88 @@ android_security_CertTool_isPkcs12Keystore(JNIEnv* env, jobject thiz, jbyteArray data) { - char buf[REPLY_MAX]; int len = (*env)->GetArrayLength(env, data); - if (len > REPLY_MAX) return 0; - (*env)->GetByteArrayRegion(env, data, 0, len, (jbyte*)buf); - return (jboolean) is_pkcs12(buf, len); + if (len > 0) { + PKCS12 *handle = NULL; + char buf[len]; + + (*env)->GetByteArrayRegion(env, data, 0, len, (jbyte*)buf); + return (jboolean)is_pkcs12(buf, len); + } else { + return 0; + } +} + +jint +android_security_CertTool_getPkcs12Handle(JNIEnv* env, + jobject thiz, + jbyteArray data, + jstring jPassword) +{ + jboolean bIsCopy; + int len = (*env)->GetArrayLength(env, data); + const char* passwd = (*env)->GetStringUTFChars(env, jPassword , &bIsCopy); + + if (len > 0) { + PKCS12_KEYSTORE *handle = NULL; + char buf[len]; + + (*env)->GetByteArrayRegion(env, data, 0, len, (jbyte*)buf); + handle = get_pkcs12_keystore_handle(buf, len, passwd); + (*env)->ReleaseStringUTFChars(env, jPassword, passwd); + return (jint)handle; + } else { + return 0; + } +} + +jstring call_pkcs12_ks_func(PKCS12_KEYSTORE_FUNC *func, + JNIEnv* env, + jobject thiz, + jint phandle) +{ + char buf[REPLY_MAX]; + + if (phandle == 0) return NULL; + if (func((PKCS12_KEYSTORE*)phandle, buf, sizeof(buf)) == 0) { + return (*env)->NewStringUTF(env, buf); + } + return NULL; +} + +jstring +android_security_CertTool_getPkcs12Certificate(JNIEnv* env, + jobject thiz, + jint phandle) +{ + return call_pkcs12_ks_func((PKCS12_KEYSTORE_FUNC *)get_pkcs12_certificate, + env, thiz, phandle); +} + +jstring +android_security_CertTool_getPkcs12PrivateKey(JNIEnv* env, + jobject thiz, + jint phandle) +{ + return call_pkcs12_ks_func((PKCS12_KEYSTORE_FUNC *)get_pkcs12_private_key, + env, thiz, phandle); +} + +jstring +android_security_CertTool_popPkcs12CertificateStack(JNIEnv* env, + jobject thiz, + jint phandle) +{ + return call_pkcs12_ks_func((PKCS12_KEYSTORE_FUNC *)pop_pkcs12_certs_stack, + env, thiz, phandle); +} + +void android_security_CertTool_freePkcs12Handle(JNIEnv* env, + jobject thiz, + jint handle) +{ + if (handle != 0) free_pkcs12_keystore((PKCS12_KEYSTORE*)handle); } jint @@ -117,6 +196,16 @@ static JNINativeMethod gCertToolMethods[] = { (void*)android_security_CertTool_generateCertificateRequest}, {"isPkcs12Keystore", "([B)Z", (void*)android_security_CertTool_isPkcs12Keystore}, + {"getPkcs12Handle", "([BLjava/lang/String;)I", + (void*)android_security_CertTool_getPkcs12Handle}, + {"getPkcs12Certificate", "(I)Ljava/lang/String;", + (void*)android_security_CertTool_getPkcs12Certificate}, + {"getPkcs12PrivateKey", "(I)Ljava/lang/String;", + (void*)android_security_CertTool_getPkcs12PrivateKey}, + {"popPkcs12CertificateStack", "(I)Ljava/lang/String;", + (void*)android_security_CertTool_popPkcs12CertificateStack}, + {"freePkcs12Handle", "(I)V", + (void*)android_security_CertTool_freePkcs12Handle}, {"generateX509Certificate", "([B)I", (void*)android_security_CertTool_generateX509Certificate}, {"isCaCertificate", "(I)Z", diff --git a/packages/TtsService/jni/android_tts_SynthProxy.cpp b/packages/TtsService/jni/android_tts_SynthProxy.cpp index 64cdb5b80160..099c4d148f80 100644 --- a/packages/TtsService/jni/android_tts_SynthProxy.cpp +++ b/packages/TtsService/jni/android_tts_SynthProxy.cpp @@ -286,6 +286,7 @@ android_tts_SynthProxy_native_finalize(JNIEnv *env, jobject thiz, jint jniData) { if (jniData) { SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData; + env->DeleteGlobalRef(pSynthData->tts_ref); delete pSynthData; } } diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 4baf202869c1..5425709fa994 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -1891,7 +1891,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo break; case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: animAttr = enter - ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation + ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation; break; } @@ -7232,17 +7232,27 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo public static WindowManager.LayoutParams findAnimations( ArrayList<AppWindowToken> order, - ArrayList<AppWindowToken> tokenList1, - ArrayList<AppWindowToken> tokenList2) { + ArrayList<AppWindowToken> openingTokenList1, + ArrayList<AppWindowToken> closingTokenList2) { // We need to figure out which animation to use... + + // First, check if there is a compatible window in opening/closing + // apps, and use it if exists. WindowManager.LayoutParams animParams = null; int animSrc = 0; - + animParams = findCompatibleWindowParams(openingTokenList1); + if (animParams == null) { + animParams = findCompatibleWindowParams(closingTokenList2); + } + if (animParams != null) { + return animParams; + } + //Log.i(TAG, "Looking for animations..."); for (int i=order.size()-1; i>=0; i--) { AppWindowToken wtoken = order.get(i); //Log.i(TAG, "Token " + wtoken + " with " + wtoken.windows.size() + " windows"); - if (tokenList1.contains(wtoken) || tokenList2.contains(wtoken)) { + if (openingTokenList1.contains(wtoken) || closingTokenList2.contains(wtoken)) { int j = wtoken.windows.size(); while (j > 0) { j--; @@ -7270,6 +7280,21 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo return animParams; } + private static LayoutParams findCompatibleWindowParams(ArrayList<AppWindowToken> tokenList) { + for (int appCount = tokenList.size() - 1; appCount >= 0; appCount--) { + AppWindowToken wtoken = tokenList.get(appCount); + // Just checking one window is sufficient as all windows have the compatible flag + // if the application is in compatibility mode. + if (wtoken.windows.size() > 0) { + WindowManager.LayoutParams params = wtoken.windows.get(0).mAttrs; + if ((params.flags & FLAG_COMPATIBLE_WINDOW) != 0) { + return params; + } + } + } + return null; + } + // ------------------------------------------------------------- // DummyAnimation // ------------------------------------------------------------- @@ -9277,16 +9302,10 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo // width is the screen width {@see AppWindowToken#stepAnimatinoLocked} mWidth = width; } - - @Override - public boolean willChangeTransformationMatrix() { - return true; - } @Override - public boolean willChangeBounds() { - return true; + public int getZAdjustment() { + return Animation.ZORDER_TOP; } } } - diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java index 39bbf16b73b2..ba461973fbfb 100644 --- a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java +++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java @@ -73,6 +73,10 @@ public class LoadTestsAutoTest extends ActivityInstrumentationTestCase2<TestShel runTestAndWaitUntilDone(activity, runner.mTestPath, runner.mTimeoutInMillis); activity.clearCache(); + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + } dumpMemoryInfo(); // Kill activity |