Creating landscape and portrait device profiles at app initialization

Change-Id: Ide9d007adc36b348e19b05cdf49e87f8b02db60e
diff --git a/src/com/android/launcher3/AlphabeticalAppsList.java b/src/com/android/launcher3/AlphabeticalAppsList.java
index 808bddb..623e4aa 100644
--- a/src/com/android/launcher3/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/AlphabeticalAppsList.java
@@ -219,7 +219,7 @@
     public void setNumAppsPerRow(int numAppsPerRow, int numPredictedAppsPerRow) {
         // Update the merge algorithm
         DeviceProfile grid = mLauncher.getDeviceProfile();
-        if (grid.isPhone()) {
+        if (grid.isPhone) {
             mMergeAlgorithm = new PhoneMergeAlgorithm((int) Math.ceil(numAppsPerRow / 2f),
                     MIN_ROWS_IN_MERGED_SECTION_PHONE, MAX_NUM_MERGES_PHONE);
         } else {
diff --git a/src/com/android/launcher3/AppsContainerView.java b/src/com/android/launcher3/AppsContainerView.java
index 9ff3bfa..3bfe26b 100644
--- a/src/com/android/launcher3/AppsContainerView.java
+++ b/src/com/android/launcher3/AppsContainerView.java
@@ -453,7 +453,7 @@
 
         // Update the apps recycler view, inset it by the container inset as well
         DeviceProfile grid = mLauncher.getDeviceProfile();
-        int startMargin = grid.isPhone() ? mContentMarginStart : 0;
+        int startMargin = grid.isPhone ? mContentMarginStart : 0;
         int inset = mFixedBounds.isEmpty() ? mContainerInset : mFixedBoundsContainerInset;
         if (isRtl) {
             mAppsRecyclerView.setPadding(inset + mAppsRecyclerView.getScrollbarWidth(), inset,
diff --git a/src/com/android/launcher3/AppsGridAdapter.java b/src/com/android/launcher3/AppsGridAdapter.java
index 9c1c46b..a593a57 100644
--- a/src/com/android/launcher3/AppsGridAdapter.java
+++ b/src/com/android/launcher3/AppsGridAdapter.java
@@ -139,7 +139,7 @@
                             mPredictedAppsDividerPaint);
                     hasDrawnPredictedAppsDivider = true;
 
-                } else if (grid.isPhone() && shouldDrawItemSection(holder, i, items)) {
+                } else if (grid.isPhone && shouldDrawItemSection(holder, i, items)) {
                     // At this point, we only draw sections for each section break;
                     int viewTopOffset = (2 * child.getPaddingTop());
                     int pos = holder.getPosition();
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 4bf862d..2b1cfe0 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -821,8 +821,6 @@
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        DeviceProfile grid = mLauncher.getDeviceProfile();
-
         int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
         int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
         int widthSize = MeasureSpec.getSize(widthMeasureSpec);
@@ -830,8 +828,8 @@
         int childWidthSize = widthSize - (getPaddingLeft() + getPaddingRight());
         int childHeightSize = heightSize - (getPaddingTop() + getPaddingBottom());
         if (mFixedCellWidth < 0 || mFixedCellHeight < 0) {
-            int cw = grid.calculateCellWidth(childWidthSize, mCountX);
-            int ch = grid.calculateCellHeight(childHeightSize, mCountY);
+            int cw = DeviceProfile.calculateCellWidth(childWidthSize, mCountX);
+            int ch = DeviceProfile.calculateCellHeight(childHeightSize, mCountY);
             if (cw != mCellWidth || ch != mCellHeight) {
                 mCellWidth = cw;
                 mCellHeight = ch;
@@ -2714,16 +2712,14 @@
      * @param result An array of length 2 in which to store the result (may be null).
      */
     public static int[] rectToCell(Launcher launcher, int width, int height, int[] result) {
-        LauncherAppState app = LauncherAppState.getInstance();
         DeviceProfile grid = launcher.getDeviceProfile();
-        Rect padding = grid.getWorkspacePadding(grid.isLandscape ?
-                CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
+        Rect padding = grid.getWorkspacePadding(Utilities.isRtl(launcher.getResources()));
 
         // Always assume we're working with the smallest span to make sure we
         // reserve enough space in both orientations.
-        int parentWidth = grid.calculateCellWidth(grid.widthPx
+        int parentWidth = DeviceProfile.calculateCellWidth(grid.widthPx
                 - padding.left - padding.right, (int) grid.inv.numColumns);
-        int parentHeight = grid.calculateCellHeight(grid.heightPx
+        int parentHeight = DeviceProfile.calculateCellHeight(grid.heightPx
                 - padding.top - padding.bottom, (int) grid.inv.numRows);
         int smallerSize = Math.min(parentWidth, parentHeight);
 
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 8ab58b9..8f20565 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -19,118 +19,104 @@
 import android.appwidget.AppWidgetHostView;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Paint;
 import android.graphics.Paint.FontMetrics;
 import android.graphics.Point;
-import android.graphics.PointF;
 import android.graphics.Rect;
 import android.util.DisplayMetrics;
-import android.util.TypedValue;
-import android.view.Display;
 import android.view.Gravity;
-import android.view.Surface;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.ViewGroup.MarginLayoutParams;
-import android.view.WindowManager;
 import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 
-import com.android.launcher3.util.Thunk;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-
 public class DeviceProfile {
 
-    public static interface DeviceProfileCallbacks {
-        public void onAvailableSizeChanged(DeviceProfile grid);
-    }
-
     public final InvariantDeviceProfile inv;
-    private int iconDrawablePaddingOriginalPx;
 
-    boolean isLandscape;
-    public boolean isTablet;
-    public boolean isLargeTablet;
-    public boolean isLayoutRtl;
+    // Device properties
+    public final boolean isTablet;
+    public final boolean isLargeTablet;
+    public final boolean isPhone;
+    public final boolean transposeLayoutWithOrientation;
 
-    boolean transposeLayoutWithOrientation;
-    int desiredWorkspaceLeftRightMarginPx;
-    public int edgeMarginPx;
-    Rect defaultWidgetPadding;
+    // Device properties in current orientation
+    public final boolean isLandscape;
+    public final int widthPx;
+    public final int heightPx;
+    public final int availableWidthPx;
+    public final int availableHeightPx;
 
-    int widthPx;
-    int heightPx;
-    public int availableWidthPx;
-    public int availableHeightPx;
-    int defaultPageSpacingPx;
+    // Overview mode
+    private final int overviewModeMinIconZoneHeightPx;
+    private final int overviewModeMaxIconZoneHeightPx;
+    private final int overviewModeBarItemWidthPx;
+    private final int overviewModeBarSpacerWidthPx;
+    private final float overviewModeIconZoneRatio;
+    private final float overviewModeScaleFactor;
 
-    int overviewModeMinIconZoneHeightPx;
-    int overviewModeMaxIconZoneHeightPx;
-    int overviewModeBarItemWidthPx;
-    int overviewModeBarSpacerWidthPx;
-    float overviewModeIconZoneRatio;
-    float overviewModeScaleFactor;
+    // Workspace
+    private int desiredWorkspaceLeftRightMarginPx;
+    public final int edgeMarginPx;
+    public final Rect defaultWidgetPadding;
+    private final int pageIndicatorHeightPx;
+    private final int defaultPageSpacingPx;
+    private float dragViewScale;
+
+    // Workspace icons
+    public int iconSizePx;
+    public int iconTextSizePx;
+    public int iconDrawablePaddingPx;
+    private final int iconDrawablePaddingOriginalPx;
 
     public int cellWidthPx;
     public int cellHeightPx;
 
-    int iconDrawablePaddingPx;
-    int allAppsCellWidthPx;
-    int allAppsCellHeightPx;
-    int allAppsCellPaddingPx;
-    int folderBackgroundOffset;
-    int folderIconSizePx;
-    int folderCellWidthPx;
-    int folderCellHeightPx;
-    int hotseatCellWidthPx;
-    int hotseatCellHeightPx;
-    int hotseatIconSizePx;
-    int hotseatBarHeightPx;
-    int allAppsNumRows;
-    int allAppsNumCols;
-    int appsViewNumCols;
-    int appsViewNumPredictiveCols;
-    int searchBarSpaceWidthPx;
-    int searchBarSpaceHeightPx;
-    int pageIndicatorHeightPx;
-    int allAppsButtonVisualSize;
+    // Folder
+    public int folderBackgroundOffset;
+    public int folderIconSizePx;
+    public int folderCellWidthPx;
+    public int folderCellHeightPx;
 
-    int iconSizePx;
-    public int iconTextSizePx;
-    int allAppsIconSizePx;
-    int allAppsIconTextSizePx;
+    // Hotseat
+    public int hotseatCellWidthPx;
+    public int hotseatCellHeightPx;
+    public int hotseatIconSizePx;
+    private int hotseatBarHeightPx;
 
-    float dragViewScale;
+    // All apps
+    private int allAppsCellWidthPx;
+    public int allAppsCellHeightPx;
+    private final int allAppsCellPaddingPx;
+    public int appsViewNumCols;
+    public int appsViewNumPredictiveCols;
+    public int allAppsButtonVisualSize;
+    public final int allAppsIconSizePx;
+    public final int allAppsIconTextSizePx;
 
-    int allAppsShortEdgeCount = -1;
-    int allAppsLongEdgeCount = -1;
+    // QSB
+    private int searchBarSpaceWidthPx;
+    private int searchBarSpaceHeightPx;
 
-    private ArrayList<DeviceProfileCallbacks> mCallbacks = new ArrayList<DeviceProfileCallbacks>();
-
-    public DeviceProfile(Context context, InvariantDeviceProfile inv) {
-        // Determine the dynamic grid properties
-        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
-        Display display = wm.getDefaultDisplay();
-
-        Point realSize = new Point();
-        display.getRealSize(realSize);
-        DisplayMetrics dm = new DisplayMetrics();
-        display.getMetrics(dm);
+    public DeviceProfile(Context context, InvariantDeviceProfile inv,
+            Point minSize, Point maxSize,
+            int width, int height, boolean isLandscape) {
 
         this.inv = inv;
-        init(context, realSize.x, realSize.y, dm.widthPixels, dm.heightPixels);
-    }
+        this.isLandscape = isLandscape;
 
-    private void init(Context context, int wPx, int hPx, int awPx, int ahPx) {
         Resources res = context.getResources();
         DisplayMetrics dm = res.getDisplayMetrics();
 
+        // Constants from resources
+        isTablet = res.getBoolean(R.bool.is_tablet);
+        isLargeTablet = res.getBoolean(R.bool.is_large_tablet);
+        isPhone = !isTablet && !isLargeTablet;
+
+        // Some more constants
         transposeLayoutWithOrientation =
                 res.getBoolean(R.bool.hotseat_transpose_layout_with_orientation);
 
@@ -167,110 +153,48 @@
         // AllApps uses the original non-scaled icon size
         allAppsIconSizePx = Utilities.pxFromDp(inv.iconSize, dm);
 
-        // If the partner customization apk contains any grid overrides, apply them
-        applyPartnerDeviceProfileOverrides(context, dm);
+        // Determine sizes.
+        widthPx = width;
+        heightPx = height;
+        if (isLandscape) {
+            availableWidthPx = maxSize.x;
+            availableHeightPx = minSize.y;
+        } else {
+            availableWidthPx = minSize.x;
+            availableHeightPx = maxSize.y;
+        }
 
         // Calculate the remaining vars
-        updateFromConfiguration(context, res, wPx, hPx, awPx, ahPx);
-        updateAvailableDimensions(context);
+        updateAvailableDimensions(dm, res);
         computeAllAppsButtonSize(context);
     }
 
     /**
-     * Apply any Partner customization grid overrides.
-     *
-     * Currently we support: all apps row / column count.
-     */
-    private void applyPartnerDeviceProfileOverrides(Context ctx, DisplayMetrics dm) {
-        Partner p = Partner.get(ctx.getPackageManager());
-        if (p != null) {
-            p.applyDeviceProfileOverrides(this);
-        }
-    }
-
-    /**
      * Determine the exact visual footprint of the all apps button, taking into account scaling
      * and internal padding of the drawable.
      */
     private void computeAllAppsButtonSize(Context context) {
         Resources res = context.getResources();
         float padding = res.getInteger(R.integer.config_allAppsButtonPaddingPercent) / 100f;
-        LauncherAppState app = LauncherAppState.getInstance();
         allAppsButtonVisualSize = (int) (hotseatIconSizePx * (1 - padding));
     }
 
-    void addCallback(DeviceProfileCallbacks cb) {
-        mCallbacks.add(cb);
-        cb.onAvailableSizeChanged(this);
-    }
-    void removeCallback(DeviceProfileCallbacks cb) {
-        mCallbacks.remove(cb);
-    }
-
-    private int getDeviceOrientation(Context context) {
-        WindowManager windowManager =  (WindowManager)
-                context.getSystemService(Context.WINDOW_SERVICE);
-        Resources resources = context.getResources();
-        DisplayMetrics dm = resources.getDisplayMetrics();
-        Configuration config = resources.getConfiguration();
-        int rotation = windowManager.getDefaultDisplay().getRotation();
-
-        boolean isLandscape = (config.orientation == Configuration.ORIENTATION_LANDSCAPE) &&
-                (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180);
-        boolean isRotatedPortrait = (config.orientation == Configuration.ORIENTATION_PORTRAIT) &&
-                (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);
-        if (isLandscape || isRotatedPortrait) {
-            return CellLayout.LANDSCAPE;
-        } else {
-            return CellLayout.PORTRAIT;
-        }
-    }
-
-    private void updateAvailableDimensions(Context context) {
-        WindowManager windowManager =  (WindowManager)
-                context.getSystemService(Context.WINDOW_SERVICE);
-        Display display = windowManager.getDefaultDisplay();
-        Resources resources = context.getResources();
-        DisplayMetrics dm = resources.getDisplayMetrics();
-        Configuration config = resources.getConfiguration();
-
-        // There are three possible configurations that the dynamic grid accounts for, portrait,
-        // landscape with the nav bar at the bottom, and landscape with the nav bar at the side.
-        // To prevent waiting for fitSystemWindows(), we make the observation that in landscape,
-        // the height is the smallest height (either with the nav bar at the bottom or to the
-        // side) and otherwise, the height is simply the largest possible height for a portrait
-        // device.
-        Point size = new Point();
-        Point smallestSize = new Point();
-        Point largestSize = new Point();
-        display.getSize(size);
-        display.getCurrentSizeRange(smallestSize, largestSize);
-        availableWidthPx = size.x;
-        if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
-            availableHeightPx = smallestSize.y;
-        } else {
-            availableHeightPx = largestSize.y;
-        }
-
+    private void updateAvailableDimensions(DisplayMetrics dm, Resources res) {
         // Check to see if the icons fit in the new available height.  If not, then we need to
         // shrink the icon size.
         float scale = 1f;
         int drawablePadding = iconDrawablePaddingOriginalPx;
-        updateIconSize(1f, drawablePadding, resources, dm);
+        updateIconSize(1f, drawablePadding, res, dm);
         float usedHeight = (cellHeightPx * inv.numRows);
 
-        Rect workspacePadding = getWorkspacePadding();
+        // We only care about the top and bottom workspace padding, which is not affected by RTL.
+        Rect workspacePadding = getWorkspacePadding(false /* isLayoutRtl */);
         int maxHeight = (availableHeightPx - workspacePadding.top - workspacePadding.bottom);
         if (usedHeight > maxHeight) {
             scale = maxHeight / usedHeight;
             drawablePadding = 0;
         }
-        updateIconSize(scale, drawablePadding, resources, dm);
-
-        // Make the callbacks
-        for (DeviceProfileCallbacks cb : mCallbacks) {
-            cb.onAvailableSizeChanged(this);
-        }
+        updateIconSize(scale, drawablePadding, res, dm);
     }
 
     private void updateIconSize(float scale, int drawablePadding, Resources res,
@@ -309,25 +233,6 @@
         // All Apps
         allAppsCellWidthPx = allAppsIconSizePx;
         allAppsCellHeightPx = allAppsIconSizePx + drawablePadding + allAppsIconTextSizePx;
-        int maxLongEdgeCellCount =
-                res.getInteger(R.integer.config_dynamic_grid_max_long_edge_cell_count);
-        int maxShortEdgeCellCount =
-                res.getInteger(R.integer.config_dynamic_grid_max_short_edge_cell_count);
-        int minEdgeCellCount =
-                res.getInteger(R.integer.config_dynamic_grid_min_edge_cell_count);
-        int maxRows = (isLandscape ? maxShortEdgeCellCount : maxLongEdgeCellCount);
-        int maxCols = (isLandscape ? maxLongEdgeCellCount : maxShortEdgeCellCount);
-
-        if (allAppsShortEdgeCount > 0 && allAppsLongEdgeCount > 0) {
-            allAppsNumRows = isLandscape ? allAppsShortEdgeCount : allAppsLongEdgeCount;
-            allAppsNumCols = isLandscape ? allAppsLongEdgeCount : allAppsShortEdgeCount;
-        } else {
-            allAppsNumRows = (availableHeightPx - pageIndicatorHeightPx) /
-                    (allAppsCellHeightPx + allAppsCellPaddingPx);
-            allAppsNumRows = Math.max(minEdgeCellCount, Math.min(maxRows, allAppsNumRows));
-            allAppsNumCols = (availableWidthPx) / (allAppsCellWidthPx + allAppsCellPaddingPx);
-            allAppsNumCols = Math.max(minEdgeCellCount, Math.min(maxCols, allAppsNumCols));
-        }
 
         int appsContainerViewWidthPx = res.getDimensionPixelSize(R.dimen.apps_container_width);
         updateAppsViewNumCols(res, appsContainerViewWidthPx);
@@ -339,7 +244,7 @@
         int availableAppsWidthPx = (containerWidth > 0) ? containerWidth : availableWidthPx;
         int numAppsCols = (availableAppsWidthPx - appsViewLeftMarginPx) /
                 (allAppsCellWidthPx + 2 * allAppsCellPaddingPx);
-        int numPredictiveAppCols = isPhone() ? 4 : numAppsCols;
+        int numPredictiveAppCols = isPhone ? 4 : numAppsCols;
         if ((numAppsCols != appsViewNumCols) ||
                 (numPredictiveAppCols != appsViewNumPredictiveCols)) {
             appsViewNumCols = numAppsCols;
@@ -349,24 +254,9 @@
         return false;
     }
 
-    void updateFromConfiguration(Context context, Resources resources, int wPx, int hPx,
-                                 int awPx, int ahPx) {
-        Configuration configuration = resources.getConfiguration();
-        isLandscape = (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE);
-        isTablet = resources.getBoolean(R.bool.is_tablet);
-        isLargeTablet = resources.getBoolean(R.bool.is_large_tablet);
-        isLayoutRtl = Utilities.isRtl(resources);
-        widthPx = wPx;
-        heightPx = hPx;
-        availableWidthPx = awPx;
-        availableHeightPx = ahPx;
-
-        updateAvailableDimensions(context);
-    }
-
     /** Returns the search bar top offset */
-    int getSearchBarTopOffset() {
-        if (isTablet() && !isVerticalBarLayout()) {
+    private int getSearchBarTopOffset() {
+        if (isTablet && !isVerticalBarLayout()) {
             return 4 * edgeMarginPx;
         } else {
             return 2 * edgeMarginPx;
@@ -374,14 +264,9 @@
     }
 
     /** Returns the search bar bounds in the current orientation */
-    Rect getSearchBarBounds() {
-        return getSearchBarBounds(isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
-    }
-    /** Returns the search bar bounds in the specified orientation */
-    Rect getSearchBarBounds(int orientation) {
+    public Rect getSearchBarBounds(boolean isLayoutRtl) {
         Rect bounds = new Rect();
-        if (orientation == CellLayout.LANDSCAPE &&
-                transposeLayoutWithOrientation) {
+        if (isLandscape && transposeLayoutWithOrientation) {
             if (isLayoutRtl) {
                 bounds.set(availableWidthPx - searchBarSpaceHeightPx, edgeMarginPx,
                         availableWidthPx, availableHeightPx - edgeMarginPx);
@@ -390,12 +275,10 @@
                         availableHeightPx - edgeMarginPx);
             }
         } else {
-            if (isTablet()) {
+            if (isTablet) {
                 // Pad the left and right of the workspace to ensure consistent spacing
                 // between all icons
-                int width = (orientation == CellLayout.LANDSCAPE)
-                        ? Math.max(widthPx, heightPx)
-                        : Math.min(widthPx, heightPx);
+                int width = isLandscape ? Math.max(widthPx, heightPx) : Math.min(widthPx, heightPx);
                 // XXX: If the icon size changes across orientations, we will have to take
                 //      that into account here too.
                 int gap = (int) ((width - 2 * edgeMarginPx -
@@ -413,47 +296,11 @@
         return bounds;
     }
 
-    /** Returns the bounds of the workspace page indicators. */
-    Rect getWorkspacePageIndicatorBounds(Rect insets) {
-        Rect workspacePadding = getWorkspacePadding();
-        if (isLandscape && transposeLayoutWithOrientation) {
-            if (isLayoutRtl) {
-                return new Rect(workspacePadding.left, workspacePadding.top,
-                        workspacePadding.left + pageIndicatorHeightPx,
-                        heightPx - workspacePadding.bottom - insets.bottom);
-            } else {
-                int pageIndicatorLeft = widthPx - workspacePadding.right;
-                return new Rect(pageIndicatorLeft, workspacePadding.top,
-                        pageIndicatorLeft + pageIndicatorHeightPx,
-                        heightPx - workspacePadding.bottom - insets.bottom);
-            }
-        } else {
-            int pageIndicatorTop = heightPx - insets.bottom - workspacePadding.bottom;
-            return new Rect(workspacePadding.left, pageIndicatorTop,
-                    widthPx - workspacePadding.right, pageIndicatorTop + pageIndicatorHeightPx);
-        }
-    }
-
-    public int getWorkspaceGridHeight() {
-        Rect p = getWorkspacePadding();
-        return availableHeightPx - p.top - p.bottom;
-    }
-
-    public int getWorkspaceGridWidth() {
-        Rect p = getWorkspacePadding();
-        return availableWidthPx - p.left - p.right;
-    }
-
     /** Returns the workspace padding in the specified orientation */
-    Rect getWorkspacePadding() {
-        return getWorkspacePadding(isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
-    }
-
-    Rect getWorkspacePadding(int orientation) {
-        Rect searchBarBounds = getSearchBarBounds(orientation);
+    Rect getWorkspacePadding(boolean isLayoutRtl) {
+        Rect searchBarBounds = getSearchBarBounds(isLayoutRtl);
         Rect padding = new Rect();
-        if (orientation == CellLayout.LANDSCAPE &&
-                transposeLayoutWithOrientation) {
+        if (isLandscape && transposeLayoutWithOrientation) {
             // Pad the left and right of the workspace with search/hotseat bar sizes
             if (isLayoutRtl) {
                 padding.set(hotseatBarHeightPx, edgeMarginPx,
@@ -463,14 +310,14 @@
                         hotseatBarHeightPx, edgeMarginPx);
             }
         } else {
-            if (isTablet()) {
+            if (isTablet) {
                 // Pad the left and right of the workspace to ensure consistent spacing
                 // between all icons
                 float gapScale = 1f + (dragViewScale - 1f) / 2f;
-                int width = (orientation == CellLayout.LANDSCAPE)
+                int width = isLandscape
                         ? Math.max(widthPx, heightPx)
                         : Math.min(widthPx, heightPx);
-                int height = (orientation != CellLayout.LANDSCAPE)
+                int height = isLandscape
                         ? Math.max(widthPx, heightPx)
                         : Math.min(widthPx, heightPx);
                 int paddingTop = searchBarBounds.bottom;
@@ -492,16 +339,15 @@
         return padding;
     }
 
-    int getWorkspacePageSpacing(int orientation) {
-        if ((orientation == CellLayout.LANDSCAPE &&
-                transposeLayoutWithOrientation) || isLargeTablet()) {
+    private int getWorkspacePageSpacing(boolean isLayoutRtl) {
+        if ((isLandscape && transposeLayoutWithOrientation) || isLargeTablet) {
             // In landscape mode the page spacing is set to the default.
             return defaultPageSpacingPx;
         } else {
             // In portrait, we want the pages spaced such that there is no
             // overhang of the previous / next page into the current page viewport.
             // We assume symmetrical padding in portrait mode.
-            return Math.max(defaultPageSpacingPx, 2 * getWorkspacePadding().left);
+            return Math.max(defaultPageSpacingPx, 2 * getWorkspacePadding(isLayoutRtl).left);
         }
     }
 
@@ -512,8 +358,8 @@
         return new Rect(0, availableHeightPx - zoneHeight, 0, availableHeightPx);
     }
 
-    float getOverviewModeScale() {
-        Rect workspacePadding = getWorkspacePadding();
+    public float getOverviewModeScale(boolean isLayoutRtl) {
+        Rect workspacePadding = getWorkspacePadding(isLayoutRtl);
         Rect overviewBar = getOverviewModeButtonBarRect();
         int pageSpace = availableHeightPx - workspacePadding.top - workspacePadding.bottom;
         return (overviewModeScaleFactor * (pageSpace - overviewBar.height())) / pageSpace;
@@ -537,16 +383,6 @@
         return height / countY;
     }
 
-    boolean isPhone() {
-        return !isTablet && !isLargeTablet;
-    }
-    boolean isTablet() {
-        return isTablet;
-    }
-    boolean isLargeTablet() {
-        return isLargeTablet;
-    }
-
     /**
      * When {@code true}, hotseat is on the bottom row when in landscape mode.
      * If {@code false}, hotseat is on the right column when in landscape mode.
@@ -556,10 +392,10 @@
     }
 
     boolean shouldFadeAdjacentWorkspaceScreens() {
-        return isVerticalBarLayout() || isLargeTablet();
+        return isVerticalBarLayout() || isLargeTablet;
     }
 
-    int getVisibleChildCount(ViewGroup parent) {
+    private int getVisibleChildCount(ViewGroup parent) {
         int visibleChildren = 0;
         for (int i = 0; i < parent.getChildCount(); i++) {
             if (parent.getChildAt(i).getVisibility() != View.GONE) {
@@ -572,6 +408,7 @@
     public void layout(Launcher launcher) {
         FrameLayout.LayoutParams lp;
         boolean hasVerticalBarLayout = isVerticalBarLayout();
+        final boolean isLayoutRtl = Utilities.isRtl(launcher.getResources());
 
         // Layout the search bar space
         View searchBar = launcher.getSearchBar();
@@ -601,11 +438,10 @@
         PagedView workspace = (PagedView) launcher.findViewById(R.id.workspace);
         lp = (FrameLayout.LayoutParams) workspace.getLayoutParams();
         lp.gravity = Gravity.CENTER;
-        int orientation = isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT;
-        Rect padding = getWorkspacePadding(orientation);
+        Rect padding = getWorkspacePadding(isLayoutRtl);
         workspace.setLayoutParams(lp);
         workspace.setPadding(padding.left, padding.top, padding.right, padding.bottom);
-        workspace.setPageSpacing(getWorkspacePageSpacing(orientation));
+        workspace.setPageSpacing(getWorkspacePageSpacing(isLayoutRtl));
 
         // Layout the hotseat
         View hotseat = launcher.findViewById(R.id.hotseat);
@@ -616,7 +452,7 @@
             lp.width = hotseatBarHeightPx;
             lp.height = LayoutParams.MATCH_PARENT;
             hotseat.findViewById(R.id.layout).setPadding(0, 2 * edgeMarginPx, 0, 2 * edgeMarginPx);
-        } else if (isTablet()) {
+        } else if (isTablet) {
             // Pad the hotseat with the workspace padding calculated above
             lp.gravity = Gravity.BOTTOM;
             lp.width = LayoutParams.MATCH_PARENT;
diff --git a/src/com/android/launcher3/FocusHelper.java b/src/com/android/launcher3/FocusHelper.java
index fe50e3a..46e4902 100644
--- a/src/com/android/launcher3/FocusHelper.java
+++ b/src/com/android/launcher3/FocusHelper.java
@@ -92,13 +92,12 @@
 
             final int pageIndex = pagedView.indexOfChild(cellLayout);
             final int pageCount = pagedView.getPageCount();
-            Launcher launcher  = (Launcher) v.getContext();
+            final boolean isLayoutRtl = Utilities.isRtl(v.getResources());
 
             int[][] matrix = FocusLogic.createSparseMatrix(cellLayout);
             // Process focus.
             int newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX,
-                    countY, matrix, iconIndex, pageIndex, pageCount,
-                    launcher.getDeviceProfile().isLayoutRtl);
+                    countY, matrix, iconIndex, pageIndex, pageCount, isLayoutRtl);
             if (newIconIndex == FocusLogic.NOOP) {
                 handleNoopKey(keyCode, v);
                 return consume;
@@ -252,7 +251,7 @@
 
         // Process the focus.
         int newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX,
-                countY, matrix, iconIndex, pageIndex, pageCount, profile.isLayoutRtl);
+                countY, matrix, iconIndex, pageIndex, pageCount, Utilities.isRtl(v.getResources()));
 
         View newIcon = null;
         if (newIconIndex == FocusLogic.NEXT_PAGE_FIRST_ITEM) {
@@ -335,7 +334,7 @@
 
         // Process the focus.
         int newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX,
-                countY, matrix, iconIndex, pageIndex, pageCount, profile.isLayoutRtl);
+                countY, matrix, iconIndex, pageIndex, pageCount, Utilities.isRtl(v.getResources()));
         View newIcon = null;
         switch (newIconIndex) {
             case FocusLogic.NOOP:
@@ -358,7 +357,8 @@
                     matrix = FocusLogic.createSparseMatrix(iconLayout,
                         iconLayout.getCountX(), row);
                     newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX + 1, countY,
-                            matrix, FocusLogic.PIVOT, newPageIndex, pageCount, profile.isLayoutRtl);
+                            matrix, FocusLogic.PIVOT, newPageIndex, pageCount,
+                            Utilities.isRtl(v.getResources()));
                     newIcon = parent.getChildAt(newIconIndex);
                 }
                 break;
@@ -391,7 +391,8 @@
                     iconLayout = (CellLayout) parent.getParent();
                     matrix = FocusLogic.createSparseMatrix(iconLayout, -1, row);
                     newIconIndex = FocusLogic.handleKeyEvent(keyCode, countX + 1, countY,
-                            matrix, FocusLogic.PIVOT, newPageIndex, pageCount, profile.isLayoutRtl);
+                            matrix, FocusLogic.PIVOT, newPageIndex, pageCount,
+                            Utilities.isRtl(v.getResources()));
                     newIcon = parent.getChildAt(newIconIndex);
                 }
                 break;
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index 72dc1e9..ec4ea04 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -36,7 +36,6 @@
 import android.util.Log;
 import android.view.ActionMode;
 import android.view.KeyEvent;
-import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.MotionEvent;
@@ -968,7 +967,7 @@
                 bounds.left + bounds.width() - width);
         int top = Math.min(Math.max(bounds.top, centeredTop),
                 bounds.top + bounds.height() - height);
-        if (grid.isPhone() && (grid.availableWidthPx - width) < grid.iconSizePx) {
+        if (grid.isPhone && (grid.availableWidthPx - width) < grid.iconSizePx) {
             // Center the folder if it is full (on phones only)
             left = (grid.availableWidthPx - width) / 2;
         } else if (width >= bounds.width()) {
@@ -1003,8 +1002,7 @@
 
     private int getContentAreaHeight() {
         DeviceProfile grid = mLauncher.getDeviceProfile();
-        Rect workspacePadding = grid.getWorkspacePadding(grid.isLandscape ?
-                CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
+        Rect workspacePadding = grid.getWorkspacePadding(mContent.mIsRtl);
         int maxContentAreaHeight = grid.availableHeightPx -
                 workspacePadding.top - workspacePadding.bottom -
                 mFooterHeight;
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 1c1342c..ce33164 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -109,7 +109,7 @@
 
         mAllAppsButtonRank = grid.inv.hotseatAllAppsRank;
         mContent = (CellLayout) findViewById(R.id.layout);
-        if (grid.isLandscape && !grid.isLargeTablet()) {
+        if (grid.isLandscape && !grid.isLargeTablet) {
             mContent.setGridSize(1, (int) grid.inv.numHotseatIcons);
         } else {
             mContent.setGridSize((int) grid.inv.numHotseatIcons, 1);
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index fcd6d60..92fdbde 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -16,29 +16,25 @@
 
 package com.android.launcher3;
 
+import android.annotation.TargetApi;
 import android.content.Context;
 import android.graphics.Point;
 import android.graphics.PointF;
+import android.os.Build;
 import android.util.DisplayMetrics;
-import android.util.TypedValue;
 import android.view.Display;
 import android.view.WindowManager;
-
 import com.android.launcher3.util.Thunk;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 
 public class InvariantDeviceProfile {
-    private static final String TAG = "InvariantDeviceProfile";
 
     // This is a static that we use for the default icon size on a 4/5-inch phone
-    static float DEFAULT_ICON_SIZE_DP = 60;
+    private static float DEFAULT_ICON_SIZE_DP = 60;
 
-
-    static ArrayList<InvariantDeviceProfile> sDeviceProfiles =
-            new ArrayList<InvariantDeviceProfile>();
+    private static final ArrayList<InvariantDeviceProfile> sDeviceProfiles = new ArrayList<>();
     static {
         sDeviceProfiles.add(new InvariantDeviceProfile("Super Short Stubby",
                 255, 300,  2, 3, 2, 3, 48, 13, 3, 48, R.xml.default_workspace_4x4));
@@ -67,7 +63,7 @@
                 1527, 2527,  7, 7, 6, 6, 100, 20,  7, 72, R.xml.default_workspace_4x4));
     }
 
-    class DeviceProfileQuery {
+    private class DeviceProfileQuery {
         InvariantDeviceProfile profile;
         float widthDps;
         float heightDps;
@@ -100,6 +96,9 @@
     // Derived invariant properties
     int hotseatAllAppsRank;
 
+    DeviceProfile landscapeProfile;
+    DeviceProfile portraitProfile;
+
     InvariantDeviceProfile() {
     }
 
@@ -124,6 +123,7 @@
         defaultLayoutId = dlId;
     }
 
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
     InvariantDeviceProfile(Context context) {
         WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
         Display display = wm.getDefaultDisplay();
@@ -179,6 +179,18 @@
         // If the partner customization apk contains any grid overrides, apply them
         // Supported overrides: numRows, numColumns, iconSize
         applyPartnerDeviceProfileOverrides(context, dm);
+
+        Point realSize = new Point();
+        display.getRealSize(realSize);
+        // The real size never changes. smallSide and largeSize will remain the
+        // same in any orientation.
+        int smallSide = Math.min(realSize.x, realSize.y);
+        int largeSide = Math.max(realSize.x, realSize.y);
+
+        landscapeProfile = new DeviceProfile(context, this, smallestSize, largestSize,
+                largeSide, smallSide, true /* isLandscape */);
+        portraitProfile = new DeviceProfile(context, this, smallestSize, largestSize,
+                smallSide, largeSide, false /* isLandscape */);
     }
 
     /**
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 6c73739..c923c95 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -431,8 +431,13 @@
         LauncherAppState.getLauncherProvider().setLauncherProviderChangeListener(this);
 
         // Load configuration-specific DeviceProfile
-        mDeviceProfile = new DeviceProfile(this, app.getInvariantDeviceProfile());
-        mDeviceProfile.addCallback(LauncherAppState.getInstance());
+        mDeviceProfile = getResources().getConfiguration().orientation
+                == Configuration.ORIENTATION_LANDSCAPE ?
+                        app.getInvariantDeviceProfile().landscapeProfile
+                            : app.getInvariantDeviceProfile().portraitProfile;
+
+        // TODO: Move this to icon cache.
+        Utilities.setIconSize(mDeviceProfile.iconSizePx);
 
         // the LauncherApplication should call this, but in case of Instrumentation it might not be present yet
         mSharedPrefs = getSharedPreferences(LauncherAppState.getSharedPreferencesKey(),
@@ -4199,7 +4204,7 @@
     }
 
     protected Rect getSearchBarBounds() {
-        return mDeviceProfile.getSearchBarBounds();
+        return mDeviceProfile.getSearchBarBounds(Utilities.isRtl(getResources()));
     }
 
     public void bindSearchablesChanged() {
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 93753a2..d4b41e6 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -16,7 +16,6 @@
 
 package com.android.launcher3;
 
-import android.annotation.TargetApi;
 import android.app.SearchManager;
 import android.content.ComponentName;
 import android.content.Context;
@@ -24,12 +23,7 @@
 import android.content.IntentFilter;
 import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.graphics.Point;
-import android.os.Build;
-import android.util.DisplayMetrics;
 import android.util.Log;
-import android.view.Display;
-import android.view.WindowManager;
 
 import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
 import com.android.launcher3.compat.LauncherAppsCompat;
@@ -38,7 +32,7 @@
 
 import java.lang.ref.WeakReference;
 
-public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
+public class LauncherAppState {
 
     private final AppFilter mAppFilter;
     private final BuildInfo mBuildInfo;
@@ -213,11 +207,6 @@
         return mInvariantDeviceProfile;
     }
 
-    @Override
-    public void onAvailableSizeChanged(DeviceProfile grid) {
-        Utilities.setIconSize(grid.iconSizePx);
-    }
-
     public static boolean isDogfoodBuild() {
         return getInstance().mBuildInfo.isDogfoodBuild();
     }
diff --git a/src/com/android/launcher3/Partner.java b/src/com/android/launcher3/Partner.java
index c9e8379..380078b 100644
--- a/src/com/android/launcher3/Partner.java
+++ b/src/com/android/launcher3/Partner.java
@@ -47,8 +47,6 @@
     public static final String RES_REQUIRE_FIRST_RUN_FLOW = "requires_first_run_flow";
 
     /** These resources are used to override the device profile  */
-    public static final String RES_GRID_AA_SHORT_EDGE_COUNT = "grid_aa_short_edge_count";
-    public static final String RES_GRID_AA_LONG_EDGE_COUNT = "grid_aa_long_edge_count";
     public static final String RES_GRID_NUM_ROWS = "grid_num_rows";
     public static final String RES_GRID_NUM_COLUMNS = "grid_num_columns";
     public static final String RES_GRID_ICON_SIZE_DP = "grid_icon_size_dp";
@@ -154,32 +152,4 @@
             inv.iconSize = iconSize;
         }
     }
-
-    public void applyDeviceProfileOverrides(DeviceProfile dp) {
-        int allAppsShortEdgeCount = -1;
-        int allAppsLongEdgeCount = -1;
-
-        try {
-            int resId = getResources().getIdentifier(RES_GRID_AA_SHORT_EDGE_COUNT,
-                    "integer", getPackageName());
-            if (resId > 0) {
-                allAppsShortEdgeCount = getResources().getInteger(resId);
-            }
-
-            resId = getResources().getIdentifier(RES_GRID_AA_LONG_EDGE_COUNT,
-                    "integer", getPackageName());
-            if (resId > 0) {
-                allAppsLongEdgeCount = getResources().getInteger(resId);
-            }
-
-        } catch (Resources.NotFoundException ex) {
-            Log.e(TAG, "Invalid Partner grid resource!", ex);
-            return;
-        }
-
-        if (allAppsShortEdgeCount > 0 && allAppsLongEdgeCount > 0) {
-            dp.allAppsShortEdgeCount = allAppsShortEdgeCount;
-            dp.allAppsLongEdgeCount = allAppsLongEdgeCount;
-        }
-    }
 }
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 7a52e58..d2c37d2 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -316,7 +316,7 @@
                 R.styleable.Workspace, defStyle, 0);
         mSpringLoadedShrinkFactor =
             res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f;
-        mOverviewModeShrinkFactor = grid.getOverviewModeScale();
+        mOverviewModeShrinkFactor = grid.getOverviewModeScale(mIsRtl);
         mOriginalDefaultPage = mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1);
         a.recycle();
 
@@ -1980,7 +1980,6 @@
     }
 
     int getOverviewModeTranslationY() {
-        LauncherAppState app = LauncherAppState.getInstance();
         DeviceProfile grid = mLauncher.getDeviceProfile();
         Rect overviewBar = grid.getOverviewModeButtonBarRect();
 
@@ -2338,7 +2337,6 @@
     }
 
     public void beginExternalDragShared(View child, DragSource source) {
-        LauncherAppState app = LauncherAppState.getInstance();
         DeviceProfile grid = mLauncher.getDeviceProfile();
         int iconSize = grid.iconSizePx;
 
@@ -2848,34 +2846,35 @@
      * widthGap/heightGap (right, bottom) */
     static Rect getCellLayoutMetrics(Launcher launcher, int orientation) {
         LauncherAppState app = LauncherAppState.getInstance();
-        DeviceProfile grid = launcher.getDeviceProfile();
+        InvariantDeviceProfile inv = app.getInvariantDeviceProfile();
 
         Display display = launcher.getWindowManager().getDefaultDisplay();
         Point smallestSize = new Point();
         Point largestSize = new Point();
         display.getCurrentSizeRange(smallestSize, largestSize);
-        int countX = (int) grid.inv.numColumns;
-        int countY = (int) grid.inv.numRows;
+        int countX = (int) inv.numColumns;
+        int countY = (int) inv.numRows;
+        boolean isLayoutRtl = Utilities.isRtl(launcher.getResources());
         if (orientation == CellLayout.LANDSCAPE) {
             if (mLandscapeCellLayoutMetrics == null) {
-                Rect padding = grid.getWorkspacePadding(CellLayout.LANDSCAPE);
+                Rect padding = inv.landscapeProfile.getWorkspacePadding(isLayoutRtl);
                 int width = largestSize.x - padding.left - padding.right;
                 int height = smallestSize.y - padding.top - padding.bottom;
                 mLandscapeCellLayoutMetrics = new Rect();
                 mLandscapeCellLayoutMetrics.set(
-                        grid.calculateCellWidth(width, countX),
-                        grid.calculateCellHeight(height, countY), 0, 0);
+                        DeviceProfile.calculateCellWidth(width, countX),
+                        DeviceProfile.calculateCellHeight(height, countY), 0, 0);
             }
             return mLandscapeCellLayoutMetrics;
         } else if (orientation == CellLayout.PORTRAIT) {
             if (mPortraitCellLayoutMetrics == null) {
-                Rect padding = grid.getWorkspacePadding(CellLayout.PORTRAIT);
+                Rect padding = inv.portraitProfile.getWorkspacePadding(isLayoutRtl);
                 int width = smallestSize.x - padding.left - padding.right;
                 int height = largestSize.y - padding.top - padding.bottom;
                 mPortraitCellLayoutMetrics = new Rect();
                 mPortraitCellLayoutMetrics.set(
-                        grid.calculateCellWidth(width, countX),
-                        grid.calculateCellHeight(height, countY), 0, 0);
+                        DeviceProfile.calculateCellWidth(width, countX),
+                        DeviceProfile.calculateCellHeight(height, countY), 0, 0);
             }
             return mPortraitCellLayoutMetrics;
         }
@@ -3018,7 +3017,6 @@
        mTempPt[1] = y;
        mLauncher.getDragLayer().getDescendantCoordRelativeToSelf(this, mTempPt, true);
 
-       LauncherAppState app = LauncherAppState.getInstance();
        DeviceProfile grid = mLauncher.getDeviceProfile();
        r = grid.getHotseatRect();
        if (r.contains(mTempPt[0], mTempPt[1])) {
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index 5744531..42ba36e 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -161,7 +161,6 @@
         mLauncher = launcher;
         mWorkspace = workspace;
 
-        LauncherAppState app = LauncherAppState.getInstance();
         DeviceProfile grid = mLauncher.getDeviceProfile();
         Resources res = launcher.getResources();
         mAllAppsTransitionTime = res.getInteger(R.integer.config_workspaceUnshrinkTime);
@@ -170,7 +169,7 @@
         mSpringLoadedShrinkFactor =
                 res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100f;
         mWorkspaceScrimAlpha = res.getInteger(R.integer.config_workspaceScrimAlpha) / 100f;
-        mOverviewModeShrinkFactor = grid.getOverviewModeScale();
+        mOverviewModeShrinkFactor = grid.getOverviewModeScale(Utilities.isRtl(res));
         mWorkspaceFadeInAdjacentScreens = grid.shouldFadeAdjacentWorkspaceScreens();
     }