Merge "Update the rowBytes when reconfiguring to match the new imageInfo." into mnc-dev
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index 6173832..9277f9b 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.os.Build;
+import android.view.View;
 
 /**
  * Log all the things.
@@ -33,6 +34,10 @@
     public static final int ACTION_BAN_APP_NOTES = 146;
     public static final int NOTIFICATION_ZEN_MODE_EVENT_RULE = 147;
     public static final int ACTION_DISMISS_ALL_NOTES = 148;
+    public static final int QS_DND_DETAILS = 149;
+    public static final int QS_BLUETOOTH_DETAILS = 150;
+    public static final int QS_CAST_DETAILS = 151;
+    public static final int QS_WIFI_DETAILS = 152;
 
     public static void visible(Context context, int category) throws IllegalArgumentException {
         if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
@@ -41,13 +46,27 @@
         EventLogTags.writeSysuiViewVisibility(category, 100);
     }
 
-    public static void hidden(Context context, int category) {
+    public static void hidden(Context context, int category) throws IllegalArgumentException {
         if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
             throw new IllegalArgumentException("Must define metric category");
         }
         EventLogTags.writeSysuiViewVisibility(category, 0);
     }
 
+    public static void visibility(Context context, int category, boolean visibile)
+            throws IllegalArgumentException {
+        if (visibile) {
+            visible(context, category);
+        } else {
+            hidden(context, category);
+        }
+    }
+
+    public static void visibility(Context context, int category, int vis)
+            throws IllegalArgumentException {
+        visibility(context, category, vis == View.VISIBLE);
+    }
+
     public static void action(Context context, int category) {
         action(context, category, "");
     }
diff --git a/graphics/java/android/graphics/Atlas.java b/graphics/java/android/graphics/Atlas.java
index 39a5a53..e0a5345 100644
--- a/graphics/java/android/graphics/Atlas.java
+++ b/graphics/java/android/graphics/Atlas.java
@@ -21,10 +21,12 @@
  */
 public class Atlas {
     /**
-     * This flag indicates whether the packing algorithm will attempt
-     * to rotate entries to make them fit better in the atlas.
+     * WARNING: These flag values are part of the on-disk configuration information,
+     * do not change their values.
      */
-    public static final int FLAG_ALLOW_ROTATIONS = 0x1;
+
+    /** DELETED: FLAG_ROTATION = 0x01 */
+
     /**
      * This flag indicates whether the packing algorithm should leave
      * an empty 1 pixel wide border around each bitmap. This border can
@@ -52,9 +54,7 @@
 
     /**
      * Represents a bitmap packed in the atlas. Each entry has a location in
-     * pixels in the atlas and a rotation flag. If the entry was rotated, the
-     * bitmap must be rotated by 90 degrees (in either direction as long as
-     * the origin remains the same) before being rendered into the atlas.
+     * pixels in the atlas and a rotation flag.
      */
     public static class Entry {
         /**
@@ -65,11 +65,6 @@
          * Location, in pixels, of the bitmap on the Y axis in the atlas.
          */
         public int y;
-
-        /**
-         * If true, the bitmap must be rotated 90 degrees in the atlas.
-         */
-        public boolean rotated;
     }
 
     private final Policy mPolicy;
@@ -239,7 +234,6 @@
 
         private final SplitDecision mSplitDecision;
 
-        private final boolean mAllowRotation;
         private final int mPadding;
 
         /**
@@ -263,7 +257,6 @@
         }
 
         SlicePolicy(int width, int height, int flags, SplitDecision splitDecision) {
-            mAllowRotation = (flags & FLAG_ALLOW_ROTATIONS) != 0;
             mPadding = (flags & FLAG_ADD_PADDING) != 0 ? 1 : 0;
 
             // The entire atlas is empty at first, minus padding
@@ -360,26 +353,9 @@
          *
          * @return True if the rectangle was packed in the atlas, false otherwise
          */
-        @SuppressWarnings("SuspiciousNameCombination")
         private boolean insert(Cell cell, Cell prev, int width, int height, Entry entry) {
-            boolean rotated = false;
-
-            // If the rectangle doesn't fit we'll try to rotate it
-            // if possible before giving up
             if (cell.width < width || cell.height < height) {
-                if (mAllowRotation) {
-                    if (cell.width < height || cell.height < width) {
-                        return false;
-                    }
-
-                    // Rotate the rectangle
-                    int temp = width;
-                    width = height;
-                    height = temp;
-                    rotated = true;
-                } else {
-                    return false;
-                }
+                return false;
             }
 
             // Remaining free space after packing the rectangle
@@ -433,7 +409,6 @@
             // Return the location and rotation of the packed rectangle
             entry.x = cell.x;
             entry.y = cell.y;
-            entry.rotated = rotated;
 
             return true;
         }
diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp
index 882826e..2889d2f 100644
--- a/libs/hwui/AssetAtlas.cpp
+++ b/libs/hwui/AssetAtlas.cpp
@@ -112,9 +112,6 @@
     Texture* const mDelegate;
 }; // struct DelegateTexture
 
-/**
- * TODO: This method does not take the rotation flag into account
- */
 void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) {
     const float width = float(mTexture->width);
     const float height = float(mTexture->height);
@@ -128,7 +125,6 @@
         // pointers on 64 bit architectures.
         const int x = static_cast<int>(map[i++]);
         const int y = static_cast<int>(map[i++]);
-        bool rotated = map[i++] > 0;
 
         // Bitmaps should never be null, we're just extra paranoid
         if (!pixelRef) continue;
@@ -142,7 +138,7 @@
         texture->width = pixelRef->info().width();
         texture->height = pixelRef->info().height();
 
-        Entry* entry = new Entry(pixelRef, x, y, rotated, texture, mapper, *this);
+        Entry* entry = new Entry(pixelRef, texture, mapper, *this);
         texture->uvMapper = &entry->uvMapper;
 
         mEntries.add(entry->pixelRef, entry);
diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h
index 17c5281..f1cd0b4 100644
--- a/libs/hwui/AssetAtlas.h
+++ b/libs/hwui/AssetAtlas.h
@@ -45,8 +45,8 @@
 class AssetAtlas {
 public:
     /**
-     * Entry representing the position and rotation of a
-     * bitmap inside the atlas.
+     * Entry representing the texture and uvMapper of a PixelRef in the
+     * atlas
      */
     class Entry {
     public:
@@ -78,30 +78,15 @@
         SkPixelRef* pixelRef;
 
         /**
-         * Location of the bitmap inside the atlas, in pixels.
-         */
-        int x;
-        int y;
-
-        /**
-         * If set, the bitmap is rotated 90 degrees (clockwise)
-         * inside the atlas.
-         */
-        bool rotated;
-
-        /**
          * Atlas this entry belongs to.
          */
         const AssetAtlas& atlas;
 
-        Entry(SkPixelRef* pixelRef, int x, int y, bool rotated,
-                    Texture* texture, const UvMapper& mapper, const AssetAtlas& atlas)
+        Entry(SkPixelRef* pixelRef, Texture* texture, const UvMapper& mapper,
+                    const AssetAtlas& atlas)
                 : texture(texture)
                 , uvMapper(mapper)
                 , pixelRef(pixelRef)
-                , x(x)
-                , y(y)
-                , rotated(rotated)
                 , atlas(atlas) {
         }
 
@@ -120,8 +105,7 @@
      * Initializes the atlas with the specified buffer and
      * map. The buffer is a gralloc'd texture that will be
      * used as an EGLImage. The map is a list of SkBitmap*
-     * and their (x, y) positions as well as their rotation
-     * flags.
+     * and their (x, y) positions
      *
      * This method returns immediately if the atlas is already
      * initialized. To re-initialize the atlas, you must
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index b5c1ca8..f352849 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -33,6 +33,7 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile.DetailAdapter;
@@ -182,8 +183,11 @@
     public void setExpanded(boolean expanded) {
         if (mExpanded == expanded) return;
         mExpanded = expanded;
+        MetricsLogger.visibility(mContext, MetricsLogger.QS_PANEL, mExpanded);
         if (!mExpanded) {
             closeDetail();
+        } else {
+            logTiles();
         }
     }
 
@@ -365,9 +369,11 @@
             mDetailContent.removeAllViews();
             mDetail.bringToFront();
             mDetailContent.addView(r.detailView);
+            MetricsLogger.visible(mContext, detailAdapter.getMetricsCategory());
             setDetailRecord(r);
             listener = mHideGridContentWhenDone;
         } else {
+            MetricsLogger.hidden(mContext, mDetailRecord.detailAdapter.getMetricsCategory());
             mClosingDetail = true;
             setGridContentVisibility(true);
             listener = mTeardownDetailWhenDone;
@@ -387,9 +393,21 @@
             }
         }
         mBrightnessView.setVisibility(newVis);
+        if (mGridContentVisible != visible) {
+            MetricsLogger.visibility(mContext, MetricsLogger.QS_PANEL, newVis);
+        }
         mGridContentVisible = visible;
     }
 
+    private void logTiles() {
+        for (int i = 0; i < mRecords.size(); i++) {
+            TileRecord tileRecord = mRecords.get(i);
+            if (tileRecord.tile.getState().visible) {
+                MetricsLogger.visible(mContext, tileRecord.tile.getMetricsCategory());
+            }
+        }
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         final int width = MeasureSpec.getSize(widthMeasureSpec);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
index b9574dc..452fd44 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTile.java
@@ -29,6 +29,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.qs.QSTile.State;
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.CastController;
@@ -66,9 +67,17 @@
     private boolean mAnnounceNextStateChange;
 
     abstract protected TState newTileState();
-    abstract protected void handleClick();
     abstract protected void handleUpdateState(TState state, Object arg);
 
+    /**
+     * Declare the category of this tile.
+     *
+     * Categories are defined in {@link com.android.internal.logging.MetricsLogger}
+     * or if there is no relevant existing category you may define one in
+     * {@link com.android.systemui.qs.QSTile}.
+     */
+    abstract public int getMetricsCategory();
+
     protected QSTile(Host host) {
         mHost = host;
         mContext = host.getContext();
@@ -97,6 +106,7 @@
         View createDetailView(Context context, View convertView, ViewGroup parent);
         Intent getSettingsIntent();
         void setToggleState(boolean state);
+        int getMetricsCategory();
     }
 
     // safe to call from any thread
@@ -160,6 +170,10 @@
         handleRefreshState(null);
     }
 
+    protected void handleClick() {
+        MetricsLogger.action(mContext, getMetricsCategory(), getMetricsPackage());
+    };
+
     protected void handleSecondaryClick() {
         // optional
     }
@@ -168,6 +182,10 @@
         // optional
     }
 
+    protected String getMetricsPackage() {
+        return "";
+    }
+
     protected void handleRefreshState(Object arg) {
         handleUpdateState(mTmpState, arg);
         final boolean changed = mTmpState.copyTo(mState);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index 2bc31fc..6744154 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -23,6 +23,7 @@
 import android.net.ConnectivityManager;
 import android.provider.Settings.Global;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
 import com.android.systemui.qs.GlobalSetting;
 import com.android.systemui.qs.QSTile;
@@ -55,6 +56,7 @@
 
     @Override
     public void handleClick() {
+        super.handleClick();
         setEnabled(!mState.value);
         mEnable.setAllowAnimation(true);
         mDisable.setAllowAnimation(true);
@@ -85,6 +87,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_AIRPLANEMODE;
+    }
+
+    @Override
     protected String composeChangeAnnouncement() {
         if (mState.value) {
             return mContext.getString(R.string.accessibility_quick_settings_airplane_changed_on);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index b42b5f6..8eb624f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -25,6 +25,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSDetailItems;
@@ -74,6 +75,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         final boolean isEnabled = (Boolean)mState.value;
         mController.setBluetoothEnabled(!isEnabled);
     }
@@ -132,6 +134,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_BLUETOOTH;
+    }
+
+    @Override
     protected String composeChangeAnnouncement() {
         if (mState.value) {
             return mContext.getString(R.string.accessibility_quick_settings_bluetooth_changed_on);
@@ -182,6 +189,11 @@
         }
 
         @Override
+        public int getMetricsCategory() {
+            return MetricsLogger.QS_BLUETOOTH_DETAILS;
+        }
+
+        @Override
         public View createDetailView(Context context, View convertView, ViewGroup parent) {
             mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
             mItems.setTagSuffix("Bluetooth");
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
index 5bf6fb5..a3d7bcc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CastTile.java
@@ -24,6 +24,7 @@
 import android.view.View.OnAttachStateChangeListener;
 import android.view.ViewGroup;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSDetailItems;
 import com.android.systemui.qs.QSDetailItems.Item;
@@ -85,6 +86,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         showDetail(true);
     }
 
@@ -113,6 +115,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_CAST;
+    }
+
+    @Override
     protected String composeChangeAnnouncement() {
         if (!mState.value) {
             // We only announce when it's turned off to avoid vocal overflow.
@@ -164,6 +171,11 @@
         }
 
         @Override
+        public int getMetricsCategory() {
+            return MetricsLogger.QS_CAST_DETAILS;
+        }
+
+        @Override
         public View createDetailView(Context context, View convertView, ViewGroup parent) {
             mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
             mItems.setTagSuffix("Cast");
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 30f92b9..0026141 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -24,6 +24,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.qs.QSTileView;
@@ -75,6 +76,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         if (mDataController.isMobileDataSupported()) {
             showDetail(true);
         } else {
@@ -118,6 +120,11 @@
                 state.label);
     }
 
+    @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_CELLULAR;
+    }
+
     // Remove the period from the network name
     public static String removeTrailingPeriod(String string) {
         if (string == null) return null;
@@ -227,6 +234,11 @@
         }
 
         @Override
+        public int getMetricsCategory() {
+            return MetricsLogger.QS_DATAUSAGEDETAIL;
+        }
+
+        @Override
         public View createDetailView(Context context, View convertView, ViewGroup parent) {
             final DataUsageDetailView v = (DataUsageDetailView) (convertView != null
                     ? convertView
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 4a33f55..6fa094e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -18,6 +18,7 @@
 
 import android.provider.Settings.Secure;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
@@ -86,6 +87,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         mSetting.setValue(mState.value ? 0 : 1);
         mEnable.setAllowAnimation(true);
         mDisable.setAllowAnimation(true);
@@ -115,6 +117,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_COLORINVERSION;
+    }
+
+    @Override
     protected String composeChangeAnnouncement() {
         if (mState.value) {
             return mContext.getString(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 5145bc7..e708a72 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -29,6 +29,7 @@
 import android.view.View.OnAttachStateChangeListener;
 import android.view.ViewGroup;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
@@ -88,6 +89,7 @@
 
     @Override
     public void handleClick() {
+        super.handleClick();
         if (mState.value) {
             mController.setZen(Global.ZEN_MODE_OFF, null, TAG);
         } else {
@@ -135,6 +137,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_DND;
+    }
+
+    @Override
     protected String composeChangeAnnouncement() {
         if (mState.value) {
             return mContext.getString(R.string.accessibility_quick_settings_dnd_changed_on);
@@ -209,6 +216,11 @@
         }
 
         @Override
+        public int getMetricsCategory() {
+            return MetricsLogger.QS_DND_DETAILS;
+        }
+
+        @Override
         public View createDetailView(Context context, View convertView, ViewGroup parent) {
             final ZenModePanel zmp = convertView != null ? (ZenModePanel) convertView
                     : (ZenModePanel) LayoutInflater.from(context).inflate(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
index cb78deb..a1f3cde 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FlashlightTile.java
@@ -18,6 +18,7 @@
 
 import android.app.ActivityManager;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.FlashlightController;
@@ -59,6 +60,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         if (ActivityManager.isUserAMonkey()) {
             return;
         }
@@ -84,6 +86,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_FLASHLIGHT;
+    }
+
+    @Override
     protected String composeChangeAnnouncement() {
         if (mState.value) {
             return mContext.getString(R.string.accessibility_quick_settings_flashlight_changed_on);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 6063f80..b864ff4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.Intent;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.qs.UsageTracker;
@@ -68,6 +69,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         final boolean isEnabled = (Boolean) mState.value;
         mController.setHotspotEnabled(!isEnabled);
         mEnable.setAllowAnimation(true);
@@ -97,6 +99,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_HOTSPOT;
+    }
+
+    @Override
     protected String composeChangeAnnouncement() {
         if (mState.value) {
             return mContext.getString(R.string.accessibility_quick_settings_hotspot_changed_on);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
index 2736530..20b5f04 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/IntentTile.java
@@ -29,6 +29,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.qs.QSTile;
 
 import java.util.Arrays;
@@ -42,6 +43,7 @@
     private PendingIntent mOnLongClick;
     private String mOnLongClickUri;
     private int mCurrentUserId;
+    private String mIntentPackage;
 
     private IntentTile(Host host, String action) {
         super(host);
@@ -82,6 +84,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         sendIntent("click", mOnClick, mOnClickUri);
     }
 
@@ -133,6 +136,17 @@
         mOnClickUri = intent.getStringExtra("onClickUri");
         mOnLongClick = intent.getParcelableExtra("onLongClick");
         mOnLongClickUri = intent.getStringExtra("onLongClickUri");
+        mIntentPackage = intent.getStringExtra("package");
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_INTENT;
+    }
+
+    @Override
+    protected String getMetricsPackage() {
+        return mIntentPackage == null ? "" : mIntentPackage;
     }
 
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index 11ec722..ab22ada 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.tiles;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
@@ -58,6 +59,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         final boolean wasEnabled = (Boolean) mState.value;
         mController.setLocationEnabled(!wasEnabled);
         mEnable.setAllowAnimation(true);
@@ -87,6 +89,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_LOCATION;
+    }
+
+    @Override
     protected String composeChangeAnnouncement() {
         if (mState.value) {
             return mContext.getString(R.string.accessibility_quick_settings_location_changed_on);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
index f46b9a6..7e3fe76 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RotationLockTile.java
@@ -18,6 +18,7 @@
 
 import android.content.res.Configuration;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.statusbar.policy.RotationLockController;
@@ -58,6 +59,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         if (mController == null) return;
         final boolean newState = !mState.value;
         mController.setRotationLocked(newState);
@@ -92,6 +94,11 @@
                 R.string.accessibility_rotation_lock_off);
     }
 
+    @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_ROTATIONLOCK;
+    }
+
     /**
      * Get the correct accessibility string based on the state
      *
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index d589366..228c293 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -26,6 +26,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.settingslib.wifi.AccessPoint;
 import com.android.systemui.R;
 import com.android.systemui.qs.QSDetailItems;
@@ -93,6 +94,7 @@
 
     @Override
     protected void handleClick() {
+        super.handleClick();
         mState.copyTo(mStateBeforeClick);
         mController.setWifiEnabled(!mState.enabled);
     }
@@ -159,6 +161,11 @@
     }
 
     @Override
+    public int getMetricsCategory() {
+        return MetricsLogger.QS_WIFI;
+    }
+
+    @Override
     protected boolean shouldAnnouncementBeDelayed() {
         return mStateBeforeClick.enabled == mState.enabled;
     }
@@ -274,6 +281,11 @@
         }
 
         @Override
+        public int getMetricsCategory() {
+            return MetricsLogger.QS_WIFI_DETAILS;
+        }
+
+        @Override
         public View createDetailView(Context context, View convertView, ViewGroup parent) {
             if (DEBUG) Log.d(TAG, "createDetailView convertView=" + (convertView != null));
             mAccessPoints = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 194bcfa..ad27c6e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -43,6 +43,7 @@
 import android.view.ViewGroup;
 import android.widget.BaseAdapter;
 
+import com.android.internal.logging.MetricsLogger;
 import com.android.internal.util.UserIcons;
 import com.android.systemui.BitmapHelper;
 import com.android.systemui.GuestResumeSessionReceiver;
@@ -548,6 +549,11 @@
         @Override
         public void setToggleState(boolean state) {
         }
+
+        @Override
+        public int getMetricsCategory() {
+            return MetricsLogger.QS_USERDETAIL;
+        }
     };
 
     private final KeyguardMonitor.Callback mCallback = new KeyguardMonitor.Callback() {
diff --git a/services/core/java/com/android/server/AssetAtlasService.java b/services/core/java/com/android/server/AssetAtlasService.java
index 26f4232..ebc810f 100644
--- a/services/core/java/com/android/server/AssetAtlasService.java
+++ b/services/core/java/com/android/server/AssetAtlasService.java
@@ -119,7 +119,6 @@
     // long0: SkBitmap*, the native bitmap object
     // long1: x position
     // long2: y position
-    // long3: rotated, 1 if the bitmap must be rotated, 0 otherwise
     private long[] mAtlasMap;
 
     /**
@@ -236,7 +235,7 @@
         /**
          * Renders a list of bitmaps into the atlas. The position of each bitmap
          * was decided by the packing algorithm and will be honored by this
-         * method. If need be this method will also rotate bitmaps.
+         * method.
          *
          * @param buffer The buffer to render the atlas entries into
          * @param atlas The atlas to pack the bitmaps into
@@ -280,16 +279,11 @@
 
                     canvas.save();
                     canvas.translate(entry.x, entry.y);
-                    if (entry.rotated) {
-                        canvas.translate(bitmap.getHeight(), 0.0f);
-                        canvas.rotate(90.0f);
-                    }
                     canvas.drawBitmap(bitmap, 0.0f, 0.0f, null);
                     canvas.restore();
                     atlasMap[mapIndex++] = bitmap.refSkPixelRef();
                     atlasMap[mapIndex++] = entry.x;
                     atlasMap[mapIndex++] = entry.y;
-                    atlasMap[mapIndex++] = entry.rotated ? 1 : 0;
                 }
             }
 
diff --git a/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
index dd823ae..b54f9be 100644
--- a/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
+++ b/tests/Compatibility/src/com/android/compatibilitytest/AppCompatibility.java
@@ -30,6 +30,7 @@
 
 import junit.framework.Assert;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
@@ -102,7 +103,11 @@
             // otherwise raise an
             // exception with the first error encountered.
             assertNull(getStackTrace(err), err);
-            assertTrue("App crashed after launch.", processStillUp(packageName));
+            try {
+                assertTrue("App crashed after launch.", processStillUp(packageName));
+            } finally {
+                returnHome();
+            }
         } else {
             Log.d(TAG, "Missing argument, use " + PACKAGE_TO_LAUNCH +
                     " to specify the package to launch");
@@ -138,6 +143,19 @@
         }
     }
 
+    private void returnHome() {
+        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
+        homeIntent.addCategory(Intent.CATEGORY_HOME);
+        homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        // Send the "home" intent and wait 2 seconds for us to get there
+        mContext.startActivity(homeIntent);
+        try {
+            Thread.sleep(mWorkspaceLaunchTimeout);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+    }
+
     /**
      * Launches and activity and queries for errors.
      *
@@ -150,9 +168,6 @@
         // the recommended way to see if this is a tv or not.
         boolean isleanback = !mPackageManager.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN)
             && !mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
-        Intent homeIntent = new Intent(Intent.ACTION_MAIN);
-        homeIntent.addCategory(Intent.CATEGORY_HOME);
-        homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         Intent intent;
         if (isleanback) {
             Log.d(TAG, "Leanback and relax! " + packageName);
@@ -173,14 +188,6 @@
             // ignore
         }
 
-        // Send the "home" intent and wait 2 seconds for us to get there
-        mContext.startActivity(homeIntent);
-        try {
-            Thread.sleep(mWorkspaceLaunchTimeout);
-        } catch (InterruptedException e) {
-            // ignore
-        }
-
         // See if there are any errors. We wait until down here to give ANRs as
         // much time as
         // possible to occur.
@@ -198,6 +205,12 @@
         return null;
     }
 
+    private boolean ensureForegroundActivity(RunningAppProcessInfo info) {
+        Log.d(TAG, String.format("ensureForegroundActivity: proc=%s, pid=%d, state=%d",
+                info.processName, info.pid, info.processState));
+        return info.processState == ActivityManager.PROCESS_STATE_TOP;
+    }
+
     /**
      * Determine if a given package is still running.
      *
@@ -207,19 +220,32 @@
     private boolean processStillUp(String packageName) {
         String processName = getProcessName(packageName);
         List<RunningAppProcessInfo> runningApps = mActivityManager.getRunningAppProcesses();
+        List<RunningAppProcessInfo> relatedProcs = new ArrayList<>();
         for (RunningAppProcessInfo app : runningApps) {
             if (app.processName.equalsIgnoreCase(processName)) {
-                Log.d(TAG, "Found process " + app.processName);
+                if (!ensureForegroundActivity(app)) {
+                    Log.w(TAG, "Found process but it's not top activity.");
+                    return false;
+                }
                 return true;
             }
             for (String relatedPackage : app.pkgList) {
-                if (relatedPackage.equalsIgnoreCase(processName)) {
-                    Log.d(TAG, "Found process " + app.processName);
-                    return true;
+                if (relatedPackage.equalsIgnoreCase(packageName)) {
+                    relatedProcs.add(app);
                 }
             }
         }
-        Log.d(TAG, "Failed to find process " + processName + " with package name "
+        // now that we are here, we've found no RAPI's directly matching processName, but
+        // potentially a List of them with one of related packages being processName
+        if (!relatedProcs.isEmpty()) {
+            for (RunningAppProcessInfo app : relatedProcs) {
+                if (ensureForegroundActivity(app)) {
+                    return true;
+                }
+            }
+            Log.w(TAG, "Found related processes, but none has top activity.");
+        }
+        Log.w(TAG, "Failed to find process " + processName + " with package name "
                 + packageName);
         return false;
     }