Merge "Some networks may have null ifaces, I guess?" into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index 584246b..2a3c086 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4490,6 +4490,7 @@
 
   public class KeyguardManager {
     method public deprecated void exitKeyguardSecurely(android.app.KeyguardManager.OnKeyguardExitResult);
+    method public android.content.Intent getConfirmDeviceCredentialIntent(java.lang.CharSequence, java.lang.CharSequence);
     method public boolean inKeyguardRestrictedInputMode();
     method public boolean isKeyguardLocked();
     method public boolean isKeyguardSecure();
@@ -7680,7 +7681,6 @@
     field public static final java.lang.String ACTION_CHOOSER = "android.intent.action.CHOOSER";
     field public static final java.lang.String ACTION_CLOSE_SYSTEM_DIALOGS = "android.intent.action.CLOSE_SYSTEM_DIALOGS";
     field public static final java.lang.String ACTION_CONFIGURATION_CHANGED = "android.intent.action.CONFIGURATION_CHANGED";
-    field public static final java.lang.String ACTION_CONFIRM_DEVICE_CREDENTIAL = "android.intent.action.CONFIRM_DEVICE_CREDENTIAL";
     field public static final java.lang.String ACTION_CREATE_DOCUMENT = "android.intent.action.CREATE_DOCUMENT";
     field public static final java.lang.String ACTION_CREATE_SHORTCUT = "android.intent.action.CREATE_SHORTCUT";
     field public static final java.lang.String ACTION_DATE_CHANGED = "android.intent.action.DATE_CHANGED";
@@ -7824,7 +7824,6 @@
     field public static final java.lang.String EXTRA_CHANGED_PACKAGE_LIST = "android.intent.extra.changed_package_list";
     field public static final java.lang.String EXTRA_CHANGED_UID_LIST = "android.intent.extra.changed_uid_list";
     field public static final java.lang.String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED";
-    field public static final java.lang.String EXTRA_DETAILS = "android.intent.extra.DETAILS";
     field public static final java.lang.String EXTRA_DOCK_STATE = "android.intent.extra.DOCK_STATE";
     field public static final int EXTRA_DOCK_STATE_CAR = 2; // 0x2
     field public static final int EXTRA_DOCK_STATE_DESK = 1; // 0x1
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index db91742a..50e3a10 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.content.Intent;
 import android.os.Binder;
 import android.os.RemoteException;
 import android.os.IBinder;
@@ -24,7 +25,7 @@
 import android.view.WindowManagerGlobal;
 
 /**
- * Class that can be used to lock and unlock the keyboard. Get an instance of this 
+ * Class that can be used to lock and unlock the keyboard. Get an instance of this
  * class by calling {@link android.content.Context#getSystemService(java.lang.String)}
  * with argument {@link android.content.Context#KEYGUARD_SERVICE}. The
  * actual class to control the keyboard locking is
@@ -34,6 +35,45 @@
     private IWindowManager mWM;
 
     /**
+     * Intent used to prompt user for device credentials.
+     * @hide
+     */
+    public static final String ACTION_CONFIRM_DEVICE_CREDENTIAL =
+            "android.app.action.CONFIRM_DEVICE_CREDENTIAL";
+
+    /**
+     * A CharSequence dialog title to show to the user when used with a
+     * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}.
+     * @hide
+     */
+    public static final String EXTRA_TITLE = "android.app.extra.TITLE";
+
+    /**
+     * A CharSequence description to show to the user when used with
+     * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}.
+     * @hide
+     */
+    public static final String EXTRA_DESCRIPTION = "android.app.extra.DESCRIPTION";
+
+    /**
+     * Get an intent to prompt the user to confirm credentials (pin, pattern or password)
+     * for the current user of the device. The caller is expected to launch this activity using
+     * {@link android.app.Activity#startActivityForResult(Intent, int)} and check for
+     * {@link android.app.Activity#RESULT_OK} if the user successfully completes the challenge.
+     *
+     * @return the intent for launching the activity or null if no password is required.
+     **/
+    public Intent getConfirmDeviceCredentialIntent(CharSequence title, CharSequence description) {
+        if (!isKeyguardSecure()) return null;
+        Intent intent = new Intent(ACTION_CONFIRM_DEVICE_CREDENTIAL);
+        intent.putExtra(EXTRA_TITLE, title);
+        intent.putExtra(EXTRA_DESCRIPTION, description);
+        // For security reasons, only allow this to come from system settings.
+        intent.setPackage("com.android.settings");
+        return intent;
+    }
+
+    /**
      * @deprecated Use {@link android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUARD}
      * and/or {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED}
      * instead; this allows you to seamlessly hide the keyguard as your application
@@ -58,7 +98,7 @@
          *
          * A good place to call this is from {@link android.app.Activity#onResume()}
          *
-         * Note: This call has no effect while any {@link android.app.admin.DevicePolicyManager} 
+         * Note: This call has no effect while any {@link android.app.admin.DevicePolicyManager}
          * is enabled that requires a password.
          *
          * <p>This method requires the caller to hold the permission
@@ -121,7 +161,7 @@
      * permissions be requested.
      *
      * Enables you to lock or unlock the keyboard. Get an instance of this class by
-     * calling {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}. 
+     * calling {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
      * This class is wrapped by {@link android.app.KeyguardManager KeyguardManager}.
      * @param tag A tag that informally identifies who you are (for debugging who
      *   is disabling he keyguard).
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index abe4f0a..61e105b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1419,21 +1419,6 @@
     public static final String ACTION_UNINSTALL_PACKAGE = "android.intent.action.UNINSTALL_PACKAGE";
 
     /**
-     * Activity Action: Prompt the user to confirm credentials (pin, pattern or password)
-     * for the current user of the device. Launch this activity using
-     * {@link android.app.Activity#startActivityForResult(Intent, int)} and check if the
-     * result is {@link android.app.Activity#RESULT_OK} for a successful response to the
-     * challenge.<p/>
-     * This intent is handled by the system at a high priority and applications cannot intercept
-     * it.<p/>
-     * You can use {@link android.app.KeyguardManager#isKeyguardSecure()} to determine if the user will be
-     * prompted.
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_CONFIRM_DEVICE_CREDENTIAL = "android.intent.action.CONFIRM_DEVICE_CREDENTIAL";
-
-
-    /**
      * Specify whether the package should be uninstalled for all users.
      * @hide because these should not be part of normal application flow.
      */
@@ -3192,17 +3177,11 @@
 
     /**
      * A CharSequence dialog title to provide to the user when used with a
-     * {@link #ACTION_CHOOSER} or {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}.
+     * {@link #ACTION_CHOOSER}.
      */
     public static final String EXTRA_TITLE = "android.intent.extra.TITLE";
 
     /**
-     * A CharSequence description to provide to the user when used with
-     * {@link #ACTION_CONFIRM_DEVICE_CREDENTIAL}.
-     */
-    public static final String EXTRA_DETAILS = "android.intent.extra.DETAILS";
-
-    /**
      * A Parcelable[] of {@link Intent} or
      * {@link android.content.pm.LabeledIntent} objects as set with
      * {@link #putExtra(String, Parcelable[])} of additional activities to place
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index a536b2d..a82fa65 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1320,8 +1320,8 @@
                 attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
 
         boolean focusable = mMovement != null || getKeyListener() != null;
-        boolean clickable = focusable;
-        boolean longClickable = focusable;
+        boolean clickable = focusable || isClickable();
+        boolean longClickable = focusable || isLongClickable();
 
         n = a.getIndexCount();
         for (int i = 0; i < n; i++) {
diff --git a/core/res/res/color/primary_text_leanback_formwizard_dark.xml b/core/res/res/color/primary_text_leanback_formwizard_dark.xml
new file mode 100644
index 0000000..8fe02b2
--- /dev/null
+++ b/core/res/res/color/primary_text_leanback_formwizard_dark.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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false"
+        android:alpha="@dimen/disabled_alpha_leanback_formwizard"
+        android:color="@color/primary_text_leanback_formwizard_default_dark"/>
+    <item android:color="@color/primary_text_leanback_formwizard_default_dark"/>
+</selector>
diff --git a/core/res/res/values/colors_leanback.xml b/core/res/res/values/colors_leanback.xml
index dc0c673..e52a861e 100644
--- a/core/res/res/values/colors_leanback.xml
+++ b/core/res/res/values/colors_leanback.xml
@@ -25,4 +25,5 @@
     <color name="primary_text_leanback_light">#cc222222</color>
     <color name="secondary_text_leanback_light">#99222222</color>
 
+    <color name="primary_text_leanback_formwizard_default_dark">#ffeeeeee</color>
 </resources>
diff --git a/core/res/res/values/dimens_leanback.xml b/core/res/res/values/dimens_leanback.xml
new file mode 100644
index 0000000..fb5f8f0
--- /dev/null
+++ b/core/res/res/values/dimens_leanback.xml
@@ -0,0 +1,19 @@
+<?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>
+    <!-- Default alpha value for disabled elements. -->
+    <item name="disabled_alpha_leanback_formwizard" format="float" type="dimen">0.2</item>
+</resources>
diff --git a/core/res/res/values/styles_leanback.xml b/core/res/res/values/styles_leanback.xml
index 256ef00..72735f7 100644
--- a/core/res/res/values/styles_leanback.xml
+++ b/core/res/res/values/styles_leanback.xml
@@ -39,25 +39,29 @@
     <style name="TextAppearance.Leanback.FormWizard" parent="@style/TextAppearance.Material">
         <item name="textSize">18sp</item>
         <item name="fontFamily">sans-serif-light</item>
+        <item name="textColor">?attr/textColorPrimary</item>
     </style>
 
     <style name="TextAppearance.Leanback.FormWizard.Small" parent="@style/TextAppearance.Material.Small">
         <item name="textSize">18sp</item>
         <item name="fontFamily">sans-serif-light</item>
+        <item name="textColor">?attr/textColorPrimary</item>
     </style>
 
     <style name="TextAppearance.Leanback.FormWizard.Medium" parent="@style/TextAppearance.Material.Medium">
         <item name="textSize">36sp</item>
         <item name="fontFamily">sans-serif-thin</item>
+        <item name="textColor">?attr/textColorPrimary</item>
     </style>
 
     <style name="TextAppearance.Leanback.FormWizard.Large" parent="@style/TextAppearance.Material.Large">
         <item name="textSize">56sp</item>
         <item name="fontFamily">sans-serif-thin</item>
+        <item name="textColor">?attr/textColorPrimary</item>
     </style>
 
     <style name="TextAppearance.Leanback.FormWizard.ListItem" parent="@style/TextAppearance.Material.Subhead">
-        <item name="textSize">18sp</item>
+        <item name="textSize">16sp</item>
         <item name="fontFamily">sans-serif-condensed</item>
     </style>
 
diff --git a/core/res/res/values/themes_leanback.xml b/core/res/res/values/themes_leanback.xml
index 321b827..1cda843 100644
--- a/core/res/res/values/themes_leanback.xml
+++ b/core/res/res/values/themes_leanback.xml
@@ -57,5 +57,6 @@
         <item name="textAppearanceLarge">@style/TextAppearance.Leanback.FormWizard.Large</item>
         <item name="textAppearanceListItem">@style/TextAppearance.Leanback.FormWizard.ListItem</item>
         <item name="textAppearance">@style/TextAppearance.Leanback.FormWizard</item>
+        <item name="textColorPrimary">@color/primary_text_leanback_formwizard_dark</item>
     </style>
 </resources>
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index f5e63ae..40adf94 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -16,6 +16,7 @@
 
 package android.graphics.drawable;
 
+import android.annotation.NonNull;
 import android.content.res.ColorStateList;
 import android.content.res.Resources;
 import android.content.res.Resources.Theme;
@@ -27,6 +28,7 @@
 import android.graphics.ColorFilter;
 import android.graphics.Insets;
 import android.graphics.Matrix;
+import android.graphics.Outline;
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
 import android.graphics.PorterDuff;
@@ -598,6 +600,16 @@
     }
 
     @Override
+    public void getOutline(@NonNull Outline outline) {
+        super.getOutline(outline);
+        if (mBitmapState.mBitmap.hasAlpha()) {
+            // Bitmaps with alpha can't report a non-0 alpha,
+            // since they may not fill their rectangular bounds
+            outline.setAlpha(0.0f);
+        }
+    }
+
+    @Override
     public void setAlpha(int alpha) {
         final int oldAlpha = mBitmapState.mPaint.getAlpha();
         if (alpha != oldAlpha) {
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 7661d58..702f150 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -2691,6 +2691,9 @@
             case ResTable_config::DENSITY_XXHIGH:
                 res.append("xxhdpi");
                 break;
+            case ResTable_config::DENSITY_XXXHIGH:
+                res.append("xxxhdpi");
+                break;
             case ResTable_config::DENSITY_NONE:
                 res.append("nodpi");
                 break;
@@ -2852,17 +2855,16 @@
 struct ResTable::Package
 {
     Package(ResTable* _owner, const Header* _header, const ResTable_package* _package)
-        : owner(_owner), header(_header), package(_package), typeIdOffset(0) {
-        if (dtohs(package->header.headerSize) == sizeof(package)) {
+        : owner(_owner), header(_header), typeIdOffset(0) {
+        if (_package != NULL && dtohs(_package->header.headerSize) == sizeof(_package)) {
             // The package structure is the same size as the definition.
             // This means it contains the typeIdOffset field.
-            typeIdOffset = package->typeIdOffset;
+            typeIdOffset = _package->typeIdOffset;
         }
     }
 
     const ResTable* const           owner;
     const Header* const             header;
-    const ResTable_package* const   package;
 
     ResStringPool                   typeStrings;
     ResStringPool                   keyStrings;
@@ -3361,6 +3363,10 @@
 
     header->header = (const ResTable_header*) resHeader;
     mHeaders.add(header);
+
+    PackageGroup* pg = new PackageGroup(this, String16(), 0);
+    pg->packages.add(new Package(this, header, NULL));
+    mPackageGroups.add(pg);
     return (mError=NO_ERROR);
 }
 
@@ -5929,7 +5935,7 @@
     *outSize += 2 * sizeof(uint16_t);
 
     // overlay packages are assumed to contain only one package group
-    const String16 overlayPackage(overlay.mPackageGroups[0]->packages[0]->package->name);
+    const String16 overlayPackage(overlay.mPackageGroups[0]->name);
 
     for (size_t typeIndex = 0; typeIndex < pg->types.size(); ++typeIndex) {
         const TypeList& typeList = pg->types[typeIndex];
@@ -6204,11 +6210,6 @@
     if (mError != 0) {
         printf("mError=0x%x (%s)\n", mError, strerror(mError));
     }
-#if 0
-    char localeStr[RESTABLE_MAX_LOCALE_LEN];
-    mParams.getBcp47Locale(localeStr);
-    printf("mParams=%s,\n" localeStr);
-#endif
     size_t pgCount = mPackageGroups.size();
     printf("Package Groups (%d)\n", (int)pgCount);
     for (size_t pgIndex=0; pgIndex<pgCount; pgIndex++) {
@@ -6217,13 +6218,6 @@
                 (int)pgIndex, pg->id, (int)pg->packages.size(),
                 String8(pg->name).string());
 
-        size_t pkgCount = pg->packages.size();
-        for (size_t pkgIndex=0; pkgIndex<pkgCount; pkgIndex++) {
-            const Package* pkg = pg->packages[pkgIndex];
-            printf("  Package %d id=%d name=%s\n", (int)pkgIndex,
-                    pkg->package->id, String8(String16(pkg->package->name)).string());
-        }
-
         for (size_t typeIndex=0; typeIndex < pg->types.size(); typeIndex++) {
             const TypeList& typeList = pg->types[typeIndex];
             if (typeList.isEmpty()) {
diff --git a/libs/androidfw/tests/ResTable_test.cpp b/libs/androidfw/tests/ResTable_test.cpp
index 8016a82..68c228e 100644
--- a/libs/androidfw/tests/ResTable_test.cpp
+++ b/libs/androidfw/tests/ResTable_test.cpp
@@ -195,4 +195,21 @@
     ASSERT_EQ(uint32_t(400), val.data);
 }
 
+TEST(ResTableTest, emptyTableHasSensibleDefaults) {
+    const int32_t expectedCookie = 1;
+
+    ResTable table;
+    ASSERT_EQ(NO_ERROR, table.addEmpty(expectedCookie));
+
+    ASSERT_EQ(uint32_t(1), table.getTableCount());
+    ASSERT_EQ(uint32_t(1), table.getBasePackageCount());
+    ASSERT_EQ(expectedCookie, table.getTableCookie(0));
+
+    const DynamicRefTable* dynamicRefTable = table.getDynamicRefTableForCookie(expectedCookie);
+    ASSERT_TRUE(dynamicRefTable != NULL);
+
+    Res_value val;
+    ASSERT_LT(table.getResource(base::R::integer::number1, &val, MAY_NOT_BE_BAG), 0);
+}
+
 }
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
index 5ecd77a..78d569d 100644
--- a/libs/hwui/Animator.cpp
+++ b/libs/hwui/Animator.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "RT-Animator"
-
 #include "Animator.h"
 
 #include <inttypes.h>
diff --git a/libs/hwui/DamageAccumulator.cpp b/libs/hwui/DamageAccumulator.cpp
index 15bed58..054a164 100644
--- a/libs/hwui/DamageAccumulator.cpp
+++ b/libs/hwui/DamageAccumulator.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "DamageAccumulator"
-
 #include "DamageAccumulator.h"
 
 #include <cutils/log.h>
@@ -26,12 +24,6 @@
 namespace android {
 namespace uirenderer {
 
-NullDamageAccumulator NullDamageAccumulator::sInstance;
-
-NullDamageAccumulator* NullDamageAccumulator::instance() {
-    return &sInstance;
-}
-
 enum TransformType {
     TransformInvalid = 0,
     TransformRenderNode,
@@ -60,6 +52,30 @@
     mHead->type = TransformNone;
 }
 
+static void computeTransformImpl(const DirtyStack* currentFrame, Matrix4* outMatrix) {
+    if (currentFrame->prev != currentFrame) {
+        computeTransformImpl(currentFrame->prev, outMatrix);
+    }
+    switch (currentFrame->type) {
+    case TransformRenderNode:
+        currentFrame->renderNode->applyViewPropertyTransforms(*outMatrix);
+        break;
+    case TransformMatrix4:
+        outMatrix->multiply(*currentFrame->matrix4);
+        break;
+    case TransformNone:
+        // nothing to be done
+        break;
+    default:
+        LOG_ALWAYS_FATAL("Tried to compute transform with an invalid type: %d", currentFrame->type);
+    }
+}
+
+void DamageAccumulator::computeCurrentTransform(Matrix4* outMatrix) const {
+    outMatrix->loadIdentity();
+    computeTransformImpl(mHead, outMatrix);
+}
+
 void DamageAccumulator::pushCommon() {
     if (!mHead->next) {
         DirtyStack* nextFrame = (DirtyStack*) mAllocator.alloc(sizeof(DirtyStack));
diff --git a/libs/hwui/DamageAccumulator.h b/libs/hwui/DamageAccumulator.h
index 90d9425..6f0bd8c 100644
--- a/libs/hwui/DamageAccumulator.h
+++ b/libs/hwui/DamageAccumulator.h
@@ -31,18 +31,7 @@
 class RenderNode;
 class Matrix4;
 
-class IDamageAccumulator {
-public:
-    virtual void pushTransform(const RenderNode* transform) = 0;
-    virtual void pushTransform(const Matrix4* transform) = 0;
-    virtual void popTransform() = 0;
-    virtual void dirty(float left, float top, float right, float bottom) = 0;
-    virtual void peekAtDirty(SkRect* dest) = 0;
-protected:
-    virtual ~IDamageAccumulator() {}
-};
-
-class DamageAccumulator : public IDamageAccumulator {
+class DamageAccumulator {
     PREVENT_COPY_AND_ASSIGN(DamageAccumulator);
 public:
     DamageAccumulator();
@@ -51,17 +40,19 @@
     // Push a transform node onto the stack. This should be called prior
     // to any dirty() calls. Subsequent calls to dirty()
     // will be affected by the transform when popTransform() is called.
-    virtual void pushTransform(const RenderNode* transform);
-    virtual void pushTransform(const Matrix4* transform);
+    void pushTransform(const RenderNode* transform);
+    void pushTransform(const Matrix4* transform);
 
     // Pops a transform node from the stack, propagating the dirty rect
     // up to the parent node. Returns the IDamageTransform that was just applied
-    virtual void popTransform();
+    void popTransform();
 
-    virtual void dirty(float left, float top, float right, float bottom);
+    void dirty(float left, float top, float right, float bottom);
 
     // Returns the current dirty area, *NOT* transformed by pushed transforms
-    virtual void peekAtDirty(SkRect* dest);
+    void peekAtDirty(SkRect* dest);
+
+    void computeCurrentTransform(Matrix4* outMatrix) const;
 
     void finish(SkRect* totalDirty);
 
@@ -74,24 +65,6 @@
     DirtyStack* mHead;
 };
 
-class NullDamageAccumulator : public IDamageAccumulator {
-    PREVENT_COPY_AND_ASSIGN(NullDamageAccumulator);
-public:
-    virtual void pushTransform(const RenderNode* transform) { }
-    virtual void pushTransform(const Matrix4* transform) { }
-    virtual void popTransform() { }
-    virtual void dirty(float left, float top, float right, float bottom) { }
-    virtual void peekAtDirty(SkRect* dest) { dest->setEmpty(); }
-
-    ANDROID_API static NullDamageAccumulator* instance();
-
-private:
-    NullDamageAccumulator() {}
-    ~NullDamageAccumulator() {}
-
-    static NullDamageAccumulator sInstance;
-};
-
 } /* namespace uirenderer */
 } /* namespace android */
 
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index f0a6e55..94162fc 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -66,7 +66,7 @@
             "prepareDirty called a second time during a recording!");
     mDisplayListData = new DisplayListData();
 
-    initializeSaveStack(0, 0, getWidth(), getHeight());
+    initializeSaveStack(0, 0, getWidth(), getHeight(), Vector3());
 
     mDirtyClip = opaque;
     mRestoreSaveCount = -1;
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index d05cabc..8639ae1 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -53,6 +53,7 @@
     deferredList = NULL;
     convexMask = NULL;
     caches.resourceCache.incrementRefcount(this);
+    rendererLightPosDirty = true;
 }
 
 Layer::~Layer() {
@@ -80,6 +81,17 @@
     }
 }
 
+void Layer::updateLightPosFromRenderer(const OpenGLRenderer& rootRenderer) {
+    if (renderer && rendererLightPosDirty) {
+        // re-init renderer's light position, based upon last cached location in window
+        Vector3 lightPos = rootRenderer.getLightCenter();
+        cachedInvTransformInWindow.mapPoint3d(lightPos);
+        renderer->initLight(lightPos, rootRenderer.getLightRadius(),
+                rootRenderer.getAmbientShadowAlpha(), rootRenderer.getSpotShadowAlpha());
+        rendererLightPosDirty = false;
+    }
+}
+
 bool Layer::resize(const uint32_t width, const uint32_t height) {
     uint32_t desiredWidth = computeIdealWidth(width);
     uint32_t desiredHeight = computeIdealWidth(height);
@@ -203,7 +215,8 @@
     }
 }
 
-void Layer::defer() {
+void Layer::defer(const OpenGLRenderer& rootRenderer) {
+    updateLightPosFromRenderer(rootRenderer);
     const float width = layer.getWidth();
     const float height = layer.getHeight();
 
@@ -253,7 +266,8 @@
     }
 }
 
-void Layer::render() {
+void Layer::render(const OpenGLRenderer& rootRenderer) {
+    updateLightPosFromRenderer(rootRenderer);
     renderer->setViewport(layer.getWidth(), layer.getHeight());
     renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom,
             !isBlend());
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 0bf05d0..38c29c7 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -86,6 +86,11 @@
         regionRect.translate(layer.left, layer.top);
     }
 
+    void setWindowTransform(Matrix4& windowTransform) {
+        cachedInvTransformInWindow.loadInverse(windowTransform);
+        rendererLightPosDirty = true;
+    }
+
     void updateDeferred(RenderNode* renderNode, int left, int top, int right, int bottom);
 
     inline uint32_t getWidth() const {
@@ -257,10 +262,10 @@
         return transform;
     }
 
-    void defer();
+    void defer(const OpenGLRenderer& rootRenderer);
     void cancelDefer();
     void flush();
-    void render();
+    void render(const OpenGLRenderer& rootRenderer);
 
     /**
      * Bounds of the layer.
@@ -304,6 +309,7 @@
 
 private:
     void requireRenderer();
+    void updateLightPosFromRenderer(const OpenGLRenderer& rootRenderer);
 
     Caches& caches;
 
@@ -383,6 +389,12 @@
     mat4 transform;
 
     /**
+     * Cached transform of layer in window, updated only on creation / resize
+     */
+    mat4 cachedInvTransformInWindow;
+    bool rendererLightPosDirty;
+
+    /**
      * Used to defer display lists when the layer is updated with a
      * display list.
      */
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 3fcfbc1..721ab3d 100755
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -188,8 +188,7 @@
 void OpenGLRenderer::setupFrameState(float left, float top,
         float right, float bottom, bool opaque) {
     mCaches.clearGarbage();
-
-    initializeSaveStack(left, top, right, bottom);
+    initializeSaveStack(left, top, right, bottom, mLightCenter);
     mOpaque = opaque;
     mTilingClip.set(left, top, right, bottom);
 }
@@ -481,9 +480,9 @@
         }
 
         if (CC_UNLIKELY(inFrame || mCaches.drawDeferDisabled)) {
-            layer->render();
+            layer->render(*this);
         } else {
-            layer->defer();
+            layer->defer(*this);
         }
 
         if (inFrame) {
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index fc95c18..e9ca5d9 100755
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -345,8 +345,10 @@
     }
 #endif
 
-    const Vector3& getLightCenter() const { return mLightCenter; }
+    const Vector3& getLightCenter() const { return currentSnapshot()->getRelativeLightCenter(); }
     float getLightRadius() const { return mLightRadius; }
+    uint8_t getAmbientShadowAlpha() const { return mAmbientShadowAlpha; }
+    uint8_t getSpotShadowAlpha() const { return mSpotShadowAlpha; }
 
 protected:
     /**
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index e3732a1..0db6198 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -116,6 +116,7 @@
 
 void RenderNode::prepareTree(TreeInfo& info) {
     ATRACE_CALL();
+    LOG_ALWAYS_FATAL_IF(!info.damageAccumulator, "DamageAccumulator missing");
 
     prepareTreeImpl(info);
 }
@@ -163,16 +164,26 @@
         return;
     }
 
+    bool transformUpdateNeeded = false;
     if (!mLayer) {
         mLayer = LayerRenderer::createRenderLayer(info.renderState, getWidth(), getHeight());
         applyLayerPropertiesToLayer(info);
         damageSelf(info);
+        transformUpdateNeeded = true;
     } else if (mLayer->layer.getWidth() != getWidth() || mLayer->layer.getHeight() != getHeight()) {
         if (!LayerRenderer::resizeLayer(mLayer, getWidth(), getHeight())) {
             LayerRenderer::destroyLayer(mLayer);
             mLayer = 0;
         }
         damageSelf(info);
+        transformUpdateNeeded = true;
+    }
+
+    if (transformUpdateNeeded) {
+        // update the transform in window of the layer to reset its origin wrt light source position
+        Matrix4 windowTransform;
+        info.damageAccumulator->computeCurrentTransform(&windowTransform);
+        mLayer->setWindowTransform(windowTransform);
     }
 
     SkRect dirty;
@@ -406,7 +417,7 @@
  * If true3dTransform is set to true, the transform applied to the input matrix will use true 4x4
  * matrix computation instead of the Skia 3x3 matrix + camera hackery.
  */
-void RenderNode::applyViewPropertyTransforms(mat4& matrix, bool true3dTransform) {
+void RenderNode::applyViewPropertyTransforms(mat4& matrix, bool true3dTransform) const {
     if (properties().getLeft() != 0 || properties().getTop() != 0) {
         matrix.translate(properties().getLeft(), properties().getTop());
     }
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index fa310e0..afa17d5 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -174,6 +174,8 @@
     // UI thread only!
     ANDROID_API void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
 
+    void applyViewPropertyTransforms(mat4& matrix, bool true3dTransform = false) const;
+
 private:
     typedef key_value_pair_t<float, DrawRenderNodeOp*> ZDrawRenderNodeOpPair;
 
@@ -189,8 +191,6 @@
         kPositiveZChildren
     };
 
-    void applyViewPropertyTransforms(mat4& matrix, bool true3dTransform = false);
-
     void computeOrderingImpl(DrawRenderNodeOp* opState,
             const SkPath* outlineOfProjectionSurface,
             Vector<DrawRenderNodeOp*>* compositedChildrenOfProjectionSurface,
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index 6f19275..ecc47d2 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -55,7 +55,8 @@
         , empty(false)
         , alpha(s->alpha)
         , roundRectClipState(s->roundRectClipState)
-        , mViewportData(s->mViewportData) {
+        , mViewportData(s->mViewportData)
+        , mRelativeLightCenter(s->mRelativeLightCenter) {
     if (saveFlags & SkCanvas::kMatrix_SaveFlag) {
         mTransformRoot.load(*s->transform);
         transform = &mTransformRoot;
@@ -200,6 +201,13 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 void Snapshot::resetTransform(float x, float y, float z) {
+    // before resetting, map current light pos with inverse of current transform
+    Vector3 center = mRelativeLightCenter;
+    mat4 inverse;
+    inverse.loadInverse(*transform);
+    inverse.mapPoint3d(center);
+    mRelativeLightCenter = center;
+
     transform = &mTransformRoot;
     transform->loadTranslate(x, y, z);
 }
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 98e2440..ad4ee9d 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -161,6 +161,9 @@
     int getViewportHeight() const { return mViewportData.mHeight; }
     const Matrix4& getOrthoMatrix() const { return mViewportData.mOrthoMatrix; }
 
+    const Vector3& getRelativeLightCenter() const { return mRelativeLightCenter; }
+    void setRelativeLightCenter(const Vector3& lightCenter) { mRelativeLightCenter = lightCenter; }
+
     /**
      * Sets (and replaces) the current clipping outline
      */
@@ -302,6 +305,7 @@
 
     SkRegion mClipRegionRoot;
     ViewportData mViewportData;
+    Vector3 mRelativeLightCenter;
 
 }; // class Snapshot
 
diff --git a/libs/hwui/StatefulBaseRenderer.cpp b/libs/hwui/StatefulBaseRenderer.cpp
index dc41157..06c5ab4 100644
--- a/libs/hwui/StatefulBaseRenderer.cpp
+++ b/libs/hwui/StatefulBaseRenderer.cpp
@@ -35,11 +35,12 @@
 }
 
 void StatefulBaseRenderer::initializeSaveStack(float clipLeft, float clipTop,
-        float clipRight, float clipBottom) {
+        float clipRight, float clipBottom, const Vector3& lightCenter) {
     mSnapshot = new Snapshot(mFirstSnapshot,
             SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
     mSnapshot->setClip(clipLeft, clipTop, clipRight, clipBottom);
     mSnapshot->fbo = getTargetFbo();
+    mSnapshot->setRelativeLightCenter(lightCenter);
     mSaveCount = 1;
 }
 
diff --git a/libs/hwui/StatefulBaseRenderer.h b/libs/hwui/StatefulBaseRenderer.h
index 6d83b4c..3957d36 100644
--- a/libs/hwui/StatefulBaseRenderer.h
+++ b/libs/hwui/StatefulBaseRenderer.h
@@ -52,7 +52,8 @@
      * the render target.
      */
     virtual void setViewport(int width, int height);
-    void initializeSaveStack(float clipLeft, float clipTop, float clipRight, float clipBottom);
+    void initializeSaveStack(float clipLeft, float clipTop, float clipRight, float clipBottom,
+            const Vector3& lightCenter);
 
     // getters
     bool hasRectToRectTransform() const {
diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp
index c5fc21f..0a9aeb8 100644
--- a/libs/hwui/TessellationCache.cpp
+++ b/libs/hwui/TessellationCache.cpp
@@ -14,9 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "OpenGLRenderer"
-#define ATRACE_TAG ATRACE_TAG_VIEW
-
 #include <utils/JenkinsHash.h>
 #include <utils/Trace.h>
 
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index de09755..331f157 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -65,7 +65,7 @@
         , frameTimeMs(0)
         , animationHook(NULL)
         , prepareTextures(mode == MODE_FULL)
-        , damageAccumulator(NullDamageAccumulator::instance())
+        , damageAccumulator(NULL)
         , renderState(renderState)
         , renderer(NULL)
         , errorHandler(NULL)
@@ -88,8 +88,9 @@
     // TODO: Remove this? Currently this is used to signal to stop preparing
     // textures if we run out of cache space.
     bool prepareTextures;
-    // Must not be null
-    IDamageAccumulator* damageAccumulator;
+
+    // Must not be null during actual usage
+    DamageAccumulator* damageAccumulator;
     RenderState& renderState;
     // The renderer that will be drawing the next frame. Use this to push any
     // layer updates or similar. May be NULL.
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 756f660..e673b0d 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "CanvasContext"
-
 #include "CanvasContext.h"
 
 #include <private/hwui/DrawGlInfo.h>
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 986e808..d9b96f6c 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "RenderProxy"
-
 #include "RenderProxy.h"
 
 #include "CanvasContext.h"
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 03e98d5..403e164 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "RenderThread"
-
 #include "RenderThread.h"
 
+#if defined(HAVE_PTHREADS)
+#include <sys/resource.h>
+#endif
 #include <gui/DisplayEventReceiver.h>
 #include <utils/Log.h>
 
@@ -244,6 +245,9 @@
 }
 
 bool RenderThread::threadLoop() {
+#if defined(HAVE_PTHREADS)
+    setpriority(PRIO_PROCESS, 0, PRIORITY_DISPLAY);
+#endif
     initThreadLocals();
 
     int timeoutMillis = -1;
diff --git a/libs/hwui/thread/TaskManager.cpp b/libs/hwui/thread/TaskManager.cpp
index 3d2b0d9..cb5401c 100644
--- a/libs/hwui/thread/TaskManager.cpp
+++ b/libs/hwui/thread/TaskManager.cpp
@@ -15,6 +15,9 @@
  */
 
 #include <sys/sysinfo.h>
+#if defined(HAVE_PTHREADS)
+#include <sys/resource.h>
+#endif
 
 #include "TaskManager.h"
 #include "Task.h"
@@ -79,6 +82,13 @@
 // Thread
 ///////////////////////////////////////////////////////////////////////////////
 
+status_t TaskManager::WorkerThread::readyToRun() {
+#if defined(HAVE_PTHREADS)
+    setpriority(PRIO_PROCESS, 0, PRIORITY_FOREGROUND);
+#endif
+    return NO_ERROR;
+}
+
 bool TaskManager::WorkerThread::threadLoop() {
     mSignal.wait();
     Vector<TaskWrapper> tasks;
diff --git a/libs/hwui/thread/TaskManager.h b/libs/hwui/thread/TaskManager.h
index f2a216f..5a933ab 100644
--- a/libs/hwui/thread/TaskManager.h
+++ b/libs/hwui/thread/TaskManager.h
@@ -84,6 +84,7 @@
         void exit();
 
     private:
+        virtual status_t readyToRun();
         virtual bool threadLoop();
 
         // Lock for the list of tasks
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index b8ac3e7..3e2a398 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -25,9 +25,12 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
+import android.os.AsyncTask;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.phone.PhoneManager;
 import android.provider.MediaStore;
+import android.telecomm.TelecommManager;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.TypedValue;
@@ -246,7 +249,18 @@
     }
 
     public void launchPhone() {
-        mActivityStarter.startActivity(PHONE_INTENT, false /* dismissShade */);
+        TelecommManager tm = TelecommManager.from(mContext);
+        if (tm.isInAPhoneCall()) {
+            final PhoneManager pm = (PhoneManager) mContext.getSystemService(Context.PHONE_SERVICE);
+            AsyncTask.execute(new Runnable() {
+                @Override
+                public void run() {
+                    pm.showCallScreen(false /* showDialpad */);
+                }
+            });
+        } else {
+            mActivityStarter.startActivity(PHONE_INTENT, false /* dismissShade */);
+        }
     }
 
 
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 3fcd067..b2575e6 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -252,6 +252,15 @@
         return false;
     }
 
+    void removeAllWindows() {
+        for (int winNdx = allAppWindows.size() - 1; winNdx >= 0; --winNdx) {
+            WindowState win = allAppWindows.get(winNdx);
+            if (WindowManagerService.DEBUG_WINDOW_MOVEMENT) Slog.w(WindowManagerService.TAG,
+                    "removeAllWindows: removing win=" + win);
+            win.mService.removeWindowLocked(win.mSession, win);
+        }
+    }
+
     @Override
     void dump(PrintWriter pw, String prefix) {
         super.dump(pw, prefix);
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index dfb1200..238c77e 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -155,7 +155,7 @@
                 final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows;
                 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
                     final WindowStateAnimator winAnimator = windows.get(winNdx).mWinAnimator;
-                    if (winAnimator.isAnimating() && !winAnimator.isDummyAnimation()) {
+                    if (winAnimator.isAnimating() || winAnimator.mWin.mExiting) {
                         return true;
                     }
                 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 711cf9c..2295656 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -3592,7 +3592,7 @@
                 return;
             }
             final Task oldTask = mTaskIdToTask.get(atoken.groupId);
-            removeAppFromTaskLocked(atoken);
+            oldTask.removeAppToken(atoken);
 
             atoken.groupId = groupId;
             Task newTask = mTaskIdToTask.get(groupId);
@@ -4634,6 +4634,8 @@
     }
 
     void removeAppFromTaskLocked(AppWindowToken wtoken) {
+        wtoken.removeAllWindows();
+
         final Task task = mTaskIdToTask.get(wtoken.groupId);
         if (task != null) {
             if (!task.removeAppToken(wtoken)) {
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index d5e4f1b..44aacfc 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -539,7 +539,10 @@
                         connection.getCallerDisplayNamePresentation(),
                         connection.getVideoProvider() == null ?
                                 null : connection.getVideoProvider().getInterface(),
-                        connection.getVideoState()));
+                        connection.getVideoState(),
+                        connection.isRequestingRingback(),
+                        connection.getAudioModeIsVoip(),
+                        connection.getStatusHints()));
     }
 
     private void abort(String callId) {
diff --git a/telecomm/java/android/telecomm/ParcelableConnection.java b/telecomm/java/android/telecomm/ParcelableConnection.java
index 78dd64a..7a87b87 100644
--- a/telecomm/java/android/telecomm/ParcelableConnection.java
+++ b/telecomm/java/android/telecomm/ParcelableConnection.java
@@ -38,6 +38,9 @@
     private int mCallerDisplayNamePresentation;
     private IVideoProvider mVideoProvider;
     private int mVideoState;
+    private boolean mRequestingRingback;
+    private boolean mAudioModeIsVoip;
+    private StatusHints mStatusHints;
 
     /** @hide */
     public ParcelableConnection(
@@ -49,7 +52,10 @@
             String callerDisplayName,
             int callerDisplayNamePresentation,
             IVideoProvider videoProvider,
-            int videoState) {
+            int videoState,
+            boolean requestingRingback,
+            boolean audioModeIsVoip,
+            StatusHints statusHints) {
         mPhoneAccount = phoneAccount;
         mState = state;
         mCapabilities = capabilities;
@@ -59,6 +65,9 @@
         mCallerDisplayNamePresentation = callerDisplayNamePresentation;
         mVideoProvider = videoProvider;
         mVideoState = videoState;
+        mRequestingRingback = requestingRingback;
+        mAudioModeIsVoip = audioModeIsVoip;
+        mStatusHints = statusHints;
     }
 
     public PhoneAccountHandle getPhoneAccount() {
@@ -98,6 +107,18 @@
         return mVideoState;
     }
 
+    public boolean isRequestingRingback() {
+        return mRequestingRingback;
+    }
+
+    public boolean getAudioModeIsVoip() {
+        return mAudioModeIsVoip;
+    }
+
+    public final StatusHints getStatusHints() {
+        return mStatusHints;
+    }
+
     @Override
     public String toString() {
         return new StringBuilder()
@@ -126,6 +147,9 @@
             IVideoProvider videoCallProvider =
                     IVideoProvider.Stub.asInterface(source.readStrongBinder());
             int videoState = source.readInt();
+            boolean requestingRingback = source.readByte() == 1;
+            boolean audioModeIsVoip = source.readByte() == 1;
+            StatusHints statusHints = source.readParcelable(classLoader);
 
             return new ParcelableConnection(
                     phoneAccount,
@@ -136,7 +160,10 @@
                     callerDisplayName,
                     callerDisplayNamePresentation,
                     videoCallProvider,
-                    videoState);
+                    videoState,
+                    requestingRingback,
+                    audioModeIsVoip,
+                    statusHints);
         }
 
         @Override
@@ -164,5 +191,8 @@
         destination.writeStrongBinder(
                 mVideoProvider != null ? mVideoProvider.asBinder() : null);
         destination.writeInt(mVideoState);
+        destination.writeByte((byte) (mRequestingRingback ? 1 : 0));
+        destination.writeByte((byte) (mAudioModeIsVoip ? 1 : 0));
+        destination.writeParcelable(mStatusHints, 0);
     }
 }
diff --git a/telecomm/java/android/telecomm/RemoteConnection.java b/telecomm/java/android/telecomm/RemoteConnection.java
index 13b0834..d3972d31 100644
--- a/telecomm/java/android/telecomm/RemoteConnection.java
+++ b/telecomm/java/android/telecomm/RemoteConnection.java
@@ -24,9 +24,11 @@
 import android.telephony.DisconnectCause;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * A connection provided to a {@link ConnectionService} by another {@code ConnectionService}
@@ -182,7 +184,8 @@
 
     private IConnectionService mConnectionService;
     private final String mConnectionId;
-    private final Set<Listener> mListeners = new HashSet<>();
+    private final Set<Listener> mListeners = Collections.newSetFromMap(
+            new ConcurrentHashMap<Listener, Boolean>(2));
     private final Set<RemoteConnection> mConferenceableConnections = new HashSet<>();
 
     private int mState = Connection.STATE_NEW;
diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp
index cf3dd0a..137c85c 100644
--- a/tools/aapt/Images.cpp
+++ b/tools/aapt/Images.cpp
@@ -485,9 +485,13 @@
     find_max_opacity(image->rows, innerStartX, innerStartY, innerMidX, innerMidY, 1, 1,
             &diagonalInset);
 
-    // Determine source radius based upon inset
-    // radius = 1 / (sqrt(2) - 1) * inset
-    image->outlineRadius = 2.4142f * diagonalInset;
+    /* Determine source radius based upon inset:
+     *     sqrt(r^2 + r^2) = sqrt(i^2 + i^2) + r
+     *     sqrt(2) * r = sqrt(2) * i + r
+     *     (sqrt(2) - 1) * r = sqrt(2) * i
+     *     r = sqrt(2) / (sqrt(2) - 1) * i
+     */
+    image->outlineRadius = 3.4142f * diagonalInset;
 
     NOISY(printf("outline insets %d %d %d %d, rad %f, alpha %x\n",
             image->outlineInsetsLeft,