Merge "Fix issue #22124996: VI: Command Request not Active" into mnc-dev
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 7fda30a..fe323f3 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -184,6 +184,7 @@
     private static final String UID_DATA = "uid";
     private static final String APK_DATA = "apk";
     private static final String PROCESS_DATA = "pr";
+    private static final String CPU_DATA = "cpu";
     private static final String SENSOR_DATA = "sr";
     private static final String VIBRATOR_DATA = "vib";
     private static final String FOREGROUND_DATA = "fg";
@@ -457,8 +458,13 @@
         public abstract long getSystemCpuTimeUs(int which);
 
         /**
+         * Get the total cpu power consumed (in milli-ampere-microseconds).
+         */
+        public abstract long getCpuPowerMaUs(int which);
+
+        /**
          * Returns the approximate cpu time (in milliseconds) spent at a certain CPU speed.
-         * @param speedStep the index of the CPU speed. This is not the actual speed of the CPU.
+         * @param step the index of the CPU speed. This is not the actual speed of the CPU.
          * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
          * @see BatteryStats#getCpuSpeedSteps()
          */
@@ -2905,6 +2911,14 @@
                 dumpLine(pw, uid, category, STATE_TIME_DATA, stateTimes);
             }
 
+            final long userCpuTimeUs = u.getUserCpuTimeUs(which);
+            final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
+            final long powerCpuMaUs = u.getCpuPowerMaUs(which);
+            if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) {
+                dumpLine(pw, uid, category, CPU_DATA, userCpuTimeUs / 1000, systemCpuTimeUs / 1000,
+                        powerCpuMaUs / 1000);
+            }
+
             final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
                     = u.getProcessStats();
             for (int ipr=processStats.size()-1; ipr>=0; ipr--) {
@@ -2970,6 +2984,10 @@
         printer.print(BatteryStatsHelper.makemAh(power));
     }
 
+    private void printmAh(StringBuilder sb, double power) {
+        sb.append(BatteryStatsHelper.makemAh(power));
+    }
+
     /**
      * Temporary for settings.
      */
@@ -4028,13 +4046,17 @@
 
             final long userCpuTimeUs = u.getUserCpuTimeUs(which);
             final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
-            if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) {
+            final long powerCpuMaUs = u.getCpuPowerMaUs(which);
+            if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) {
                 sb.setLength(0);
                 sb.append(prefix);
                 sb.append("    Total cpu time: u=");
                 formatTimeMs(sb, userCpuTimeUs / 1000);
                 sb.append("s=");
                 formatTimeMs(sb, systemCpuTimeUs / 1000);
+                sb.append("p=");
+                printmAh(sb, powerCpuMaUs / (1000.0 * 1000.0 * 60.0 * 60.0));
+                sb.append("mAh");
                 pw.println(sb.toString());
             }
 
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 6874e77..511bd5f 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -179,6 +179,19 @@
     }
 
     /**
+     * Returns the app id for a given shared app gid.
+     * @hide
+     */
+    public static final int getAppIdFromSharedAppGid(int gid) {
+        final int noUserGid = getAppId(gid);
+        if (noUserGid < Process.FIRST_SHARED_APPLICATION_GID ||
+                noUserGid > Process.LAST_SHARED_APPLICATION_GID) {
+            throw new IllegalArgumentException(Integer.toString(gid) + " is not a shared app gid");
+        }
+        return (noUserGid + Process.FIRST_APPLICATION_UID) - Process.FIRST_SHARED_APPLICATION_GID;
+    }
+
+    /**
      * Generate a text representation of the uid, breaking out its individual
      * components -- user, app, isolated, etc.
      * @hide
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 6384af3..b104135 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -572,6 +572,16 @@
     }
 
     /**
+     * @hide
+     * Returns whether the caller is running as an admin user. There can be more than one admin
+     * user.
+     */
+    public boolean isAdminUser() {
+        UserInfo user = getUserInfo(UserHandle.myUserId());
+        return user != null ? user.isAdmin() : false;
+    }
+
+    /**
      * Used to check if the user making this call is linked to another user. Linked users may have
      * a reduced number of available apps, app restrictions and account restrictions.
      * @return whether the user making this call is a linked user
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 23da6d2..63dd492 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12288,6 +12288,7 @@
             mRenderNode.offsetTopAndBottom(offset);
             if (isHardwareAccelerated()) {
                 invalidateViewProperty(false, false);
+                invalidateParentIfNeededAndWasQuickRejected();
             } else {
                 if (!matrixIsIdentity) {
                     invalidateViewProperty(false, true);
@@ -12335,6 +12336,7 @@
             mRenderNode.offsetLeftAndRight(offset);
             if (isHardwareAccelerated()) {
                 invalidateViewProperty(false, false);
+                invalidateParentIfNeededAndWasQuickRejected();
             } else {
                 if (!matrixIsIdentity) {
                     invalidateViewProperty(false, true);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 1bd821d..8b4b9942 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -106,7 +106,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 129 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 130 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -4386,6 +4386,7 @@
 
         LongSamplingCounter mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase);
         LongSamplingCounter mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase);
+        LongSamplingCounter mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase);
         LongSamplingCounter[] mSpeedBins;
 
         /**
@@ -4978,6 +4979,11 @@
         }
 
         @Override
+        public long getCpuPowerMaUs(int which) {
+            return mCpuPower.getCountLocked(which);
+        }
+
+        @Override
         public long getTimeAtCpuSpeed(int step, int which) {
             if (step >= 0 && step < mSpeedBins.length) {
                 if (mSpeedBins[step] != null) {
@@ -5097,6 +5103,7 @@
 
             mUserCpuTime.reset(false);
             mSystemCpuTime.reset(false);
+            mCpuPower.reset(false);
             for (int i = 0; i < mSpeedBins.length; i++) {
                 LongSamplingCounter c = mSpeedBins[i];
                 if (c != null) {
@@ -5248,6 +5255,7 @@
 
                 mUserCpuTime.detach();
                 mSystemCpuTime.detach();
+                mCpuPower.detach();
                 for (int i = 0; i < mSpeedBins.length; i++) {
                     LongSamplingCounter c = mSpeedBins[i];
                     if (c != null) {
@@ -5427,6 +5435,7 @@
 
             mUserCpuTime.writeToParcel(out);
             mSystemCpuTime.writeToParcel(out);
+            mCpuPower.writeToParcel(out);
 
             out.writeInt(mSpeedBins.length);
             for (int i = 0; i < mSpeedBins.length; i++) {
@@ -5618,6 +5627,7 @@
 
             mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
             mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
+            mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase, in);
 
             int bins = in.readInt();
             int steps = getCpuSpeedSteps();
@@ -7964,7 +7974,8 @@
         mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null :
                 new KernelUidCpuTimeReader.Callback() {
                     @Override
-                    public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) {
+                    public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs,
+                                             long powerMaUs) {
                         final Uid u = getUidStatsLocked(mapUid(uid));
 
                         // Accumulate the total system and user time.
@@ -7978,7 +7989,7 @@
                             TimeUtils.formatDuration(userTimeUs / 1000, sb);
                             sb.append(" s=");
                             TimeUtils.formatDuration(systemTimeUs / 1000, sb);
-                            sb.append("\n");
+                            sb.append(" p=").append(powerMaUs / 1000).append("mAms\n");
                         }
 
                         if (numWakelocksF > 0) {
@@ -7994,11 +8005,13 @@
                             TimeUtils.formatDuration(userTimeUs / 1000, sb);
                             sb.append(" s=");
                             TimeUtils.formatDuration(systemTimeUs / 1000, sb);
+                            sb.append(" p=").append(powerMaUs / 1000).append("mAms");
                             Slog.d(TAG, sb.toString());
                         }
 
                         u.mUserCpuTime.addCountLocked(userTimeUs);
                         u.mSystemCpuTime.addCountLocked(systemTimeUs);
+                        u.mCpuPower.addCountLocked(powerMaUs);
 
                         // Add the cpu speeds to this UID. These are used as a ratio
                         // for computing the power this UID used.
@@ -9229,6 +9242,7 @@
 
             u.mUserCpuTime.readSummaryFromParcelLocked(in);
             u.mSystemCpuTime.readSummaryFromParcelLocked(in);
+            u.mCpuPower.readSummaryFromParcelLocked(in);
 
             int NSB = in.readInt();
             if (NSB > 100) {
@@ -9575,6 +9589,7 @@
 
             u.mUserCpuTime.writeSummaryFromParcelLocked(out);
             u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
+            u.mCpuPower.writeSummaryFromParcelLocked(out);
 
             out.writeInt(u.mSpeedBins.length);
             for (int i = 0; i < u.mSpeedBins.length; i++) {
diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
index 41efd2c..e2d366a 100644
--- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
+++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java
@@ -30,7 +30,7 @@
 /**
  * Reads /proc/uid_cputime/show_uid_stat which has the line format:
  *
- * uid: user_time_micro_seconds system_time_micro_seconds
+ * uid: user_time_micro_seconds system_time_micro_seconds power_in_milli-amp-micro_seconds
  *
  * This provides the time a UID's processes spent executing in user-space and kernel-space.
  * The file contains a monotonically increasing count of time for a single boot. This class
@@ -46,11 +46,18 @@
      * Callback interface for processing each line of the proc file.
      */
     public interface Callback {
-        void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs);
+        /**
+         * @param uid UID of the app
+         * @param userTimeUs time spent executing in user space in microseconds
+         * @param systemTimeUs time spent executing in kernel space in microseconds
+         * @param powerMaUs power consumed executing, in milli-ampere microseconds
+         */
+        void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs, long powerMaUs);
     }
 
     private SparseLongArray mLastUserTimeUs = new SparseLongArray();
     private SparseLongArray mLastSystemTimeUs = new SparseLongArray();
+    private SparseLongArray mLastPowerMaUs = new SparseLongArray();
     private long mLastTimeReadUs = 0;
 
     /**
@@ -70,50 +77,60 @@
                 final int uid = Integer.parseInt(uidStr.substring(0, uidStr.length() - 1), 10);
                 final long userTimeUs = Long.parseLong(splitter.next(), 10);
                 final long systemTimeUs = Long.parseLong(splitter.next(), 10);
+                final long powerMaUs = Long.parseLong(splitter.next(), 10) / 1000;
 
                 if (callback != null) {
                     long userTimeDeltaUs = userTimeUs;
                     long systemTimeDeltaUs = systemTimeUs;
+                    long powerDeltaMaUs = powerMaUs;
                     int index = mLastUserTimeUs.indexOfKey(uid);
                     if (index >= 0) {
                         userTimeDeltaUs -= mLastUserTimeUs.valueAt(index);
                         systemTimeDeltaUs -= mLastSystemTimeUs.valueAt(index);
+                        powerDeltaMaUs -= mLastPowerMaUs.valueAt(index);
 
                         final long timeDiffUs = nowUs - mLastTimeReadUs;
-                        if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0 ||
+                        if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0 || powerDeltaMaUs < 0 ||
                                 userTimeDeltaUs > timeDiffUs || systemTimeDeltaUs > timeDiffUs) {
-                            StringBuilder sb = new StringBuilder("Malformed cpu data!\n");
+                            StringBuilder sb = new StringBuilder("Malformed cpu data for UID=");
+                            sb.append(uid).append("!\n");
                             sb.append("Time between reads: ");
                             TimeUtils.formatDuration(timeDiffUs / 1000, sb);
-                            sb.append("ms\n");
+                            sb.append("\n");
                             sb.append("Previous times: u=");
                             TimeUtils.formatDuration(mLastUserTimeUs.valueAt(index) / 1000, sb);
-                            sb.append("ms s=");
+                            sb.append(" s=");
                             TimeUtils.formatDuration(mLastSystemTimeUs.valueAt(index) / 1000, sb);
-                            sb.append("ms\n");
+                            sb.append(" p=").append(mLastPowerMaUs.valueAt(index) / 1000);
+                            sb.append("mAms\n");
+
                             sb.append("Current times: u=");
                             TimeUtils.formatDuration(userTimeUs / 1000, sb);
-                            sb.append("ms s=");
+                            sb.append(" s=");
                             TimeUtils.formatDuration(systemTimeUs / 1000, sb);
-                            sb.append("ms\n");
-                            sb.append("Delta for UID=").append(uid).append(": u=");
+                            sb.append(" p=").append(powerMaUs / 1000);
+                            sb.append("mAms\n");
+                            sb.append("Delta: u=");
                             TimeUtils.formatDuration(userTimeDeltaUs / 1000, sb);
-                            sb.append("ms s=");
+                            sb.append(" s=");
                             TimeUtils.formatDuration(systemTimeDeltaUs / 1000, sb);
-                            sb.append("ms");
+                            sb.append(" p=").append(powerDeltaMaUs / 1000).append("mAms");
                             Slog.wtf(TAG, sb.toString());
 
                             userTimeDeltaUs = 0;
                             systemTimeDeltaUs = 0;
+                            powerDeltaMaUs = 0;
                         }
                     }
 
-                    if (userTimeDeltaUs != 0 || systemTimeDeltaUs != 0) {
-                        callback.onUidCpuTime(uid, userTimeDeltaUs, systemTimeDeltaUs);
+                    if (userTimeDeltaUs != 0 || systemTimeDeltaUs != 0 || powerDeltaMaUs != 0) {
+                        callback.onUidCpuTime(uid, userTimeDeltaUs, systemTimeDeltaUs,
+                                powerDeltaMaUs);
                     }
                 }
                 mLastUserTimeUs.put(uid, userTimeUs);
                 mLastSystemTimeUs.put(uid, systemTimeUs);
+                mLastPowerMaUs.put(uid, powerMaUs);
             }
         } catch (IOException e) {
             Slog.e(TAG, "Failed to read uid_cputime", e);
diff --git a/core/java/com/android/internal/widget/DrawingSpace.java b/core/java/com/android/internal/widget/DrawingSpace.java
new file mode 100644
index 0000000..b8222db
--- /dev/null
+++ b/core/java/com/android/internal/widget/DrawingSpace.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * Implementation of {@link android.widget.Space} that uses normal View drawing
+ * rather than a no-op. Useful for dialogs and other places where the base View
+ * class is too greedy when measured with AT_MOST.
+ */
+public final class DrawingSpace extends View {
+    public DrawingSpace(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    public DrawingSpace(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public DrawingSpace(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public DrawingSpace(Context context) {
+        this(context, null);
+    }
+
+    /**
+     * Compare to: {@link View#getDefaultSize(int, int)}
+     * <p>
+     * If mode is AT_MOST, return the child size instead of the parent size
+     * (unless it is too big).
+     */
+    private static int getDefaultSizeNonGreedy(int size, int measureSpec) {
+        int result = size;
+        int specMode = MeasureSpec.getMode(measureSpec);
+        int specSize = MeasureSpec.getSize(measureSpec);
+
+        switch (specMode) {
+            case MeasureSpec.UNSPECIFIED:
+                result = size;
+                break;
+            case MeasureSpec.AT_MOST:
+                result = Math.min(size, specSize);
+                break;
+            case MeasureSpec.EXACTLY:
+                result = specSize;
+                break;
+        }
+        return result;
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        setMeasuredDimension(
+                getDefaultSizeNonGreedy(getSuggestedMinimumWidth(), widthMeasureSpec),
+                getDefaultSizeNonGreedy(getSuggestedMinimumHeight(), heightMeasureSpec));
+    }
+}
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index f7cfe0e..db88962 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -20,9 +20,13 @@
 #include <sys/mount.h>
 #include <linux/fs.h>
 
+#include <list>
+#include <string>
+
 #include <fcntl.h>
 #include <grp.h>
 #include <inttypes.h>
+#include <mntent.h>
 #include <paths.h>
 #include <signal.h>
 #include <stdlib.h>
@@ -249,6 +253,34 @@
   }
 }
 
+static int UnmountTree(const char* path) {
+    size_t path_len = strlen(path);
+
+    FILE* fp = setmntent("/proc/mounts", "r");
+    if (fp == NULL) {
+        ALOGE("Error opening /proc/mounts: %s", strerror(errno));
+        return -errno;
+    }
+
+    // Some volumes can be stacked on each other, so force unmount in
+    // reverse order to give us the best chance of success.
+    std::list<std::string> toUnmount;
+    mntent* mentry;
+    while ((mentry = getmntent(fp)) != NULL) {
+        if (strncmp(mentry->mnt_dir, path, path_len) == 0) {
+            toUnmount.push_front(std::string(mentry->mnt_dir));
+        }
+    }
+    endmntent(fp);
+
+    for (auto path : toUnmount) {
+        if (umount2(path.c_str(), MNT_DETACH)) {
+            ALOGW("Failed to unmount %s: %s", path.c_str(), strerror(errno));
+        }
+    }
+    return 0;
+}
+
 // Create a private mount namespace and bind mount appropriate emulated
 // storage for the given user.
 static bool MountEmulatedStorage(uid_t uid, jint mount_mode,
@@ -262,7 +294,7 @@
     }
 
     // Unmount storage provided by root namespace and mount requested view
-    umount2("/storage", MNT_FORCE);
+    UnmountTree("/storage");
 
     String8 storageSource;
     if (mount_mode == MOUNT_EXTERNAL_DEFAULT) {
@@ -281,7 +313,7 @@
         return false;
     }
 
-    // Mount user-specific symlink helpers into place
+    // Mount user-specific symlink helper into place
     userid_t user_id = multiuser_get_user_id(uid);
     const String8 userSource(String8::format("/mnt/user/%d", user_id));
     if (fs_prepare_dir(userSource.string(), 0751, 0, 0) == -1) {
diff --git a/core/res/res/layout-land/time_picker_material.xml b/core/res/res/layout-land/time_picker_material.xml
index 2fa2054..2473e87 100644
--- a/core/res/res/layout-land/time_picker_material.xml
+++ b/core/res/res/layout-land/time_picker_material.xml
@@ -21,7 +21,7 @@
             android:layoutDirection="ltr">
 
     <!-- Provides a background for the time layout that extends into the button bar area. -->
-    <View
+    <com.android.internal.widget.DrawingSpace
         android:id="@+id/time_header"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
diff --git a/docs/html/training/material/drawables.jd b/docs/html/training/material/drawables.jd
index a2de8e9..c58075e 100644
--- a/docs/html/training/material/drawables.jd
+++ b/docs/html/training/material/drawables.jd
@@ -36,8 +36,9 @@
 resources (for example, <code>?android:attr/colorPrimary</code>). Usually, you create these assets
 only once and color them automatically to match your theme.</p>
 
-<p>You can apply a tint to {@link android.graphics.drawable.BitmapDrawable} or {@link
-android.graphics.drawable.NinePatchDrawable} objects with the {@code setTint()} method. You can
+<p>You can apply a tint to {@link android.graphics.drawable.BitmapDrawable}, {@link
+android.graphics.drawable.NinePatchDrawable} or {@link
+android.graphics.drawable.VectorDrawable} objects with the {@code setTint()} method. You can
 also set the tint color and mode in your layouts with the <code>android:tint</code> and
 <code>android:tintMode</code> attributes.</p>
 
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 6ba5626..51d0bf1 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -131,7 +131,7 @@
         }
 
         final boolean isService = isAssistantService();
-        if (isService || !isVoiceSessionRunning()) {
+        if (!isService || !isVoiceSessionRunning()) {
             showOrb();
             mView.postDelayed(mHideRunnable, isService
                     ? TIMEOUT_SERVICE
@@ -227,10 +227,6 @@
         mAssistUtils.launchVoiceAssistFromKeyguard();
     }
 
-    private boolean getVoiceInteractorSupportsAssistGesture() {
-        return mAssistUtils.activeServiceSupportsAssistGesture();
-    }
-
     public boolean canVoiceAssistBeLaunchedFromKeyguard() {
         return mAssistUtils.activeServiceSupportsLaunchFromKeyguard();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index cf0d670..c89a37d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1126,38 +1126,41 @@
     };
 
     private void animateKeyguardStatusBarOut() {
-        mKeyguardStatusBar.animate()
-                .alpha(0f)
-                .setStartDelay(mStatusBar.isKeyguardFadingAway()
-                        ? mStatusBar.getKeyguardFadingAwayDelay()
-                        : 0)
-                .setDuration(mStatusBar.isKeyguardFadingAway()
-                        ? mStatusBar.getKeyguardFadingAwayDuration() / 2
-                        : StackStateAnimator.ANIMATION_DURATION_STANDARD)
-                .setInterpolator(PhoneStatusBar.ALPHA_OUT)
-                .setUpdateListener(mStatusBarAnimateAlphaListener)
-                .withEndAction(mAnimateKeyguardStatusBarInvisibleEndRunnable)
-                .start();
+        ValueAnimator anim = ValueAnimator.ofFloat(mKeyguardStatusBar.getAlpha(), 0f);
+        anim.addUpdateListener(mStatusBarAnimateAlphaListener);
+        anim.setStartDelay(mStatusBar.isKeyguardFadingAway()
+                ? mStatusBar.getKeyguardFadingAwayDelay()
+                : 0);
+        anim.setDuration(mStatusBar.isKeyguardFadingAway()
+                ? mStatusBar.getKeyguardFadingAwayDuration() / 2
+                : StackStateAnimator.ANIMATION_DURATION_STANDARD);
+        anim.setInterpolator(mDozeAnimationInterpolator);
+        anim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mAnimateKeyguardStatusBarInvisibleEndRunnable.run();
+            }
+        });
+        anim.start();
     }
 
     private final ValueAnimator.AnimatorUpdateListener mStatusBarAnimateAlphaListener =
             new ValueAnimator.AnimatorUpdateListener() {
         @Override
         public void onAnimationUpdate(ValueAnimator animation) {
-            mKeyguardStatusBarAnimateAlpha = mKeyguardStatusBar.getAlpha();
+            mKeyguardStatusBarAnimateAlpha = (float) animation.getAnimatedValue();
+            updateHeaderKeyguardAlpha();
         }
     };
 
     private void animateKeyguardStatusBarIn(long duration) {
         mKeyguardStatusBar.setVisibility(View.VISIBLE);
         mKeyguardStatusBar.setAlpha(0f);
-        mKeyguardStatusBar.animate()
-                .alpha(1f)
-                .setStartDelay(0)
-                .setDuration(duration)
-                .setInterpolator(mDozeAnimationInterpolator)
-                .setUpdateListener(mStatusBarAnimateAlphaListener)
-                .start();
+        ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
+        anim.addUpdateListener(mStatusBarAnimateAlphaListener);
+        anim.setDuration(duration);
+        anim.setInterpolator(mDozeAnimationInterpolator);
+        anim.start();
     }
 
     private final Runnable mAnimateKeyguardBottomAreaInvisibleEndRunnable = new Runnable() {
@@ -1716,12 +1719,16 @@
         return alpha;
     }
 
-    private void updateHeaderKeyguard() {
+    private void updateHeaderKeyguardAlpha() {
         float alphaQsExpansion = 1 - Math.min(1, getQsExpansionFraction() * 2);
         mKeyguardStatusBar.setAlpha(Math.min(getKeyguardContentsAlpha(), alphaQsExpansion)
                 * mKeyguardStatusBarAnimateAlpha);
         mKeyguardStatusBar.setVisibility(mKeyguardStatusBar.getAlpha() != 0f
                 && !mDozing ? VISIBLE : INVISIBLE);
+    }
+
+    private void updateHeaderKeyguard() {
+        updateHeaderKeyguardAlpha();
         setQsTranslation(mQsExpansionHeight);
     }
 
@@ -1811,6 +1818,7 @@
                 || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) {
             mAfforanceHelper.animateHideLeftRightIcon();
         }
+        mNotificationStackScroller.onPanelTrackingStarted();
     }
 
     @Override
@@ -1820,6 +1828,7 @@
             mNotificationStackScroller.setOverScrolledPixels(
                     0.0f, true /* onTop */, true /* animate */);
         }
+        mNotificationStackScroller.onPanelTrackingStopped();
         if (expand && (mStatusBar.getBarState() == StatusBarState.KEYGUARD
                 || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED)) {
             if (!mHintAnimationRunning) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 39a06aa..9343172 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -834,8 +834,10 @@
             }
         } else if (!isFullyCollapsed() && !mTracking && !mClosing) {
             cancelHeightAnimator();
-            mClosing = true;
             notifyExpandingStarted();
+
+            // Set after notifyExpandingStarted, as notifyExpandingStarted resets the closing state.
+            mClosing = true;
             if (delayed) {
                 mNextCollapseSpeedUpFactor = speedUpFactor;
                 postDelayed(mFlingCollapseRunnable, 120);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index f98840b..7040864 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -163,6 +163,7 @@
     private boolean mChildrenUpdateRequested;
     private SpeedBumpView mSpeedBumpView;
     private boolean mIsExpansionChanging;
+    private boolean mPanelTracking;
     private boolean mExpandingNotification;
     private boolean mExpandedInThisMotion;
     private boolean mScrollingEnabled;
@@ -1513,7 +1514,7 @@
         }
         if (mExpandedInThisMotion) {
             return RUBBER_BAND_FACTOR_AFTER_EXPAND;
-        } else if (mIsExpansionChanging) {
+        } else if (mIsExpansionChanging || mPanelTracking) {
             return RUBBER_BAND_FACTOR_ON_PANEL_EXPAND;
         } else if (mScrolledToTopOnFirstDown) {
             return 1.0f;
@@ -1527,7 +1528,7 @@
      * overscroll view (e.g. expand QS).
      */
     private boolean isRubberbanded(boolean onTop) {
-        return !onTop || mExpandedInThisMotion || mIsExpansionChanging
+        return !onTop || mExpandedInThisMotion || mIsExpansionChanging || mPanelTracking
                 || !mScrolledToTopOnFirstDown;
     }
 
@@ -2249,6 +2250,13 @@
         }
     }
 
+    public void onPanelTrackingStarted() {
+        mPanelTracking = true;
+    }
+    public void onPanelTrackingStopped() {
+        mPanelTracking = false;
+    }
+
     public void resetScrollPosition() {
         mScroller.abortAnimation();
         mOwnScrollY = 0;
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index 45a7767..b4fa46d 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -1202,6 +1202,21 @@
         }
     }
 
+    private void enforceAdminUser() {
+        UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        final int callingUserId = UserHandle.getCallingUserId();
+        boolean isAdmin;
+        long token = Binder.clearCallingIdentity();
+        try {
+            isAdmin = um.getUserInfo(callingUserId).isAdmin();
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+        if (!isAdmin) {
+            throw new SecurityException("Only admin users can adopt sd cards");
+        }
+    }
+
     /**
      * Constructs a new MountService instance
      *
@@ -1537,6 +1552,7 @@
     @Override
     public void partitionPrivate(String diskId) {
         enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
+        enforceAdminUser();
         waitForReady();
 
         final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
@@ -1551,6 +1567,7 @@
     @Override
     public void partitionMixed(String diskId, int ratio) {
         enforcePermission(android.Manifest.permission.MOUNT_FORMAT_FILESYSTEMS);
+        enforceAdminUser();
         waitForReady();
 
         final CountDownLatch latch = findOrCreateDiskScanLatch(diskId);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 422b2aa..582ac33 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -742,7 +742,7 @@
                 if (item != null) {
                     // item is a reference to a style entry. Search for it.
                     item = mRenderResources.findResValue(item.getValue(), item.isFramework());
-
+                    item = mRenderResources.resolveResValue(item);
                     if (item instanceof StyleResourceValue) {
                         defStyleValues = (StyleResourceValue) item;
                     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java
index 8b8cc38..958b7aa 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/AppCompatActionBar.java
@@ -151,7 +151,7 @@
 
     @Override
     public void createMenuPopup() {
-        // it's hard to addd menus to appcompat's actionbar, since it'll use a lot of reflection.
+        // it's hard to add menus to appcompat's actionbar, since it'll use a lot of reflection.
         // so we skip it for now.
     }
 
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
index f6c2626..dae5509 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmGenerator.java
@@ -94,14 +94,8 @@
         ListIterator<Class<?>> iter = injectedClasses.listIterator();
         while (iter.hasNext()) {
             Class<?> clazz = iter.next();
-            try {
-                int i = 1;
-                while(i < 100) {
-                    iter.add(Class.forName(clazz.getName() + "$" + i));
-                    i++;
-                }
-            } catch (ClassNotFoundException ignored) {
-                // Expected.
+            for (Class<?> aClass : clazz.getDeclaredClasses()) {
+                iter.add(aClass);
             }
         }
         mInjectClasses = injectedClasses.toArray(new Class<?>[0]);