diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java index da92551526..d83387705a 100644 --- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java +++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java @@ -307,14 +307,15 @@ public class TaskThumbnailView extends View { } } - // Draw the background in all cases, except when the thumbnail data is opaque + // Always draw the background since the snapshots might be translucent or partially empty + // (For example, tasks been reparented out of dismissing split root when drag-to-dismiss + // split screen). + canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mBackgroundPaint); + final boolean drawBackgroundOnly = mTask == null || mTask.isLocked || mBitmapShader == null || mThumbnailData == null; - if (drawBackgroundOnly || mThumbnailData.isTranslucent) { - canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mBackgroundPaint); - if (drawBackgroundOnly) { - return; - } + if (drawBackgroundOnly) { + return; } canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mPaint); diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 08f0089438..08570eb7c2 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -154,7 +154,15 @@ - + + + + + + + + + diff --git a/res/xml/default_workspace_6x5.xml b/res/xml/default_workspace_6x5.xml new file mode 100644 index 0000000000..b078cfd7f8 --- /dev/null +++ b/res/xml/default_workspace_6x5.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/xml/device_profiles.xml b/res/xml/device_profiles.xml index e030f81098..b4bb43e9a9 100644 --- a/res/xml/device_profiles.xml +++ b/res/xml/device_profiles.xml @@ -133,4 +133,32 @@ + + + + + + \ No newline at end of file diff --git a/res/xml/device_profiles_split.xml b/res/xml/device_profiles_split.xml deleted file mode 100644 index 2fad0c9ab0..0000000000 --- a/res/xml/device_profiles_split.xml +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index 2ebedf71de..ff7a90cb2c 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -42,6 +42,7 @@ import android.util.TypedValue; import android.util.Xml; import android.view.Display; +import androidx.annotation.IntDef; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -58,6 +59,8 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -70,6 +73,13 @@ public class InvariantDeviceProfile { public static final MainThreadInitializedObject INSTANCE = new MainThreadInitializedObject<>(InvariantDeviceProfile::new); + @Retention(RetentionPolicy.SOURCE) + @IntDef({TYPE_PHONE, TYPE_MULTI_DISPLAY, TYPE_TABLET}) + public @interface DeviceType{} + public static final int TYPE_PHONE = 0; + public static final int TYPE_MULTI_DISPLAY = 1; + public static final int TYPE_TABLET = 2; + private static final String KEY_IDP_GRID_NAME = "idp_grid_name"; private static final float ICON_SIZE_DEFINED_IN_APP_DP = 48; @@ -106,7 +116,7 @@ public class InvariantDeviceProfile { public float[] iconTextSize; public int iconBitmapSize; public int fillResIconDpi; - public boolean isSplitDisplay; + public @DeviceType int deviceType; public PointF[] minCellSize; @@ -198,13 +208,21 @@ public class InvariantDeviceProfile { String gridName = getCurrentGridName(context); // Get the display info based on default display and interpolate it to existing display + Info defaultInfo = DisplayController.INSTANCE.get(context).getInfo(); + @DeviceType int defaultDeviceType = getDeviceType(defaultInfo); DisplayOption defaultDisplayOption = invDistWeightedInterpolate( - DisplayController.INSTANCE.get(context).getInfo(), - getPredefinedDeviceProfiles(context, gridName, false, false), false); + defaultInfo, + getPredefinedDeviceProfiles(context, gridName, defaultDeviceType, + /*allowDisabledGrid=*/false), + defaultDeviceType); Info myInfo = new Info(context, display); + @DeviceType int deviceType = getDeviceType(myInfo); DisplayOption myDisplayOption = invDistWeightedInterpolate( - myInfo, getPredefinedDeviceProfiles(context, gridName, false, false), false); + myInfo, + getPredefinedDeviceProfiles(context, gridName, deviceType, + /*allowDisabledGrid=*/false), + deviceType); DisplayOption result = new DisplayOption(defaultDisplayOption.grid) .add(myDisplayOption); @@ -220,7 +238,7 @@ public class InvariantDeviceProfile { System.arraycopy(defaultDisplayOption.borderSpaces, 0, result.borderSpaces, 0, COUNT_SIZES); - initGrid(context, myInfo, result, false); + initGrid(context, myInfo, result, deviceType); } /** @@ -246,6 +264,18 @@ public class InvariantDeviceProfile { } } + private static @DeviceType int getDeviceType(Info displayInfo) { + // Each screen has two profiles (portrait/landscape), so devices with four or more + // supported profiles implies two or more internal displays. + if (displayInfo.supportedBounds.size() >= 4 && ENABLE_TWO_PANEL_HOME.get()) { + return TYPE_MULTI_DISPLAY; + } else if (displayInfo.supportedBounds.stream().allMatch(displayInfo::isTablet)) { + return TYPE_TABLET; + } else { + return TYPE_PHONE; + } + } + public static String getCurrentGridName(Context context) { return Utilities.isGridOptionsEnabled(context) ? Utilities.getPrefs(context).getString(KEY_IDP_GRID_NAME, null) : null; @@ -253,23 +283,19 @@ public class InvariantDeviceProfile { private String initGrid(Context context, String gridName) { Info displayInfo = DisplayController.INSTANCE.get(context).getInfo(); - // Each screen has two profiles (portrait/landscape), so devices with four or more - // supported profiles implies two or more internal displays. - boolean isSplitDisplay = - displayInfo.supportedBounds.size() >= 4 && ENABLE_TWO_PANEL_HOME.get(); + @DeviceType int deviceType = getDeviceType(displayInfo); ArrayList allOptions = - getPredefinedDeviceProfiles(context, gridName, isSplitDisplay, + getPredefinedDeviceProfiles(context, gridName, deviceType, RestoreDbTask.isPending(context)); DisplayOption displayOption = - invDistWeightedInterpolate(displayInfo, allOptions, isSplitDisplay); - initGrid(context, displayInfo, displayOption, isSplitDisplay); + invDistWeightedInterpolate(displayInfo, allOptions, deviceType); + initGrid(context, displayInfo, displayOption, deviceType); return displayOption.grid.name; } - private void initGrid( - Context context, Info displayInfo, DisplayOption displayOption, - boolean isSplitDisplay) { + private void initGrid(Context context, Info displayInfo, DisplayOption displayOption, + @DeviceType int deviceType) { DisplayMetrics metrics = context.getResources().getDisplayMetrics(); GridOption closestProfile = displayOption.grid; numRows = closestProfile.numRows; @@ -281,7 +307,7 @@ public class InvariantDeviceProfile { numFolderColumns = closestProfile.numFolderColumns; isScalable = closestProfile.isScalable; devicePaddingId = closestProfile.devicePaddingId; - this.isSplitDisplay = isSplitDisplay; + this.deviceType = deviceType; mExtraAttrs = closestProfile.extraAttrs; @@ -303,11 +329,11 @@ public class InvariantDeviceProfile { horizontalMargin = displayOption.horizontalMargin; numShownHotseatIcons = closestProfile.numHotseatIcons; - numDatabaseHotseatIcons = isSplitDisplay + numDatabaseHotseatIcons = deviceType == TYPE_MULTI_DISPLAY ? closestProfile.numDatabaseHotseatIcons : closestProfile.numHotseatIcons; numAllAppsColumns = closestProfile.numAllAppsColumns; - numDatabaseAllAppsColumns = isSplitDisplay + numDatabaseAllAppsColumns = deviceType == TYPE_MULTI_DISPLAY ? closestProfile.numDatabaseAllAppsColumns : closestProfile.numAllAppsColumns; if (!Utilities.isGridOptionsEnabled(context)) { @@ -327,7 +353,7 @@ public class InvariantDeviceProfile { defaultWallpaperSize = new Point(displayInfo.currentSize); for (WindowBounds bounds : displayInfo.supportedBounds) { localSupportedProfiles.add(new DeviceProfile.Builder(context, this, displayInfo) - .setUseTwoPanels(isSplitDisplay) + .setUseTwoPanels(deviceType == TYPE_MULTI_DISPLAY) .setWindowBounds(bounds).build()); // Wallpaper size should be the maximum of the all possible sizes Launcher expects @@ -350,11 +376,6 @@ public class InvariantDeviceProfile { defaultWidgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(context, cn, null); } - @Nullable - public TypedValue getAttrValue(int attr) { - return mExtraAttrs == null ? null : mExtraAttrs.get(attr); - } - public void addOnChangeListener(OnIDPChangeListener listener) { mChangeListeners.add(listener); } @@ -389,12 +410,11 @@ public class InvariantDeviceProfile { } } - private static ArrayList getPredefinedDeviceProfiles( - Context context, String gridName, boolean isSplitDisplay, boolean allowDisabledGrid) { + private static ArrayList getPredefinedDeviceProfiles(Context context, + String gridName, @DeviceType int deviceType, boolean allowDisabledGrid) { ArrayList profiles = new ArrayList<>(); - int xmlResource = isSplitDisplay ? R.xml.device_profiles_split : R.xml.device_profiles; - try (XmlResourceParser parser = context.getResources().getXml(xmlResource)) { + try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) { final int depth = parser.getDepth(); int type; while (((type = parser.next()) != XmlPullParser.END_TAG || @@ -402,8 +422,8 @@ public class InvariantDeviceProfile { if ((type == XmlPullParser.START_TAG) && GridOption.TAG_NAME.equals(parser.getName())) { - GridOption gridOption = - new GridOption(context, Xml.asAttributeSet(parser), isSplitDisplay); + GridOption gridOption = new GridOption(context, Xml.asAttributeSet(parser), + deviceType); if (gridOption.isEnabled || allowDisabledGrid) { final int displayDepth = parser.getDepth(); while (((type = parser.next()) != XmlPullParser.END_TAG @@ -450,9 +470,8 @@ public class InvariantDeviceProfile { */ public List parseAllGridOptions(Context context) { List result = new ArrayList<>(); - int xmlResource = isSplitDisplay ? R.xml.device_profiles_split : R.xml.device_profiles; - try (XmlResourceParser parser = context.getResources().getXml(xmlResource)) { + try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) { final int depth = parser.getDepth(); int type; while (((type = parser.next()) != XmlPullParser.END_TAG @@ -460,7 +479,7 @@ public class InvariantDeviceProfile { if ((type == XmlPullParser.START_TAG) && GridOption.TAG_NAME.equals(parser.getName())) { GridOption option = - new GridOption(context, Xml.asAttributeSet(parser), isSplitDisplay); + new GridOption(context, Xml.asAttributeSet(parser), deviceType); if (option.isEnabled) { result.add(option); } @@ -514,12 +533,12 @@ public class InvariantDeviceProfile { } private static DisplayOption invDistWeightedInterpolate( - Info displayInfo, ArrayList points, boolean isSplitDisplay) { + Info displayInfo, ArrayList points, @DeviceType int deviceType) { int minWidthPx = Integer.MAX_VALUE; int minHeightPx = Integer.MAX_VALUE; for (WindowBounds bounds : displayInfo.supportedBounds) { boolean isTablet = displayInfo.isTablet(bounds); - if (isTablet && isSplitDisplay) { + if (isTablet && deviceType == TYPE_MULTI_DISPLAY) { // For split displays, take half width per page minWidthPx = Math.min(minWidthPx, bounds.availableSize.x / 2); minHeightPx = Math.min(minHeightPx, bounds.availableSize.y); @@ -643,6 +662,12 @@ public class InvariantDeviceProfile { public static final String TAG_NAME = "grid-option"; + private static final int DEVICE_CATEGORY_PHONE = 1 << 0; + private static final int DEVICE_CATEGORY_TABLET = 1 << 1; + private static final int DEVICE_CATEGORY_MULTI_DISPLAY = 1 << 2; + private static final int DEVICE_CATEGORY_ALL = + DEVICE_CATEGORY_PHONE | DEVICE_CATEGORY_TABLET | DEVICE_CATEGORY_MULTI_DISPLAY; + public final String name; public final int numRows; public final int numColumns; @@ -666,7 +691,7 @@ public class InvariantDeviceProfile { private final SparseArray extraAttrs; - public GridOption(Context context, AttributeSet attrs, boolean isSplitDisplay) { + public GridOption(Context context, AttributeSet attrs, @DeviceType int deviceType) { TypedArray a = context.obtainStyledAttributes( attrs, R.styleable.GridDisplayOption); name = a.getString(R.styleable.GridDisplayOption_name); @@ -674,7 +699,7 @@ public class InvariantDeviceProfile { numColumns = a.getInt(R.styleable.GridDisplayOption_numColumns, 0); dbFile = a.getString(R.styleable.GridDisplayOption_dbFile); - defaultLayoutId = a.getResourceId(isSplitDisplay && a.hasValue( + defaultLayoutId = a.getResourceId(deviceType == TYPE_MULTI_DISPLAY && a.hasValue( R.styleable.GridDisplayOption_defaultSplitDisplayLayoutId) ? R.styleable.GridDisplayOption_defaultSplitDisplayLayoutId : R.styleable.GridDisplayOption_defaultLayoutId, 0); @@ -701,7 +726,15 @@ public class InvariantDeviceProfile { devicePaddingId = a.getResourceId( R.styleable.GridDisplayOption_devicePaddingId, 0); - isEnabled = a.getBoolean(R.styleable.GridDisplayOption_gridEnabled, true); + int deviceCategory = a.getInt(R.styleable.GridDisplayOption_deviceCategory, + DEVICE_CATEGORY_ALL); + isEnabled = (deviceType == TYPE_PHONE + && ((deviceCategory & DEVICE_CATEGORY_PHONE) == DEVICE_CATEGORY_PHONE)) + || (deviceType == TYPE_TABLET + && ((deviceCategory & DEVICE_CATEGORY_TABLET) == DEVICE_CATEGORY_TABLET)) + || (deviceType == TYPE_MULTI_DISPLAY + && ((deviceCategory & DEVICE_CATEGORY_MULTI_DISPLAY) + == DEVICE_CATEGORY_MULTI_DISPLAY)); a.recycle(); extraAttrs = Themes.createValueMap(context, attrs, diff --git a/src/com/android/launcher3/model/DeviceGridState.java b/src/com/android/launcher3/model/DeviceGridState.java index 0fc4c2d716..01ebc5347b 100644 --- a/src/com/android/launcher3/model/DeviceGridState.java +++ b/src/com/android/launcher3/model/DeviceGridState.java @@ -16,6 +16,9 @@ package com.android.launcher3.model; +import static com.android.launcher3.InvariantDeviceProfile.DeviceType; +import static com.android.launcher3.InvariantDeviceProfile.TYPE_MULTI_DISPLAY; +import static com.android.launcher3.InvariantDeviceProfile.TYPE_PHONE; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_2; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_3; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_4; @@ -25,15 +28,11 @@ import android.content.Context; import android.content.SharedPreferences; import android.text.TextUtils; -import androidx.annotation.IntDef; - import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.Utilities; import com.android.launcher3.logging.StatsLogManager.LauncherEvent; import com.android.launcher3.util.IntSet; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; import java.util.Locale; import java.util.Objects; @@ -46,13 +45,6 @@ public class DeviceGridState { public static final String KEY_HOTSEAT_COUNT = "migration_src_hotseat_count"; public static final String KEY_DEVICE_TYPE = "migration_src_device_type"; - @Retention(RetentionPolicy.SOURCE) - @IntDef({TYPE_PHONE, TYPE_MULTI_DISPLAY, TYPE_TABLET}) - public @interface DeviceType{} - public static final int TYPE_PHONE = 0; - public static final int TYPE_MULTI_DISPLAY = 1; - public static final int TYPE_TABLET = 2; - private static final IntSet COMPATIBLE_TYPES = IntSet.wrap(TYPE_PHONE, TYPE_MULTI_DISPLAY); public static boolean deviceTypeCompatible(@DeviceType int typeA, @DeviceType int typeB) { @@ -67,11 +59,7 @@ public class DeviceGridState { public DeviceGridState(InvariantDeviceProfile idp) { mGridSizeString = String.format(Locale.ENGLISH, "%d,%d", idp.numColumns, idp.numRows); mNumHotseat = idp.numDatabaseHotseatIcons; - mDeviceType = idp.supportedProfiles.size() > 2 - ? TYPE_MULTI_DISPLAY - : idp.supportedProfiles.stream().allMatch(dp -> dp.isTablet) - ? TYPE_TABLET - : TYPE_PHONE; + mDeviceType = idp.deviceType; } public DeviceGridState(Context context) { diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java index 8f607a1797..4c0930bb32 100644 --- a/src/com/android/launcher3/provider/RestoreDbTask.java +++ b/src/com/android/launcher3/provider/RestoreDbTask.java @@ -16,8 +16,8 @@ package com.android.launcher3.provider; -import static com.android.launcher3.model.DeviceGridState.TYPE_MULTI_DISPLAY; -import static com.android.launcher3.model.DeviceGridState.TYPE_PHONE; +import static com.android.launcher3.InvariantDeviceProfile.TYPE_MULTI_DISPLAY; +import static com.android.launcher3.InvariantDeviceProfile.TYPE_PHONE; import static com.android.launcher3.provider.LauncherDbUtils.dropTable; import android.app.backup.BackupManager;