Merge "Don't strip country and variant from locale." into mnc-dev
diff --git a/core/java/com/android/internal/util/AsyncChannel.java b/core/java/com/android/internal/util/AsyncChannel.java
index 34f62ba..bd0e6ce 100644
--- a/core/java/com/android/internal/util/AsyncChannel.java
+++ b/core/java/com/android/internal/util/AsyncChannel.java
@@ -462,10 +462,8 @@
         } catch(Exception e) {
         }
         // Tell source we're disconnected.
-        if (mSrcHandler != null) {
-            replyDisconnected(STATUS_SUCCESSFUL);
-            mSrcHandler = null;
-        }
+        replyDisconnected(STATUS_SUCCESSFUL);
+        mSrcHandler = null;
         // Unlink only when bindService isn't used
         if (mConnection == null && mDstMessenger != null && mDeathMonitor!= null) {
             mDstMessenger.getBinder().unlinkToDeath(mDeathMonitor, 0);
@@ -871,6 +869,8 @@
      * @param status to be stored in msg.arg1
      */
     private void replyDisconnected(int status) {
+        // Can't reply if already disconnected. Avoid NullPointerException.
+        if (mSrcHandler == null) return;
         Message msg = mSrcHandler.obtainMessage(CMD_CHANNEL_DISCONNECTED);
         msg.arg1 = status;
         msg.obj = this;
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 8ae2e3b..9babe82 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -188,18 +188,43 @@
     return mPixelRef->rowBytes();
 }
 
-SkPixelRef* Bitmap::pixelRef() const {
+SkPixelRef* Bitmap::peekAtPixelRef() const {
     assertValid();
     return mPixelRef.get();
 }
 
+SkPixelRef* Bitmap::refPixelRef() {
+    assertValid();
+    android::AutoMutex _lock(mLock);
+    return refPixelRefLocked();
+}
+
+SkPixelRef* Bitmap::refPixelRefLocked() {
+    mPixelRef->ref();
+    if (mPixelRef->unique()) {
+        // We just restored this from 0, pin the pixels and inc the strong count
+        // Note that there *might be* an incoming onStrongRefDestroyed from whatever
+        // last unref'd
+        pinPixelsLocked();
+        mPinnedRefCount++;
+    }
+    return mPixelRef.get();
+}
+
 void Bitmap::reconfigure(const SkImageInfo& info, size_t rowBytes,
         SkColorTable* ctable) {
+    {
+        android::AutoMutex _lock(mLock);
+        if (mPinnedRefCount) {
+            ALOGW("Called reconfigure on a bitmap that is in use! This may"
+                    " cause graphical corruption!");
+        }
+    }
     mPixelRef->reconfigure(info, rowBytes, ctable);
 }
 
 void Bitmap::reconfigure(const SkImageInfo& info) {
-    mPixelRef->reconfigure(info, mPixelRef->rowBytes(), mPixelRef->colorTable());
+    reconfigure(info, mPixelRef->rowBytes(), mPixelRef->colorTable());
 }
 
 void Bitmap::detachFromJava() {
@@ -287,18 +312,10 @@
 void Bitmap::getSkBitmap(SkBitmap* outBitmap) {
     assertValid();
     android::AutoMutex _lock(mLock);
-    mPixelRef->ref();
-    if (mPixelRef->unique()) {
-        // We just restored this from 0, pin the pixels and inc the strong count
-        // Note that there *might be* an incoming onStrongRefDestroyed from whatever
-        // last unref'd
-        pinPixelsLocked();
-        mPinnedRefCount++;
-    }
     // Safe because mPixelRef is a WrappedPixelRef type, otherwise rowBytes()
     // would require locking the pixels first.
     outBitmap->setInfo(mPixelRef->info(), mPixelRef->rowBytes());
-    outBitmap->setPixelRef(mPixelRef.get())->unref();
+    outBitmap->setPixelRef(refPixelRefLocked())->unref();
     outBitmap->setHasHardwareMipMap(hasHardwareMipMap());
 }
 
@@ -323,7 +340,7 @@
     }
 
     void* pixels() {
-        return mBitmap->pixelRef()->pixels();
+        return mBitmap->peekAtPixelRef()->pixels();
     }
 
     bool valid() {
@@ -780,7 +797,7 @@
 
 static jint Bitmap_getGenerationId(JNIEnv* env, jobject, jlong bitmapHandle) {
     LocalScopedBitmap bitmap(bitmapHandle);
-    return static_cast<jint>(bitmap->pixelRef()->getGenerationID());
+    return static_cast<jint>(bitmap->peekAtPixelRef()->getGenerationID());
 }
 
 static jboolean Bitmap_isPremultiplied(JNIEnv* env, jobject, jlong bitmapHandle) {
@@ -800,10 +817,10 @@
         jboolean hasAlpha, jboolean requestPremul) {
     LocalScopedBitmap bitmap(bitmapHandle);
     if (hasAlpha) {
-        bitmap->pixelRef()->changeAlphaType(
+        bitmap->peekAtPixelRef()->changeAlphaType(
                 requestPremul ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
     } else {
-        bitmap->pixelRef()->changeAlphaType(kOpaque_SkAlphaType);
+        bitmap->peekAtPixelRef()->changeAlphaType(kOpaque_SkAlphaType);
     }
 }
 
@@ -812,9 +829,9 @@
     LocalScopedBitmap bitmap(bitmapHandle);
     if (!bitmap->info().isOpaque()) {
         if (isPremul) {
-            bitmap->pixelRef()->changeAlphaType(kPremul_SkAlphaType);
+            bitmap->peekAtPixelRef()->changeAlphaType(kPremul_SkAlphaType);
         } else {
-            bitmap->pixelRef()->changeAlphaType(kUnpremul_SkAlphaType);
+            bitmap->peekAtPixelRef()->changeAlphaType(kUnpremul_SkAlphaType);
         }
     }
 }
@@ -1164,7 +1181,7 @@
 
 static jlong Bitmap_refPixelRef(JNIEnv* env, jobject, jlong bitmapHandle) {
     LocalScopedBitmap bitmap(bitmapHandle);
-    SkPixelRef* pixelRef = bitmap.valid() ? bitmap->pixelRef() : nullptr;
+    SkPixelRef* pixelRef = bitmap.valid() ? bitmap->peekAtPixelRef() : nullptr;
     SkSafeRef(pixelRef);
     return reinterpret_cast<jlong>(pixelRef);
 }
diff --git a/core/jni/android/graphics/Bitmap.h b/core/jni/android/graphics/Bitmap.h
index d6e5c61..efeb898 100644
--- a/core/jni/android/graphics/Bitmap.h
+++ b/core/jni/android/graphics/Bitmap.h
@@ -62,7 +62,8 @@
     int width() const { return info().width(); }
     int height() const { return info().height(); }
     size_t rowBytes() const;
-    SkPixelRef* pixelRef() const;
+    SkPixelRef* peekAtPixelRef() const;
+    SkPixelRef* refPixelRef();
     bool valid() const { return mPixelStorageType != PixelStorageType::Invalid; }
 
     void reconfigure(const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
@@ -88,6 +89,7 @@
     JNIEnv* jniEnv();
     bool shouldDisposeSelfLocked();
     void assertValid() const;
+    SkPixelRef* refPixelRefLocked();
 
     android::Mutex mLock;
     int mPinnedRefCount = 0;
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index cdd397d..3ca4e72 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -184,7 +184,7 @@
         }
 
         mBitmap->reconfigure(info, bitmap->rowBytes(), ctable);
-        bitmap->setPixelRef(mBitmap->pixelRef());
+        bitmap->setPixelRef(mBitmap->refPixelRef())->unref();
 
         // since we're already allocated, we lockPixels right away
         // HeapAllocator/JavaPixelAllocator behaves this way too
@@ -258,7 +258,7 @@
     unsigned int existingBufferSize = 0;
     if (javaBitmap != NULL) {
         reuseBitmap = GraphicsJNI::getBitmap(env, javaBitmap);
-        if (reuseBitmap->pixelRef()->isImmutable()) {
+        if (reuseBitmap->peekAtPixelRef()->isImmutable()) {
             ALOGW("Unable to reuse an immutable bitmap as an image decoder target.");
             javaBitmap = NULL;
             reuseBitmap = nullptr;
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 0deb8cc..1c6f7de 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -352,8 +352,8 @@
     getBitmap(env, bitmap)->getSkBitmap(outBitmap);
 }
 
-SkPixelRef* GraphicsJNI::getSkPixelRef(JNIEnv* env, jobject bitmap) {
-    return getBitmap(env, bitmap)->pixelRef();
+SkPixelRef* GraphicsJNI::refSkPixelRef(JNIEnv* env, jobject bitmap) {
+    return getBitmap(env, bitmap)->refPixelRef();
 }
 
 SkColorType GraphicsJNI::getNativeBitmapColorType(JNIEnv* env, jobject jconfig) {
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index e748bac..ef9c2a9 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -52,7 +52,7 @@
     static android::Canvas* getNativeCanvas(JNIEnv*, jobject canvas);
     static android::Bitmap* getBitmap(JNIEnv*, jobject bitmap);
     static void getSkBitmap(JNIEnv*, jobject bitmap, SkBitmap* outBitmap);
-    static SkPixelRef* getSkPixelRef(JNIEnv*, jobject bitmap);
+    static SkPixelRef* refSkPixelRef(JNIEnv*, jobject bitmap);
     static SkRegion* getNativeRegion(JNIEnv*, jobject region);
 
     // Given the 'native' long held by the Rasterizer.java object, return a
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 1965cd3..77af341 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -180,7 +180,7 @@
             (void*) screenshot->getPixels(), (void*) screenshot.get(), DeleteScreenshot,
             screenshotInfo, rowBytes, nullptr);
     screenshot.detach();
-    bitmap->pixelRef()->setImmutable();
+    bitmap->peekAtPixelRef()->setImmutable();
 
     return GraphicsJNI::createBitmap(env, bitmap,
             GraphicsJNI::kBitmapCreateFlag_Premultiplied, NULL);
diff --git a/native/graphics/jni/bitmap.cpp b/native/graphics/jni/bitmap.cpp
index 0521833..6d2de98 100644
--- a/native/graphics/jni/bitmap.cpp
+++ b/native/graphics/jni/bitmap.cpp
@@ -62,7 +62,7 @@
         return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
     }
 
-    SkPixelRef* pixelRef = GraphicsJNI::getSkPixelRef(env, jbitmap);
+    SkPixelRef* pixelRef = GraphicsJNI::refSkPixelRef(env, jbitmap);
     if (!pixelRef) {
         return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
     }
@@ -71,9 +71,9 @@
     void* addr = pixelRef->pixels();
     if (NULL == addr) {
         pixelRef->unlockPixels();
+        pixelRef->unref();
         return ANDROID_BITMAP_RESULT_ALLOCATION_FAILED;
     }
-    pixelRef->ref();
 
     if (addrPtr) {
         *addrPtr = addr;
@@ -86,7 +86,7 @@
         return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
     }
 
-    SkPixelRef* pixelRef = GraphicsJNI::getSkPixelRef(env, jbitmap);
+    SkPixelRef* pixelRef = GraphicsJNI::refSkPixelRef(env, jbitmap);
     if (!pixelRef) {
         return ANDROID_BITMAP_RESULT_JNI_EXCEPTION;
     }
@@ -98,6 +98,12 @@
     pixelRef->notifyPixelsChanged();
 
     pixelRef->unlockPixels();
+    // Awkward in that we need to double-unref as the call to get the SkPixelRef
+    // did a ref(), so we need to unref() for the local ref and for the previous
+    // AndroidBitmap_lockPixels(). However this keeps GraphicsJNI a bit safer
+    // if others start using it without knowing about android::Bitmap's "fun"
+    // ref counting mechanism(s).
+    pixelRef->unref();
     pixelRef->unref();
 
     return ANDROID_BITMAP_RESULT_SUCCESS;