Merge "Always trigger a write if no pages are written" into nyc-mr1-dev
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index 3cf13d9..3a92b9e 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -36,8 +36,4 @@
 LOCAL_32_BIT_ONLY := true
 endif
 
-# get asserts to work
-APP_OPTIM := debug
-LOCAL_CFLAGS += -UNDEBUG
-
 include $(BUILD_EXECUTABLE)
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 4098772..ebcc9ff 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -588,7 +588,7 @@
         return false;
     }
 
-    bool hasAudio = false;
+    Animation::Part* partWithAudio = NULL;
     ZipEntryRO entry;
     char name[ANIM_ENTRY_NAME_MAX];
     while ((entry = zip->nextEntry(cookie)) != NULL) {
@@ -612,10 +612,10 @@
                             if (map) {
                                 Animation::Part& part(animation.parts.editItemAt(j));
                                 if (leaf == "audio.wav") {
-                                    hasAudio = true;
                                     // a part may have at most one audio file
                                     part.audioData = (uint8_t *)map->getDataPtr();
                                     part.audioLength = map->getDataLength();
+                                    partWithAudio = ∂
                                 } else if (leaf == "trim.txt") {
                                     part.trimData.setTo((char const*)map->getDataPtr(),
                                                         map->getDataLength());
@@ -666,9 +666,11 @@
     }
 
     // Create and initialize audioplay if there is a wav file in any of the animations.
-    if (hasAudio) {
+    if (partWithAudio != NULL) {
         ALOGD("found audio.wav, creating playback engine");
-        audioplay::create();
+        if (!audioplay::create(partWithAudio->audioData, partWithAudio->audioLength)) {
+            return false;
+        }
     }
 
     zip->endIteration(cookie);
@@ -904,7 +906,10 @@
     mLoadedFiles.add(animation->fileName);
 
     parseAnimationDesc(*animation);
-    preloadZip(*animation);
+    if (!preloadZip(*animation)) {
+        return NULL;
+    }
+
 
     mLoadedFiles.remove(fn);
     return animation;
diff --git a/cmds/bootanimation/audioplay.cpp b/cmds/bootanimation/audioplay.cpp
index e20ef0c..8a5c2c6 100644
--- a/cmds/bootanimation/audioplay.cpp
+++ b/cmds/bootanimation/audioplay.cpp
@@ -21,7 +21,6 @@
 
 #define CHATTY ALOGD
 
-#include <assert.h>
 #include <string.h>
 
 #include <utils/Log.h>
@@ -80,8 +79,6 @@
 void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) {
     (void)bq;
     (void)context;
-    assert(bq == bqPlayerBufferQueue);
-    assert(NULL == context);
     audioplay::setPlaying(false);
 }
 
@@ -90,39 +87,56 @@
 }
 
 // create the engine and output mix objects
-void createEngine() {
+bool createEngine() {
     SLresult result;
 
     // create engine
     result = slCreateEngine(&engineObject, 0, NULL, 0, NULL, NULL);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("slCreateEngine failed with result %d", result);
+        return false;
+    }
     (void)result;
 
     // realize the engine
     result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl engine Realize failed with result %d", result);
+        return false;
+    }
     (void)result;
 
     // get the engine interface, which is needed in order to create other objects
     result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl engine GetInterface failed with result %d", result);
+        return false;
+    }
     (void)result;
 
     // create output mix, with environmental reverb specified as a non-required interface
     const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB};
     const SLboolean req[1] = {SL_BOOLEAN_FALSE};
     result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 1, ids, req);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl engine CreateOutputMix failed with result %d", result);
+        return false;
+    }
     (void)result;
 
     // realize the output mix
     result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl outputMix Realize failed with result %d", result);
+        return false;
+    }
     (void)result;
+
+    return true;
 }
 
 // create buffer queue audio player
-void createBufferQueueAudioPlayer(const ChunkFormat* chunkFormat) {
+bool createBufferQueueAudioPlayer(const ChunkFormat* chunkFormat) {
     SLresult result;
 
     // configure audio source
@@ -148,83 +162,89 @@
     const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
     result = (*engineEngine)->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk,
             2, ids, req);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl CreateAudioPlayer failed with result %d", result);
+        return false;
+    }
     (void)result;
 
     // realize the player
     result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl player Realize failed with result %d", result);
+        return false;
+    }
     (void)result;
 
     // get the play interface
     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl player GetInterface failed with result %d", result);
+        return false;
+    }
     (void)result;
 
     // get the buffer queue interface
     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE,
             &bqPlayerBufferQueue);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl playberBufferQueue GetInterface failed with result %d", result);
+        return false;
+    }
     (void)result;
 
     // register callback on the buffer queue
     result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, NULL);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl bqPlayerBufferQueue RegisterCallback failed with result %d", result);
+        return false;
+    }
     (void)result;
 
-#if 0   // mute/solo is not supported for sources that are known to be mono, as this is
-    // get the mute/solo interface
-    result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_MUTESOLO, &bqPlayerMuteSolo);
-    assert(SL_RESULT_SUCCESS == result);
-    (void)result;
-#endif
-
     // get the volume interface
     result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
-    assert(SL_RESULT_SUCCESS == result);
+    if (result != SL_RESULT_SUCCESS) {
+        ALOGE("sl volume GetInterface failed with result %d", result);
+        return false;
+    }
     (void)result;
 
     // set the player's state to playing
     audioplay::setPlaying(true);
     CHATTY("Created buffer queue player: %p", bqPlayerBufferQueue);
+    return true;
 }
 
-} // namespace
-
-void create() {
-    createEngine();
-}
-
-bool playClip(const uint8_t* buf, int size) {
-    // Parse the WAV header
-    nextBuffer = buf;
-    nextSize = size;
-    const RiffWaveHeader* wavHeader = (const RiffWaveHeader*)buf;
-    if (nextSize < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) ||
+bool parseClipBuf(const uint8_t* clipBuf, int clipBufSize, const ChunkFormat** oChunkFormat,
+                  const uint8_t** oSoundBuf, unsigned* oSoundBufSize) {
+    *oSoundBuf = clipBuf;
+    *oSoundBufSize = clipBufSize;
+    *oChunkFormat = NULL;
+    const RiffWaveHeader* wavHeader = (const RiffWaveHeader*)*oSoundBuf;
+    if (*oSoundBufSize < sizeof(*wavHeader) || (wavHeader->riff_id != ID_RIFF) ||
         (wavHeader->wave_id != ID_WAVE)) {
         ALOGE("Error: audio file is not a riff/wave file\n");
         return false;
     }
-    nextBuffer += sizeof(*wavHeader);
-    nextSize -= sizeof(*wavHeader);
+    *oSoundBuf += sizeof(*wavHeader);
+    *oSoundBufSize -= sizeof(*wavHeader);
 
-    const ChunkFormat* chunkFormat = nullptr;
     while (true) {
-        const ChunkHeader* chunkHeader = (const ChunkHeader*)nextBuffer;
-        if (nextSize < sizeof(*chunkHeader)) {
+        const ChunkHeader* chunkHeader = (const ChunkHeader*)*oSoundBuf;
+        if (*oSoundBufSize < sizeof(*chunkHeader)) {
             ALOGE("EOF reading chunk headers");
             return false;
         }
 
-        nextBuffer += sizeof(*chunkHeader);
-        nextSize -= sizeof(*chunkHeader);
+        *oSoundBuf += sizeof(*chunkHeader);
+        *oSoundBufSize -= sizeof(*chunkHeader);
 
         bool endLoop = false;
         switch (chunkHeader->id) {
             case ID_FMT:
-                chunkFormat = (const ChunkFormat*)nextBuffer;
-                nextBuffer += chunkHeader->sz;
-                nextSize -= chunkHeader->sz;
+                *oChunkFormat = (const ChunkFormat*)*oSoundBuf;
+                *oSoundBuf += chunkHeader->sz;
+                *oSoundBufSize -= chunkHeader->sz;
                 break;
             case ID_DATA:
                 /* Stop looking for chunks */
@@ -232,27 +252,49 @@
                 break;
             default:
                 /* Unknown chunk, skip bytes */
-                nextBuffer += chunkHeader->sz;
-                nextSize -= chunkHeader->sz;
+                *oSoundBuf += chunkHeader->sz;
+                *oSoundBufSize -= chunkHeader->sz;
         }
         if (endLoop) {
             break;
         }
     }
 
-    if (!chunkFormat) {
+    if (*oChunkFormat == NULL) {
         ALOGE("format not found in WAV file");
         return false;
     }
+    return true;
+}
 
-    // If this is the first clip, create the buffer based on this WAV's header.
-    // We assume all future clips with be in the same format.
-    if (bqPlayerBufferQueue == nullptr) {
-        createBufferQueueAudioPlayer(chunkFormat);
+} // namespace
+
+bool create(const uint8_t* exampleClipBuf, int exampleClipBufSize) {
+    if (!createEngine()) {
+        return false;
     }
 
-    assert(bqPlayerBufferQueue != nullptr);
-    assert(buf != nullptr);
+    // Parse the example clip.
+    const ChunkFormat* chunkFormat;
+    const uint8_t* soundBuf;
+    unsigned soundBufSize;
+    if (!parseClipBuf(exampleClipBuf, exampleClipBufSize, &chunkFormat, &soundBuf, &soundBufSize)) {
+        return false;
+    }
+
+    // Initialize the BufferQueue based on this clip's format.
+    if (!createBufferQueueAudioPlayer(chunkFormat)) {
+        return false;
+    }
+    return true;
+}
+
+bool playClip(const uint8_t* buf, int size) {
+    // Parse the WAV header
+    const ChunkFormat* chunkFormat;
+    if (!parseClipBuf(buf, size, &chunkFormat, &nextBuffer, &nextSize)) {
+        return false;
+    }
 
     if (!hasPlayer()) {
         ALOGD("cannot play clip %p without a player", buf);
@@ -285,8 +327,6 @@
         // set the player's state
         result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay,
             isPlaying ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_STOPPED);
-        assert(SL_RESULT_SUCCESS == result);
-        (void)result;
     }
 
 }
diff --git a/cmds/bootanimation/audioplay.h b/cmds/bootanimation/audioplay.h
index bdc0a1c..0e5705af 100644
--- a/cmds/bootanimation/audioplay.h
+++ b/cmds/bootanimation/audioplay.h
@@ -22,10 +22,12 @@
 
 namespace audioplay {
 
-void create();
+// Initializes the engine with an example of the type of WAV clip to play.
+// All buffers passed to playClip are assumed to be in the same format.
+bool create(const uint8_t* exampleClipBuf, int exampleClipBufSize);
 
-// Play a WAV pointed to by buf.  All clips are assumed to be in the same format.
-// playClip should not be called while a clip is still playing.
+// Plays a WAV contained in buf.
+// Should not be called while a clip is still playing.
 bool playClip(const uint8_t* buf, int size);
 void setPlaying(bool isPlaying);
 void destroy();
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index dc33671..2a12ac8 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1315,7 +1315,7 @@
 
     /**
      * Retrieve the current minimum password quality for a particular admin or all admins that set
-     * retrictions on this user and its participating profiles. Restrictions on profiles that have
+     * restrictions on this user and its participating profiles. Restrictions on profiles that have
      * a separate challenge are not taken into account.
      *
      * <p>This method can be called on the {@link DevicePolicyManager} instance
@@ -1379,7 +1379,7 @@
 
     /**
      * Retrieve the current minimum password length for a particular admin or all admins that set
-     * retrictions on this user and its participating profiles. Restrictions on profiles that have
+     * restrictions on this user and its participating profiles. Restrictions on profiles that have
      * a separate challenge are not taken into account.
      *
      * <p>This method can be called on the {@link DevicePolicyManager} instance
@@ -1442,7 +1442,7 @@
 
     /**
      * Retrieve the current number of upper case letters required in the password
-     * for a particular admin or all admins that set retrictions on this user and
+     * for a particular admin or all admins that set restrictions on this user and
      * its participating profiles. Restrictions on profiles that have a separate challenge
      * are not taken into account.
      * This is the same value as set by
@@ -1511,7 +1511,7 @@
 
     /**
      * Retrieve the current number of lower case letters required in the password
-     * for a particular admin or all admins that set retrictions on this user
+     * for a particular admin or all admins that set restrictions on this user
      * and its participating profiles. Restrictions on profiles that have
      * a separate challenge are not taken into account.
      * This is the same value as set by
@@ -1580,7 +1580,7 @@
 
     /**
      * Retrieve the current number of letters required in the password
-     * for a particular admin or all admins that set retrictions on this user
+     * for a particular admin or all admins that set restrictions on this user
      * and its participating profiles. Restrictions on profiles that have
      * a separate challenge are not taken into account.
      * This is the same value as set by
@@ -1648,7 +1648,7 @@
 
     /**
      * Retrieve the current number of numerical digits required in the password
-     * for a particular admin or all admins that set retrictions on this user
+     * for a particular admin or all admins that set restrictions on this user
      * and its participating profiles. Restrictions on profiles that have
      * a separate challenge are not taken into account.
      * This is the same value as set by
@@ -1716,7 +1716,7 @@
 
     /**
      * Retrieve the current number of symbols required in the password
-     * for a particular admin or all admins that set retrictions on this user
+     * for a particular admin or all admins that set restrictions on this user
      * and its participating profiles. Restrictions on profiles that have
      * a separate challenge are not taken into account. This is the same value as
      * set by {@link #setPasswordMinimumSymbols(ComponentName, int)}
@@ -1783,7 +1783,7 @@
 
     /**
      * Retrieve the current number of non-letter characters required in the password
-     * for a particular admin or all admins that set retrictions on this user
+     * for a particular admin or all admins that set restrictions on this user
      * and its participating profiles. Restrictions on profiles that have
      * a separate challenge are not taken into account.
      * This is the same value as set by
@@ -1915,7 +1915,7 @@
 
     /**
      * Get the current password expiration time for a particular admin or all admins that set
-     * retrictions on this user and its participating profiles. Restrictions on profiles that have
+     * restrictions on this user and its participating profiles. Restrictions on profiles that have
      * a separate challenge are not taken into account. If admin is {@code null}, then a composite
      * of all expiration times is returned - which will be the minimum of all of them.
      *
@@ -1939,7 +1939,7 @@
 
     /**
      * Retrieve the current password history length for a particular admin or all admins that
-     * set retrictions on this user and its participating profiles. Restrictions on profiles that
+     * set restrictions on this user and its participating profiles. Restrictions on profiles that
      * have a separate challenge are not taken into account.
      *
      * <p>This method can be called on the {@link DevicePolicyManager} instance
@@ -2121,7 +2121,7 @@
 
     /**
      * Retrieve the current maximum number of login attempts that are allowed before the device
-     * or profile is wiped, for a particular admin or all admins that set retrictions on this user
+     * or profile is wiped, for a particular admin or all admins that set restrictions on this user
      * and its participating profiles. Restrictions on profiles that have a separate challenge are
      * not taken into account.
      *
@@ -2262,7 +2262,7 @@
 
     /**
      * Retrieve the current maximum time to unlock for a particular admin or all admins that set
-     * retrictions on this user and its participating profiles. Restrictions on profiles that have
+     * restrictions on this user and its participating profiles. Restrictions on profiles that have
      * a separate challenge are not taken into account.
      *
      * <p>This method can be called on the {@link DevicePolicyManager} instance
@@ -3348,7 +3348,7 @@
 
     /**
      * Determine whether or not features have been disabled in keyguard either by the calling
-     * admin, if specified, or all admins that set retrictions on this user and its participating
+     * admin, if specified, or all admins that set restrictions on this user and its participating
      * profiles. Restrictions on profiles that have a separate challenge are not taken into account.
      *
      * <p>This method can be called on the {@link DevicePolicyManager} instance
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index 80927f3..8d6d9ed 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -286,6 +286,11 @@
     }
 
     /** {@hide} */
+    public static File getReferenceProfile(String packageName) {
+        return buildPath(getDataDirectory(), "misc", "profiles", "ref", packageName);
+    }
+
+    /** {@hide} */
     public static File getDataProfilesDePackageDirectory(int userId, String packageName) {
         return buildPath(getDataProfilesDeDirectory(userId), packageName);
     }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index a64827a..e648114 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4215,25 +4215,25 @@
                     setAlpha(a.getFloat(attr, 1f));
                     break;
                 case com.android.internal.R.styleable.View_transformPivotX:
-                    setPivotX(a.getDimensionPixelOffset(attr, 0));
+                    setPivotX(a.getDimension(attr, 0));
                     break;
                 case com.android.internal.R.styleable.View_transformPivotY:
-                    setPivotY(a.getDimensionPixelOffset(attr, 0));
+                    setPivotY(a.getDimension(attr, 0));
                     break;
                 case com.android.internal.R.styleable.View_translationX:
-                    tx = a.getDimensionPixelOffset(attr, 0);
+                    tx = a.getDimension(attr, 0);
                     transformSet = true;
                     break;
                 case com.android.internal.R.styleable.View_translationY:
-                    ty = a.getDimensionPixelOffset(attr, 0);
+                    ty = a.getDimension(attr, 0);
                     transformSet = true;
                     break;
                 case com.android.internal.R.styleable.View_translationZ:
-                    tz = a.getDimensionPixelOffset(attr, 0);
+                    tz = a.getDimension(attr, 0);
                     transformSet = true;
                     break;
                 case com.android.internal.R.styleable.View_elevation:
-                    elevation = a.getDimensionPixelOffset(attr, 0);
+                    elevation = a.getDimension(attr, 0);
                     transformSet = true;
                     break;
                 case com.android.internal.R.styleable.View_rotation:
diff --git a/packages/SystemUI/res/layout/battery_detail.xml b/packages/SystemUI/res/layout/battery_detail.xml
index 1f24ab0..8abfcf6 100644
--- a/packages/SystemUI/res/layout/battery_detail.xml
+++ b/packages/SystemUI/res/layout/battery_detail.xml
@@ -25,7 +25,7 @@
         android:id="@+id/charge_and_estimation"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:paddingStart="72dp"
+        android:paddingStart="16dp"
         android:textAppearance="?android:attr/textAppearanceSmall"
         android:textColor="?android:attr/colorAccent" />
 
diff --git a/packages/SystemUI/res/layout/qs_detail_header.xml b/packages/SystemUI/res/layout/qs_detail_header.xml
index c062b6d..f6ca862 100644
--- a/packages/SystemUI/res/layout/qs_detail_header.xml
+++ b/packages/SystemUI/res/layout/qs_detail_header.xml
@@ -22,19 +22,9 @@
     android:background="@drawable/btn_borderless_rect"
     android:gravity="center">
 
-    <ImageView
-        android:id="@*android:id/up"
-        android:layout_width="56dp"
-        android:layout_height="56dp"
-        android:layout_marginEnd="16dp"
-        android:padding="16dp"
-        android:clickable="true"
-        android:background="?android:attr/selectableItemBackground"
-        android:contentDescription="@*android:string/action_bar_up_description"
-        android:src="?android:attr/homeAsUpIndicator" />
-
     <TextView
         android:id="@android:id/title"
+        android:paddingStart="16dp"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:layout_weight="1"
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index a40e5b7..c63be9c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -63,7 +63,6 @@
     private boolean mScanState;
     private boolean mClosingDetail;
     private boolean mFullyExpanded;
-    private View mQsDetailHeaderBack;
     private BaseStatusBarHeader mHeader;
     private boolean mTriggeredExpand;
     private int mOpenX;
@@ -92,7 +91,6 @@
         mDetailDoneButton = (TextView) findViewById(android.R.id.button1);
 
         mQsDetailHeader = findViewById(R.id.qs_detail_header);
-        mQsDetailHeaderBack = mQsDetailHeader.findViewById(com.android.internal.R.id.up);
         mQsDetailHeaderTitle = (TextView) mQsDetailHeader.findViewById(android.R.id.title);
         mQsDetailHeaderSwitch = (Switch) mQsDetailHeader.findViewById(android.R.id.toggle);
         mQsDetailHeaderProgress = (ImageView) findViewById(R.id.qs_detail_header_progress);
@@ -109,7 +107,6 @@
                 mQsPanel.closeDetail();
             }
         };
-        mQsDetailHeaderBack.setOnClickListener(doneListener);
         mDetailDoneButton.setOnClickListener(doneListener);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index f415ae5..0c9bfab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -338,11 +338,12 @@
 
     public void dump(PrintWriter pw) {
         int N = mStatusIcons.getChildCount();
-        pw.println("  system icons: " + N);
+        pw.println("  icon views: " + N);
         for (int i=0; i<N; i++) {
             StatusBarIconView ic = (StatusBarIconView) mStatusIcons.getChildAt(i);
             pw.println("    [" + i + "] icon=" + ic);
         }
+        super.dump(pw);
     }
 
     public void dispatchDemoCommand(String command, Bundle args) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
index 97b31f2..6821879 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
@@ -81,9 +81,9 @@
 
     public void dump(PrintWriter pw) {
         final int N = mSlots.size();
-        pw.println("Icon list:");
+        pw.println("  icon slots: " + N);
         for (int i=0; i<N; i++) {
-            pw.printf("  %2d: (%s) %s\n", i, mSlots.get(i), mIcons.get(i));
+            pw.printf("    %2d: (%s) %s\n", i, mSlots.get(i), mIcons.get(i));
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java
index cc0ffb0..1ea23bb 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerZenModePanel.java
@@ -54,7 +54,6 @@
         mHeaderSwitch = findViewById(R.id.tuner_zen_switch);
         mHeaderSwitch.setVisibility(View.VISIBLE);
         mHeaderSwitch.setOnClickListener(this);
-        mHeaderSwitch.findViewById(com.android.internal.R.id.up).setVisibility(View.GONE);
         ((TextView) mHeaderSwitch.findViewById(android.R.id.title)).setText(
                 R.string.quick_settings_dnd_label);
         mZenModePanel = (ZenModePanel) findViewById(R.id.zen_mode_panel);
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 01b3dc2..02c6472 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -213,9 +213,19 @@
         // Use the package manager install and install lock here for the OTA dex optimizer.
         PackageDexOptimizer optimizer = new OTADexoptPackageDexOptimizer(
                 collectingInstaller, mPackageManagerService.mInstallLock, mContext);
+        // Make sure that core apps are optimized according to their own "reason".
+        // If the core apps are not preopted in the B OTA, and REASON_AB_OTA is not speed
+        // (by default is speed-profile) they will be interepreted/JITed. This in itself is not a
+        // problem as we will end up doing profile guided compilation. However, some core apps may
+        // be loaded by system server which doesn't JIT and we need to make sure we don't
+        // interpret-only
+        int compilationReason = nextPackage.coreApp
+                ? PackageManagerService.REASON_CORE_APP
+                : PackageManagerService.REASON_AB_OTA;
+
         optimizer.performDexOpt(nextPackage, nextPackage.usesLibraryFiles,
                 null /* ISAs */, false /* checkProfiles */,
-                getCompilerFilterForReason(PackageManagerService.REASON_AB_OTA));
+                getCompilerFilterForReason(compilationReason));
 
         mCommandsForCurrentPackage = collectingConnection.commands;
         if (mCommandsForCurrentPackage.isEmpty()) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 5980715..78fa3a3 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -95,6 +95,7 @@
 import static com.android.server.pm.InstructionSets.getPrimaryInstructionSet;
 import static com.android.server.pm.PackageManagerServiceCompilerMapping.getCompilerFilterForReason;
 import static com.android.server.pm.PackageManagerServiceCompilerMapping.getFullCompilerFilter;
+import static com.android.server.pm.PackageManagerServiceCompilerMapping.getNonProfileGuidedCompilerFilter;
 import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_FAILURE;
 import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS;
 import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
@@ -2800,7 +2801,7 @@
                     }
                 }
 
-                int[] stats = performDexOpt(coreApps, false,
+                int[] stats = performDexOptUpgrade(coreApps, false,
                         getCompilerFilterForReason(REASON_CORE_APP));
 
                 final int elapsedTimeSeconds =
@@ -7324,7 +7325,7 @@
         }
 
         final long startTime = System.nanoTime();
-        final int[] stats = performDexOpt(pkgs, mIsPreNUpgrade /* showDialog */,
+        final int[] stats = performDexOptUpgrade(pkgs, mIsPreNUpgrade /* showDialog */,
                     getCompilerFilterForReason(causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT));
 
         final int elapsedTimeSeconds =
@@ -7343,7 +7344,7 @@
      * which are (in order) {@code numberOfPackagesOptimized}, {@code numberOfPackagesSkipped}
      * and {@code numberOfPackagesFailed}.
      */
-    private int[] performDexOpt(List<PackageParser.Package> pkgs, boolean showDialog,
+    private int[] performDexOptUpgrade(List<PackageParser.Package> pkgs, boolean showDialog,
             String compilerFilter) {
 
         int numberOfPackagesVisited = 0;
@@ -7377,6 +7378,19 @@
                 }
             }
 
+            // If the OTA updates a system app which was previously preopted to a non-preopted state
+            // the app might end up being verified at runtime. That's because by default the apps
+            // are verify-profile but for preopted apps there's no profile.
+            // Do a hacky check to ensure that if we have no profiles (a reasonable indication
+            // that before the OTA the app was preopted) the app gets compiled with a non-profile
+            // filter (by default interpret-only).
+            // Note that at this stage unused apps are already filtered.
+            if (isSystemApp(pkg) &&
+                    DexFile.isProfileGuidedCompilerFilter(compilerFilter) &&
+                    !Environment.getReferenceProfile(pkg.packageName).exists()) {
+                compilerFilter = getNonProfileGuidedCompilerFilter(compilerFilter);
+            }
+
             // checkProfiles is false to avoid merging profiles during boot which
             // might interfere with background compilation (b/28612421).
             // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index ca92b90..552803f 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -29,6 +29,7 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.UserHandle;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Slog;
 import android.view.KeyEvent;
@@ -942,6 +943,20 @@
                                 + " token=" + tok.token);
             }
             pw.println("  mCurrentUserId=" + mCurrentUserId);
+            pw.println("  mIcons=");
+            for (String slot : mIcons.keySet()) {
+                pw.println("    ");
+                pw.print(slot);
+                pw.print(" -> ");
+                final StatusBarIcon icon = mIcons.get(slot);
+                pw.print(icon);
+                if (!TextUtils.isEmpty(icon.contentDescription)) {
+                    pw.print(" \"");
+                    pw.print(icon.contentDescription);
+                    pw.print("\"");
+                }
+                pw.println();
+            }
         }
     }
 }