Merge "MediaBrowser: Handle onServiceConnected/Disconnected in the given thread"
diff --git a/api/current.txt b/api/current.txt
index ef7d64c..eb888af 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -36477,6 +36477,7 @@
     method public boolean performHapticFeedback(int);
     method public boolean performHapticFeedback(int, int);
     method public boolean performLongClick();
+    method public boolean performLongClick(float, float);
     method public void playSoundEffect(int);
     method public boolean post(java.lang.Runnable);
     method public boolean postDelayed(java.lang.Runnable, long);
diff --git a/api/system-current.txt b/api/system-current.txt
index 892e3c9..d288ad1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -38774,6 +38774,7 @@
     method public boolean performHapticFeedback(int);
     method public boolean performHapticFeedback(int, int);
     method public boolean performLongClick();
+    method public boolean performLongClick(float, float);
     method public void playSoundEffect(int);
     method public boolean post(java.lang.Runnable);
     method public boolean postDelayed(java.lang.Runnable, long);
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index ff4ebee..874026f 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -1059,6 +1059,41 @@
     }
 
     /**
+     * Sets whether audio routing is allowed.
+     *
+     * Note: This is an internal function and shouldn't be exposed
+     */
+    public void setAudioRouteAllowed(boolean allowed) {
+        if (VDBG) log("setAudioRouteAllowed");
+        if (mService != null && isEnabled()) {
+            try {
+                mService.setAudioRouteAllowed(allowed);
+            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+        }
+    }
+
+    /**
+     * Returns whether audio routing is allowed.
+     *
+     * Note: This is an internal function and shouldn't be exposed
+     */
+    public boolean getAudioRouteAllowed() {
+        if (VDBG) log("getAudioRouteAllowed");
+        if (mService != null && isEnabled()) {
+            try {
+                return mService.getAudioRouteAllowed();
+            } catch (RemoteException e) {Log.e(TAG, e.toString());}
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+        }
+        return false;
+    }
+
+    /**
      * Initiates a connection of audio channel.
      *
      * It setup SCO channel with remote connected Handsfree AG device.
diff --git a/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl b/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl
index e518b7d..79ae4e4 100644
--- a/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl
+++ b/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl
@@ -62,6 +62,8 @@
     int getAudioState(in BluetoothDevice device);
     boolean connectAudio();
     boolean disconnectAudio();
+    void setAudioRouteAllowed(boolean allowed);
+    boolean getAudioRouteAllowed();
 
     Bundle getCurrentAgFeatures(in BluetoothDevice device);
 }
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 1fcfaca..51796eb 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -513,7 +513,7 @@
      * {@link CameraManager#registerAvailabilityCallback} to be notified of such availability
      * changes.</p>
      *
-     * @see registerAvailabilityCallback
+     * @see #registerAvailabilityCallback
      */
     public static abstract class AvailabilityCallback {
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index fed1bd1..8b804e8 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5372,21 +5372,53 @@
     }
 
     /**
-     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
-     * OnLongClickListener did not consume the event.
+     * Calls this view's OnLongClickListener, if it is defined. Invokes the
+     * context menu if the OnLongClickListener did not consume the event.
      *
-     * @return True if one of the above receivers consumed the event, false otherwise.
+     * @return {@code true} if one of the above receivers consumed the event,
+     *         {@code false} otherwise
      */
     public boolean performLongClick() {
+        return performLongClickInternal(false, 0, 0);
+    }
+
+    /**
+     * Calls this view's OnLongClickListener, if it is defined. Invokes the
+     * context menu if the OnLongClickListener did not consume the event,
+     * anchoring it to an (x,y) coordinate.
+     *
+     * @param x x coordinate of the anchoring touch event
+     * @param y y coordinate of the anchoring touch event
+     * @return {@code true} if one of the above receivers consumed the event,
+     *         {@code false} otherwise
+     */
+    public boolean performLongClick(float x, float y) {
+        return performLongClickInternal(true, x, y);
+    }
+
+    /**
+     * Calls this view's OnLongClickListener, if it is defined. Invokes the
+     * context menu if the OnLongClickListener did not consume the event,
+     * optionally anchoring it to an (x,y) coordinate.
+     *
+     * @param isAnchored whether this long click is anchored to a touch event
+     * @param x x coordinate of the anchoring touch event, ignored if
+     *          {@code isAnchored} is set to {@code false}
+     * @param y y coordinate of the anchoring touch event, ignored if
+     *          {@code isAnchored} is set to {@code false}
+     * @return {@code true} if one of the above receivers consumed the event,
+     *         {@code false} otherwise
+     */
+    private boolean performLongClickInternal(boolean isAnchored, float x, float y) {
         sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
 
         boolean handled = false;
-        ListenerInfo li = mListenerInfo;
+        final ListenerInfo li = mListenerInfo;
         if (li != null && li.mOnLongClickListener != null) {
             handled = li.mOnLongClickListener.onLongClick(View.this);
         }
         if (!handled) {
-            handled = showContextMenu();
+            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
         }
         if (handled) {
             performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
@@ -10033,32 +10065,36 @@
      * KeyEvent.Callback.onKeyDown()}: perform press of the view
      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
      * is released, if the view is enabled and clickable.
+     * <p>
+     * Key presses in software keyboards will generally NOT trigger this
+     * listener, although some may elect to do so in some situations. Do not
+     * rely on this to catch software key presses.
      *
-     * <p>Key presses in software keyboards will generally NOT trigger this listener,
-     * although some may elect to do so in some situations. Do not rely on this to
-     * catch software key presses.
-     *
-     * @param keyCode A key code that represents the button pressed, from
-     *                {@link android.view.KeyEvent}.
-     * @param event   The KeyEvent object that defines the button action.
+     * @param keyCode a key code that represents the button pressed, from
+     *                {@link android.view.KeyEvent}
+     * @param event the KeyEvent object that defines the button action
      */
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        boolean result = false;
-
         if (KeyEvent.isConfirmKey(keyCode)) {
             if ((mViewFlags & ENABLED_MASK) == DISABLED) {
                 return true;
             }
-            // Long clickable items don't necessarily have to be clickable
-            if (((mViewFlags & CLICKABLE) == CLICKABLE ||
-                    (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
-                    (event.getRepeatCount() == 0)) {
-                setPressed(true);
-                checkForLongClick(0);
+
+            // Long clickable items don't necessarily have to be clickable.
+            if (((mViewFlags & CLICKABLE) == CLICKABLE
+                    || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
+                    && (event.getRepeatCount() == 0)) {
+                // For the purposes of menu anchoring and drawable hotspots,
+                // key events are considered to be at the center of the view.
+                final float x = getWidth() / 2f;
+                final float y = getHeight() / 2f;
+                setPressed(true, x, y);
+                checkForLongClick(0, x, y);
                 return true;
             }
         }
-        return result;
+
+        return false;
     }
 
     /**
@@ -10586,7 +10622,7 @@
                     } else {
                         // Not inside a scrolling container, so show the feedback right away
                         setPressed(true, x, y);
-                        checkForLongClick(0);
+                        checkForLongClick(0, x, y);
                     }
                     break;
 
@@ -20027,13 +20063,14 @@
         }
     }
 
-    private void checkForLongClick(int delayOffset) {
+    private void checkForLongClick(int delayOffset, float x, float y) {
         if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
             mHasPerformedLongPress = false;
 
             if (mPendingCheckForLongPress == null) {
                 mPendingCheckForLongPress = new CheckForLongPress();
             }
+            mPendingCheckForLongPress.setAnchor(x, y);
             mPendingCheckForLongPress.rememberWindowAttachCount();
             postDelayed(mPendingCheckForLongPress,
                     ViewConfiguration.getLongPressTimeout() - delayOffset);
@@ -21422,17 +21459,24 @@
 
     private final class CheckForLongPress implements Runnable {
         private int mOriginalWindowAttachCount;
+        private float mX;
+        private float mY;
 
         @Override
         public void run() {
             if (isPressed() && (mParent != null)
                     && mOriginalWindowAttachCount == mWindowAttachCount) {
-                if (performLongClick()) {
+                if (performLongClick(mX, mY)) {
                     mHasPerformedLongPress = true;
                 }
             }
         }
 
+        public void setAnchor(float x, float y) {
+            mX = x;
+            mY = y;
+        }
+
         public void rememberWindowAttachCount() {
             mOriginalWindowAttachCount = mWindowAttachCount;
         }
@@ -21446,7 +21490,7 @@
         public void run() {
             mPrivateFlags &= ~PFLAG_PREPRESSED;
             setPressed(true, x, y);
-            checkForLongClick(ViewConfiguration.getTapTimeout());
+            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
         }
     }
 
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 1b17736..1735e1b 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -3083,8 +3083,32 @@
                 return "ACTION_PASTE";
             case ACTION_SET_SELECTION:
                 return "ACTION_SET_SELECTION";
+            case ACTION_EXPAND:
+                return "ACTION_EXPAND";
+            case ACTION_COLLAPSE:
+                return "ACTION_COLLAPSE";
+            case ACTION_DISMISS:
+                return "ACTION_DISMISS";
+            case ACTION_SET_TEXT:
+                return "ACTION_SET_TEXT";
+            case R.id.accessibilityActionShowOnScreen:
+                return "ACTION_SHOW_ON_SCREEN";
+            case R.id.accessibilityActionScrollToPosition:
+                return "ACTION_SCROLL_TO_POSITION";
+            case R.id.accessibilityActionScrollUp:
+                return "ACTION_SCROLL_UP";
+            case R.id.accessibilityActionScrollLeft:
+                return "ACTION_SCROLL_LEFT";
+            case R.id.accessibilityActionScrollDown:
+                return "ACTION_SCROLL_DOWN";
+            case R.id.accessibilityActionScrollRight:
+                return "ACTION_SCROLL_RIGHT";
+            case R.id.accessibilityActionSetProgress:
+                return "ACTION_SET_PROGRESS";
+            case R.id.accessibilityActionContextClick:
+                return "ACTION_CONTEXT_CLICK";
             default:
-                return"ACTION_UNKNOWN";
+                return "ACTION_UNKNOWN";
         }
     }
 
diff --git a/core/java/com/android/internal/alsa/AlsaCardsParser.java b/core/java/com/android/internal/alsa/AlsaCardsParser.java
index 67ee085..17e8c9c 100644
--- a/core/java/com/android/internal/alsa/AlsaCardsParser.java
+++ b/core/java/com/android/internal/alsa/AlsaCardsParser.java
@@ -94,6 +94,12 @@
         public String textFormat() {
           return mCardName + " : " + mCardDescription;
         }
+
+        public void log(int listIndex) {
+            Slog.d(TAG, "" + listIndex +
+                " [" + mCardNum + " " + mCardName + " : " + mCardDescription +
+                " usb:" + mIsUsb);
+        }
     }
 
     public AlsaCardsParser() {}
@@ -169,9 +175,41 @@
 
     // return -1 if none found
     public int getDefaultUsbCard() {
+        // save the current list of devices
+        ArrayList<AlsaCardsParser.AlsaCardRecord> prevRecs = mCardRecords;
+        if (DEBUG) {
+            LogDevices("Previous Devices:", prevRecs);
+        }
+
+        // get the new list of devices
+        scan();
+        if (DEBUG) {
+            LogDevices("Current Devices:", mCardRecords);
+        }
+
+        // Calculate the difference between the old and new device list
+        ArrayList<AlsaCardRecord> newRecs = getNewCardRecords(prevRecs);
+        if (DEBUG) {
+            LogDevices("New Devices:", newRecs);
+        }
+
         // Choose the most-recently added EXTERNAL card
+        // Check recently added devices
+        for (AlsaCardRecord rec : newRecs) {
+            if (DEBUG) {
+                Slog.d(TAG, rec.mCardName + " card:" + rec.mCardNum + " usb:" + rec.mIsUsb);
+            }
+            if (rec.mIsUsb) {
+                // Found it
+                return rec.mCardNum;
+            }
+        }
+
         // or return the first added EXTERNAL card?
-        for (AlsaCardRecord rec : mCardRecords) {
+        for (AlsaCardRecord rec : prevRecs) {
+            if (DEBUG) {
+                Slog.d(TAG, rec.mCardName + " card:" + rec.mCardNum + " usb:" + rec.mIsUsb);
+            }
             if (rec.mIsUsb) {
                 return rec.mCardNum;
             }
@@ -183,11 +221,17 @@
     public int getDefaultCard() {
         // return an external card if possible
         int card = getDefaultUsbCard();
+        if (DEBUG) {
+            Slog.d(TAG, "getDefaultCard() default usb card:" + card);
+        }
 
         if (card < 0 && getNumCardRecords() > 0) {
             // otherwise return the (internal) card with the highest number
             card = getCardRecordAt(getNumCardRecords() - 1).mCardNum;
         }
+        if (DEBUG) {
+            Slog.d(TAG, "  returns card:" + card);
+        }
         return card;
     }
 
@@ -222,4 +266,13 @@
             }
         }
     }
+
+    static public void LogDevices(String caption, ArrayList<AlsaCardRecord> deviceList) {
+        Slog.d(TAG, caption + " ----------------");
+        int listIndex = 0;
+        for (AlsaCardRecord device : deviceList) {
+            device.log(listIndex++);
+        }
+        Slog.d(TAG, "----------------");
+    }
 }
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 20d00b0..7b69c9e 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -189,6 +189,7 @@
     external/pdfium/core/include/fpdfdoc \
     external/pdfium/fpdfsdk/include \
     external/pdfium/public \
+    external/skia/include/private \
     external/skia/src/core \
     external/skia/src/effects \
     external/skia/src/images \
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 28bc7fe..ecaf951 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -165,7 +165,7 @@
 
     virtual bool allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
         const SkImageInfo& info = bitmap->info();
-        if (info.fColorType == kUnknown_SkColorType) {
+        if (info.colorType() == kUnknown_SkColorType) {
             ALOGW("unable to reuse a bitmap as the target has an unknown bitmap configuration");
             return false;
         }
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 93259e7..068517a 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -486,7 +486,7 @@
 android::Bitmap* GraphicsJNI::allocateJavaPixelRef(JNIEnv* env, SkBitmap* bitmap,
                                              SkColorTable* ctable) {
     const SkImageInfo& info = bitmap->info();
-    if (info.fColorType == kUnknown_SkColorType) {
+    if (info.colorType() == kUnknown_SkColorType) {
         doThrowIAE(env, "unknown bitmap configuration");
         return NULL;
     }
@@ -538,7 +538,7 @@
 
 bool GraphicsJNI::allocatePixels(JNIEnv* env, SkBitmap* bitmap, SkColorTable* ctable) {
     const SkImageInfo& info = bitmap->info();
-    if (info.fColorType == kUnknown_SkColorType) {
+    if (info.colorType() == kUnknown_SkColorType) {
         doThrowIAE(env, "unknown bitmap configuration");
         return NULL;
     }
@@ -581,7 +581,7 @@
     int fd;
 
     const SkImageInfo& info = bitmap->info();
-    if (info.fColorType == kUnknown_SkColorType) {
+    if (info.colorType() == kUnknown_SkColorType) {
         doThrowIAE(env, "unknown bitmap configuration");
         return nullptr;
     }
@@ -625,7 +625,7 @@
 android::Bitmap* GraphicsJNI::mapAshmemPixelRef(JNIEnv* env, SkBitmap* bitmap,
         SkColorTable* ctable, int fd, void* addr, bool readOnly) {
     const SkImageInfo& info = bitmap->info();
-    if (info.fColorType == kUnknown_SkColorType) {
+    if (info.colorType() == kUnknown_SkColorType) {
         doThrowIAE(env, "unknown bitmap configuration");
         return nullptr;
     }
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 24055e7..da96b93 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -313,12 +313,11 @@
         return 0;
     }
 
+
     SkImageInfo info = SkImageInfo::Make(outBuffer.width, outBuffer.height,
                                          convertPixelFormat(outBuffer.format),
-                                         kPremul_SkAlphaType);
-    if (outBuffer.format == PIXEL_FORMAT_RGBX_8888) {
-        info.fAlphaType = kOpaque_SkAlphaType;
-    }
+                                         outBuffer.format == PIXEL_FORMAT_RGBX_8888 ?
+                                         kOpaque_SkAlphaType : kPremul_SkAlphaType);
 
     SkBitmap bitmap;
     ssize_t bpr = outBuffer.stride * bytesPerPixel(outBuffer.format);
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 65ebb663..931ad54 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -138,35 +138,36 @@
         return NULL;
     }
 
-    SkImageInfo screenshotInfo;
-    screenshotInfo.fWidth = screenshot->getWidth();
-    screenshotInfo.fHeight = screenshot->getHeight();
-
+    SkColorType colorType;
+    SkAlphaType alphaType;
     switch (screenshot->getFormat()) {
         case PIXEL_FORMAT_RGBX_8888: {
-            screenshotInfo.fColorType = kRGBA_8888_SkColorType;
-            screenshotInfo.fAlphaType = kOpaque_SkAlphaType;
+            colorType = kRGBA_8888_SkColorType;
+            alphaType = kOpaque_SkAlphaType;
             break;
         }
         case PIXEL_FORMAT_RGBA_8888: {
-            screenshotInfo.fColorType = kRGBA_8888_SkColorType;
-            screenshotInfo.fAlphaType = kPremul_SkAlphaType;
+            colorType = kRGBA_8888_SkColorType;
+            alphaType = kPremul_SkAlphaType;
             break;
         }
         case PIXEL_FORMAT_RGB_565: {
-            screenshotInfo.fColorType = kRGB_565_SkColorType;
-            screenshotInfo.fAlphaType = kOpaque_SkAlphaType;
+            colorType = kRGB_565_SkColorType;
+            alphaType = kOpaque_SkAlphaType;
             break;
         }
         default: {
             return NULL;
         }
     }
+    SkImageInfo screenshotInfo = SkImageInfo::Make(screenshot->getWidth(),
+                                                   screenshot->getHeight(),
+                                                   colorType, alphaType);
 
     const size_t rowBytes =
             screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat());
 
-    if (!screenshotInfo.fWidth || !screenshotInfo.fHeight) {
+    if (!screenshotInfo.width() || !screenshotInfo.height()) {
         return NULL;
     }
 
diff --git a/core/jni/android_view_TextureView.cpp b/core/jni/android_view_TextureView.cpp
index b736a17..e185281 100644
--- a/core/jni/android_view_TextureView.cpp
+++ b/core/jni/android_view_TextureView.cpp
@@ -72,29 +72,25 @@
 
 // FIXME: consider exporting this to share (e.g. android_view_Surface.cpp)
 static inline SkImageInfo convertPixelFormat(const ANativeWindow_Buffer& buffer) {
-    SkImageInfo info;
-    info.fWidth = buffer.width;
-    info.fHeight = buffer.height;
+    SkColorType colorType = kUnknown_SkColorType;
+    SkAlphaType alphaType = kOpaque_SkAlphaType;
     switch (buffer.format) {
         case WINDOW_FORMAT_RGBA_8888:
-            info.fColorType = kN32_SkColorType;
-            info.fAlphaType = kPremul_SkAlphaType;
+            colorType = kN32_SkColorType;
+            alphaType = kPremul_SkAlphaType;
             break;
         case WINDOW_FORMAT_RGBX_8888:
-            info.fColorType = kN32_SkColorType;
-            info.fAlphaType = kOpaque_SkAlphaType;
+            colorType = kN32_SkColorType;
+            alphaType = kOpaque_SkAlphaType;
             break;
         case WINDOW_FORMAT_RGB_565:
-            info.fColorType = kRGB_565_SkColorType;
-            info.fAlphaType = kOpaque_SkAlphaType;
+            colorType = kRGB_565_SkColorType;
+            alphaType = kOpaque_SkAlphaType;
             break;
         default:
-            info.fColorType = kUnknown_SkColorType;
-            // switch to kUnknown_SkAlphaType when its in skia
-            info.fAlphaType = kOpaque_SkAlphaType;
             break;
     }
-    return info;
+    return SkImageInfo::Make(buffer.width, buffer.height, colorType, alphaType);
 }
 
 /**
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 39eda58..5828829 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1476,7 +1476,7 @@
     <permission android:name="android.permission.SYSTEM_ALERT_WINDOW"
         android:label="@string/permlab_systemAlertWindow"
         android:description="@string/permdesc_systemAlertWindow"
-        android:protectionLevel="signature|preinstalled|appop|pre23" />
+        android:protectionLevel="signature|preinstalled|appop|pre23|development" />
 
     <!-- ================================== -->
     <!-- Permissions affecting the system wallpaper -->
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 4385e70..f14e444 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -113,6 +113,7 @@
 endef
 
 hwui_c_includes += \
+    external/skia/include/private \
     external/skia/src/core
 
 hwui_shared_libraries := \
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
index bad3972..f5e5735 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -584,7 +584,7 @@
     // it to the bitmap pile
     SkBitmap bitmap;
     SkShader::TileMode xy[2];
-    if (shader->asABitmap(&bitmap, nullptr, xy) == SkShader::kDefault_BitmapType) {
+    if (shader->isABitmap(&bitmap, nullptr, xy)) {
         refBitmap(bitmap);
         return;
     }
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 1f113bc..273af3a 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -458,7 +458,7 @@
     // it to the bitmap pile
     SkBitmap bitmap;
     SkShader::TileMode xy[2];
-    if (shader->asABitmap(&bitmap, nullptr, xy) == SkShader::kDefault_BitmapType) {
+    if (shader->isABitmap(&bitmap, nullptr, xy)) {
         refBitmap(bitmap);
         return;
     }
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 9c32b1a..454ee24 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -27,6 +27,8 @@
 #include "Snapshot.h"
 
 #include "SkDrawFilter.h"
+#include "SkPaint.h"
+#include "SkTLazy.h"
 #include <vector>
 
 namespace android {
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 36633b5..a8f8134 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -194,15 +194,13 @@
 
 void SkiaCanvas::setBitmap(const SkBitmap& bitmap) {
     SkCanvas* newCanvas = new SkCanvas(bitmap);
-    SkASSERT(newCanvas);
 
     if (!bitmap.isNull()) {
         // Copy the canvas matrix & clip state.
         newCanvas->setMatrix(mCanvas->getTotalMatrix());
-        if (NULL != mCanvas->getDevice() && NULL != newCanvas->getDevice()) {
-            ClipCopier copier(newCanvas);
-            mCanvas->replayClips(&copier);
-        }
+
+        ClipCopier copier(newCanvas);
+        mCanvas->replayClips(&copier);
     }
 
     // unrefs the existing canvas
@@ -217,15 +215,15 @@
 // ----------------------------------------------------------------------------
 
 bool SkiaCanvas::isOpaque() {
-    return mCanvas->getDevice()->accessBitmap(false).isOpaque();
+    return mCanvas->imageInfo().isOpaque();
 }
 
 int SkiaCanvas::width() {
-    return mCanvas->getBaseLayerSize().width();
+    return mCanvas->imageInfo().width();
 }
 
 int SkiaCanvas::height() {
-    return mCanvas->getBaseLayerSize().height();
+    return mCanvas->imageInfo().height();
 }
 
 // ----------------------------------------------------------------------------
@@ -581,7 +579,7 @@
                             float dstRight, float dstBottom, const SkPaint* paint) {
     SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
     SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
-    mCanvas->drawBitmapRectToRect(bitmap, &srcRect, dstRect, paint);
+    mCanvas->drawBitmapRect(bitmap, srcRect, dstRect, paint);
 }
 
 void SkiaCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index c3f5eb2..2d5f70f 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -125,7 +125,7 @@
 }
 
 void SkiaCanvasProxy::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* srcPtr,
-        const SkRect& dst, const SkPaint* paint, DrawBitmapRectFlags) {
+        const SkRect& dst, const SkPaint* paint, SrcRectConstraint) {
     SkRect src = (srcPtr) ? *srcPtr : SkRect::MakeWH(bitmap.width(), bitmap.height());
     // TODO: if bitmap is a subset, do we need to add pixelRefOrigin to src?
     mCanvas->drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
diff --git a/libs/hwui/SkiaCanvasProxy.h b/libs/hwui/SkiaCanvasProxy.h
index 0de9650..2fe4327 100644
--- a/libs/hwui/SkiaCanvasProxy.h
+++ b/libs/hwui/SkiaCanvasProxy.h
@@ -63,7 +63,7 @@
     virtual void onDrawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
                               const SkPaint*) override;
     virtual void onDrawBitmapRect(const SkBitmap&, const SkRect* src, const SkRect& dst,
-                                  const SkPaint* paint, DrawBitmapRectFlags flags) override;
+                                  const SkPaint* paint, SrcRectConstraint) override;
     virtual void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
                                   const SkRect& dst, const SkPaint*) override;
     virtual void onDrawSprite(const SkBitmap&, int left, int top,
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 6c105cf..83652c6 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -204,7 +204,7 @@
         SkiaShaderData::BitmapShaderData* outData) {
     SkBitmap bitmap;
     SkShader::TileMode xy[2];
-    if (shader.asABitmap(&bitmap, nullptr, xy) != SkShader::kDefault_BitmapType) {
+    if (!shader.isABitmap(&bitmap, nullptr, xy)) {
         return false;
     }
 
@@ -272,7 +272,7 @@
     }
 
     // The shader is not a gradient. Check for a bitmap shader.
-    if (shader.asABitmap(nullptr, nullptr, nullptr) == SkShader::kDefault_BitmapType) {
+    if (shader.isABitmap()) {
         return kBitmap_SkiaShaderType;
     }
     return kNone_SkiaShaderType;
diff --git a/libs/hwui/utils/NinePatchImpl.cpp b/libs/hwui/utils/NinePatchImpl.cpp
index f51f5df..985f3fb 100644
--- a/libs/hwui/utils/NinePatchImpl.cpp
+++ b/libs/hwui/utils/NinePatchImpl.cpp
@@ -82,7 +82,7 @@
         }
     } else {
     SLOW_CASE:
-        canvas->drawBitmapRect(bitmap, &src, dst, &paint);
+        canvas->drawBitmapRect(bitmap, SkRect::Make(src), dst, &paint);
     }
 }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e149616..be9f44d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1759,8 +1759,9 @@
         synchronized (mPackages) {
             for (String permission : pkg.requestedPermissions) {
                 BasePermission bp = mSettings.mPermissions.get(permission);
-                if (bp != null && bp.isRuntime() && (grantedPermissions == null
-                        || ArrayUtils.contains(grantedPermissions, permission))) {
+                if (bp != null && (bp.isRuntime() || bp.isDevelopment())
+                        && (grantedPermissions == null
+                               || ArrayUtils.contains(grantedPermissions, permission))) {
                     final int flags = permissionsState.getPermissionFlags(permission, userId);
                     // Installer cannot change immutable permissions.
                     if ((flags & immutableFlags) == 0) {
@@ -3567,7 +3568,8 @@
                             killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED);
                         }
                     });
-                } break;
+                }
+                break;
             }
 
             mOnPermissionChangeListeners.onPermissionsChanged(uid);
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 2d87123..04cba81 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -18,6 +18,8 @@
 
 import static android.app.ActivityManager.DOCKED_STACK_ID;
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.view.PointerIcon.STYLE_HORIZONTAL_DOUBLE_ARROW;
+import static android.view.PointerIcon.STYLE_VERTICAL_DOUBLE_ARROW;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
@@ -87,6 +89,8 @@
         final boolean landscape = configuration.orientation == ORIENTATION_LANDSCAPE;
         final int width = landscape ? mDividerWidth : MATCH_PARENT;
         final int height = landscape ? MATCH_PARENT : mDividerWidth;
+        view.setPointerShape(
+                landscape ? STYLE_HORIZONTAL_DOUBLE_ARROW : STYLE_VERTICAL_DOUBLE_ARROW);
         WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                 width, height, TYPE_DOCK_DIVIDER,
                 FLAG_TOUCHABLE_WHEN_WAKING | FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL
diff --git a/services/net/java/android/net/dhcp/DhcpClient.java b/services/net/java/android/net/dhcp/DhcpClient.java
index 28cb114..c9efc69 100644
--- a/services/net/java/android/net/dhcp/DhcpClient.java
+++ b/services/net/java/android/net/dhcp/DhcpClient.java
@@ -417,9 +417,10 @@
                 encap, mTransactionId, getSecs(), clientAddress,
                 DO_UNICAST, mHwAddr, requestedAddress,
                 serverAddress, REQUESTED_PARAMS, null);
+        String serverStr = (serverAddress != null) ? serverAddress.getHostAddress() : null;
         String description = "DHCPREQUEST ciaddr=" + clientAddress.getHostAddress() +
                              " request=" + requestedAddress.getHostAddress() +
-                             " to=" + serverAddress.getHostAddress();
+                             " serverid=" + serverStr;
         return transmitPacket(packet, description, to);
     }
 
@@ -822,7 +823,8 @@
         public void enter() {
             super.enter();
             if (!setIpAddress(mDhcpLease.ipAddress) ||
-                    !connectUdpSock((mDhcpLease.serverAddress))) {
+                    (mDhcpLease.serverAddress != null &&
+                            !connectUdpSock((mDhcpLease.serverAddress)))) {
                 notifyFailure();
                 // There's likely no point in going into DhcpInitState here, we'll probably just
                 // repeat the transaction, get the same IP address as before, and fail.
@@ -878,11 +880,15 @@
         }
 
         protected boolean sendPacket() {
+            // Not specifying a SERVER_IDENTIFIER option is a violation of RFC 2131, but...
+            // http://b/25343517 . Try to make things work anyway by using broadcast renews.
+            Inet4Address to = (mDhcpLease.serverAddress != null) ?
+                    mDhcpLease.serverAddress : INADDR_BROADCAST;
             return sendRequestPacket(
                     (Inet4Address) mDhcpLease.ipAddress.getAddress(),  // ciaddr
                     INADDR_ANY,                                        // DHCP_REQUESTED_IP
-                    INADDR_ANY,                                        // DHCP_SERVER_IDENTIFIER
-                    (Inet4Address) mDhcpLease.serverAddress);          // packet destination address
+                    null,                                              // DHCP_SERVER_IDENTIFIER
+                    to);                                               // packet destination address
         }
 
         protected void receivePacket(DhcpPacket packet) {
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 701272e..129e537 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -212,6 +212,10 @@
     }
 
     private AlsaDevice waitForAlsaDevice(int card, int device, int type) {
+        if (DEBUG) {
+            Slog.e(TAG, "waitForAlsaDevice(c:" + card + " d:" + device + ")");
+        }
+
         AlsaDevice testDevice = new AlsaDevice(type, card, device);
 
         // This value was empirically determined.
@@ -292,7 +296,8 @@
      */
     /* package */ UsbAudioDevice selectAudioCard(int card) {
         if (DEBUG) {
-            Slog.d(TAG, "selectAudioCard() card:" + card);
+            Slog.d(TAG, "selectAudioCard() card:" + card
+                    + " isCardUsb(): " + mCardsParser.isCardUsb(card));
         }
         if (!mCardsParser.isCardUsb(card)) {
             // Don't. AudioPolicyManager has logic for falling back to internal devices.
@@ -304,6 +309,10 @@
 
         boolean hasPlayback = mDevicesParser.hasPlaybackDevices(card);
         boolean hasCapture = mDevicesParser.hasCaptureDevices(card);
+        if (DEBUG) {
+            Slog.d(TAG, "usb: hasPlayback:" + hasPlayback + " hasCapture:" + hasCapture);
+        }
+
         int deviceClass =
             (mCardsParser.isCardUsb(card)
                 ? UsbAudioDevice.kAudioDeviceClass_External
@@ -320,10 +329,6 @@
             return null;
         }
 
-        if (DEBUG) {
-            Slog.d(TAG, "usb: hasPlayback:" + hasPlayback + " hasCapture:" + hasCapture);
-        }
-
         UsbAudioDevice audioDevice =
                 new UsbAudioDevice(card, device, hasPlayback, hasCapture, deviceClass);
         AlsaCardsParser.AlsaCardRecord cardRecord = mCardsParser.getCardRecordFor(card);
@@ -339,14 +344,13 @@
         if (DEBUG) {
             Slog.d(TAG, "UsbAudioManager.selectDefaultDevice()");
         }
-        mCardsParser.scan();
         return selectAudioCard(mCardsParser.getDefaultCard());
     }
 
     /* package */ void usbDeviceAdded(UsbDevice usbDevice) {
        if (DEBUG) {
           Slog.d(TAG, "deviceAdded(): " + usbDevice.getManufacturerName() +
-                  "nm:" + usbDevice.getProductName());
+                  " nm:" + usbDevice.getProductName());
         }
 
         // Is there an audio interface in there?
@@ -361,27 +365,22 @@
                 isAudioDevice = true;
             }
         }
+
+        if (DEBUG) {
+            Slog.d(TAG, "  isAudioDevice: " + isAudioDevice);
+        }
         if (!isAudioDevice) {
             return;
         }
 
-        ArrayList<AlsaCardsParser.AlsaCardRecord> prevScanRecs = mCardsParser.getScanRecords();
-        mCardsParser.scan();
-
-        int addedCard = -1;
-        ArrayList<AlsaCardsParser.AlsaCardRecord>
-            newScanRecs = mCardsParser.getNewCardRecords(prevScanRecs);
-        if (newScanRecs.size() > 0) {
-            // This is where we select the just connected device
-            // NOTE - to switch to prefering the first-connected device, just always
-            // take the else clause below.
-            addedCard = newScanRecs.get(0).mCardNum;
-        } else {
-            addedCard = mCardsParser.getDefaultUsbCard();
-        }
+        int addedCard = mCardsParser.getDefaultUsbCard();
 
         // If the default isn't a USB device, let the existing "select internal mechanism"
         // handle the selection.
+        if (DEBUG) {
+            Slog.d(TAG, "  mCardsParser.isCardUsb(" + addedCard + ") = "
+                        + mCardsParser.isCardUsb(addedCard));
+        }
         if (mCardsParser.isCardUsb(addedCard)) {
             UsbAudioDevice audioDevice = selectAudioCard(addedCard);
             if (audioDevice != null) {
@@ -429,6 +428,10 @@
                 }
             }
         }
+
+        if (DEBUG) {
+            Slog.d(TAG, "deviceAdded() - done");
+        }
     }
 
     /* package */ void usbDeviceRemoved(UsbDevice usbDevice) {