summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/launcher3')
-rw-r--r--src/com/android/launcher3/AbstractFloatingView.java38
-rw-r--r--src/com/android/launcher3/AppInfo.java15
-rw-r--r--src/com/android/launcher3/AppWidgetResizeFrame.java57
-rw-r--r--src/com/android/launcher3/AutoInstallsLayout.java8
-rw-r--r--src/com/android/launcher3/BubbleTextView.java16
-rw-r--r--src/com/android/launcher3/ButtonDropTarget.java6
-rw-r--r--src/com/android/launcher3/CellLayout.java4
-rw-r--r--src/com/android/launcher3/CustomAppWidget.java14
-rw-r--r--src/com/android/launcher3/DeleteDropTarget.java10
-rw-r--r--src/com/android/launcher3/DeviceProfile.java26
-rw-r--r--src/com/android/launcher3/DragSource.java16
-rw-r--r--src/com/android/launcher3/ExtendedEditText.java20
-rw-r--r--src/com/android/launcher3/FirstFrameAnimatorHelper.java10
-rw-r--r--src/com/android/launcher3/Hotseat.java67
-rw-r--r--src/com/android/launcher3/IconCache.java2
-rw-r--r--src/com/android/launcher3/InfoDropTarget.java4
-rw-r--r--src/com/android/launcher3/InvariantDeviceProfile.java11
-rw-r--r--src/com/android/launcher3/Launcher.java326
-rw-r--r--src/com/android/launcher3/LauncherAppState.java10
-rw-r--r--src/com/android/launcher3/LauncherAppWidgetHost.java3
-rw-r--r--src/com/android/launcher3/LauncherAppWidgetHostView.java87
-rw-r--r--src/com/android/launcher3/LauncherAppWidgetInfo.java12
-rw-r--r--src/com/android/launcher3/LauncherAppWidgetProviderInfo.java51
-rw-r--r--src/com/android/launcher3/LauncherCallbacks.java5
-rw-r--r--src/com/android/launcher3/LauncherModel.java3
-rw-r--r--src/com/android/launcher3/LauncherProvider.java36
-rw-r--r--src/com/android/launcher3/LauncherProviderChangeListener.java2
-rw-r--r--src/com/android/launcher3/LauncherSettings.java5
-rw-r--r--src/com/android/launcher3/PendingAppWidgetHostView.java4
-rw-r--r--src/com/android/launcher3/SessionCommitReceiver.java4
-rw-r--r--src/com/android/launcher3/SettingsActivity.java2
-rw-r--r--src/com/android/launcher3/UninstallDropTarget.java20
-rw-r--r--src/com/android/launcher3/Utilities.java56
-rw-r--r--src/com/android/launcher3/WidgetPreviewLoader.java4
-rw-r--r--src/com/android/launcher3/Workspace.java139
-rw-r--r--src/com/android/launcher3/allapps/AllAppsContainerView.java27
-rw-r--r--src/com/android/launcher3/allapps/AllAppsTransitionController.java50
-rw-r--r--src/com/android/launcher3/allapps/AlphabeticalAppsList.java9
-rw-r--r--src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java23
-rw-r--r--src/com/android/launcher3/compat/AppWidgetManagerCompat.java16
-rw-r--r--src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java33
-rw-r--r--src/com/android/launcher3/compat/LauncherAppsCompat.java2
-rw-r--r--src/com/android/launcher3/compat/WallpaperManagerCompat.java4
-rw-r--r--src/com/android/launcher3/compat/WallpaperManagerCompatVL.java34
-rw-r--r--src/com/android/launcher3/compat/WallpaperManagerCompatVOMR1.java3
-rw-r--r--src/com/android/launcher3/config/BaseFlags.java9
-rw-r--r--src/com/android/launcher3/dragndrop/BaseItemDragListener.java15
-rw-r--r--src/com/android/launcher3/dragndrop/DragController.java5
-rw-r--r--src/com/android/launcher3/dragndrop/DragLayer.java90
-rw-r--r--src/com/android/launcher3/dragndrop/DragOptions.java3
-rw-r--r--src/com/android/launcher3/dragndrop/DragView.java8
-rw-r--r--src/com/android/launcher3/dragndrop/PinItemDragListener.java2
-rw-r--r--src/com/android/launcher3/dynamicui/ColorExtractionService.java204
-rw-r--r--src/com/android/launcher3/dynamicui/ExtractedColors.java184
-rw-r--r--src/com/android/launcher3/dynamicui/ExtractionUtils.java125
-rw-r--r--src/com/android/launcher3/folder/Folder.java65
-rw-r--r--src/com/android/launcher3/graphics/DragPreviewProvider.java136
-rw-r--r--src/com/android/launcher3/graphics/DrawableFactory.java2
-rw-r--r--src/com/android/launcher3/graphics/HolographicOutlineHelper.java90
-rw-r--r--src/com/android/launcher3/graphics/IconNormalizer.java20
-rw-r--r--src/com/android/launcher3/graphics/IconShapeOverride.java4
-rw-r--r--src/com/android/launcher3/graphics/LauncherIcons.java101
-rw-r--r--src/com/android/launcher3/graphics/ShadowDrawable.java2
-rw-r--r--src/com/android/launcher3/logging/LoggerUtils.java8
-rw-r--r--src/com/android/launcher3/model/GridSizeMigrationTask.java2
-rw-r--r--src/com/android/launcher3/model/LoaderTask.java60
-rw-r--r--src/com/android/launcher3/model/PackageUpdatedTask.java21
-rw-r--r--src/com/android/launcher3/notification/NotificationGroup.java52
-rw-r--r--src/com/android/launcher3/notification/NotificationInfo.java3
-rw-r--r--src/com/android/launcher3/notification/NotificationListener.java33
-rw-r--r--src/com/android/launcher3/pageindicators/PageIndicator.java4
-rw-r--r--src/com/android/launcher3/pageindicators/PageIndicatorCaretLandscape.java1
-rw-r--r--src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java34
-rw-r--r--src/com/android/launcher3/popup/PopupContainerWithArrow.java53
-rw-r--r--src/com/android/launcher3/qsb/QsbContainerView.java8
-rw-r--r--src/com/android/launcher3/qsb/QsbWidgetHostView.java4
-rw-r--r--src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java25
-rw-r--r--src/com/android/launcher3/testing/DummyWidget.java53
-rw-r--r--src/com/android/launcher3/testing/LauncherExtension.java9
-rw-r--r--src/com/android/launcher3/util/ManagedProfileHeuristic.java2
-rw-r--r--src/com/android/launcher3/util/SystemUiController.java2
-rw-r--r--src/com/android/launcher3/util/TestingUtils.java19
-rw-r--r--src/com/android/launcher3/util/TraceHelper.java90
-rw-r--r--src/com/android/launcher3/util/UiThreadHelper.java76
-rw-r--r--src/com/android/launcher3/util/WallpaperOffsetInterpolator.java295
-rw-r--r--src/com/android/launcher3/widget/PendingAddWidgetInfo.java4
-rw-r--r--src/com/android/launcher3/widget/PendingItemDragHelper.java67
-rw-r--r--src/com/android/launcher3/widget/WidgetHostViewLoader.java4
-rw-r--r--src/com/android/launcher3/widget/WidgetsBottomSheet.java35
-rw-r--r--src/com/android/launcher3/widget/WidgetsContainerView.java19
-rw-r--r--src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java103
-rw-r--r--src/com/android/launcher3/widget/custom/CustomWidgetParser.java142
92 files changed, 1447 insertions, 2140 deletions
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index 597e93703..49968189b 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -25,6 +25,8 @@ import android.view.View;
import android.widget.LinearLayout;
import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
+import com.android.launcher3.util.TouchController;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -32,18 +34,20 @@ import java.lang.annotation.RetentionPolicy;
/**
* Base class for a View which shows a floating UI on top of the launcher UI.
*/
-public abstract class AbstractFloatingView extends LinearLayout {
+public abstract class AbstractFloatingView extends LinearLayout implements TouchController {
@IntDef(flag = true, value = {
TYPE_FOLDER,
TYPE_POPUP_CONTAINER_WITH_ARROW,
- TYPE_WIDGETS_BOTTOM_SHEET
+ TYPE_WIDGETS_BOTTOM_SHEET,
+ TYPE_WIDGET_RESIZE_FRAME
})
@Retention(RetentionPolicy.SOURCE)
public @interface FloatingViewType {}
public static final int TYPE_FOLDER = 1 << 0;
public static final int TYPE_POPUP_CONTAINER_WITH_ARROW = 1 << 1;
public static final int TYPE_WIDGETS_BOTTOM_SHEET = 1 << 2;
+ public static final int TYPE_WIDGET_RESIZE_FRAME = 1 << 3;
protected boolean mIsOpen;
@@ -72,21 +76,7 @@ public abstract class AbstractFloatingView extends LinearLayout {
protected abstract void handleClose(boolean animate);
- /**
- * If the view is current handling keyboard, return the active target, null otherwise
- */
- public ExtendedEditText getActiveTextView() {
- return null;
- }
-
-
- /**
- * Any additional view (outside of this container) where touch should be allowed while this
- * view is visible.
- */
- public View getExtendedTouchView() {
- return null;
- }
+ public abstract void logActionCommand(int command);
public final boolean isOpen() {
return mIsOpen;
@@ -97,6 +87,16 @@ public abstract class AbstractFloatingView extends LinearLayout {
protected abstract boolean isOfType(@FloatingViewType int type);
+ public void onBackPressed() {
+ logActionCommand(Action.Command.BACK);
+ close(true);
+ }
+
+ @Override
+ public boolean onControllerTouchEvent(MotionEvent ev) {
+ return false;
+ }
+
protected static <T extends AbstractFloatingView> T getOpenView(
Launcher launcher, @FloatingViewType int type) {
DragLayer dragLayer = launcher.getDragLayer();
@@ -139,8 +139,6 @@ public abstract class AbstractFloatingView extends LinearLayout {
public static AbstractFloatingView getTopOpenView(Launcher launcher) {
return getOpenView(launcher, TYPE_FOLDER | TYPE_POPUP_CONTAINER_WITH_ARROW
- | TYPE_WIDGETS_BOTTOM_SHEET);
+ | TYPE_WIDGETS_BOTTOM_SHEET | TYPE_WIDGET_RESIZE_FRAME);
}
-
- public abstract int getLogContainerType();
}
diff --git a/src/com/android/launcher3/AppInfo.java b/src/com/android/launcher3/AppInfo.java
index 3da199635..7d2f75385 100644
--- a/src/com/android/launcher3/AppInfo.java
+++ b/src/com/android/launcher3/AppInfo.java
@@ -19,6 +19,7 @@ package com.android.launcher3;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherActivityInfo;
import android.os.UserHandle;
@@ -31,6 +32,10 @@ import com.android.launcher3.util.PackageManagerHelper;
*/
public class AppInfo extends ItemInfoWithIcon {
+ public static final int FLAG_SYSTEM_UNKNOWN = 0;
+ public static final int FLAG_SYSTEM_YES = 1 << 0;
+ public static final int FLAG_SYSTEM_NO = 1 << 1;
+
/**
* The intent used to start the application.
*/
@@ -43,6 +48,11 @@ public class AppInfo extends ItemInfoWithIcon {
*/
public int isDisabled = ShortcutInfo.DEFAULT;
+ /**
+ * Stores if the app is a system app or not.
+ */
+ public int isSystemApp;
+
public AppInfo() {
itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
}
@@ -71,6 +81,10 @@ public class AppInfo extends ItemInfoWithIcon {
}
intent = makeLaunchIntent(info);
+
+ isSystemApp = (info.getApplicationInfo().flags & ApplicationInfo.FLAG_SYSTEM) == 0
+ ? FLAG_SYSTEM_NO : FLAG_SYSTEM_YES;
+
}
public AppInfo(AppInfo info) {
@@ -79,6 +93,7 @@ public class AppInfo extends ItemInfoWithIcon {
title = Utilities.trim(info.title);
intent = new Intent(info.intent);
isDisabled = info.isDisabled;
+ isSystemApp = info.isSystemApp;
}
@Override
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index a486a3aa3..1e95333ff 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -8,22 +8,19 @@ import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
-import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
-import android.widget.FrameLayout;
+import android.view.ViewGroup;
import com.android.launcher3.accessibility.DragViewStateAnnouncer;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.util.FocusLogic;
-import com.android.launcher3.util.TouchController;
-public class AppWidgetResizeFrame extends FrameLayout
- implements View.OnKeyListener, TouchController {
+public class AppWidgetResizeFrame extends AbstractFloatingView implements View.OnKeyListener {
private static final int SNAP_DURATION = 150;
private static final float DIMMED_HANDLE_ALPHA = 0f;
private static final float RESIZE_THRESHOLD = 0.66f;
@@ -109,12 +106,28 @@ public class AppWidgetResizeFrame extends FrameLayout
protected void onFinishInflate() {
super.onFinishInflate();
+ ViewGroup content = (ViewGroup) getChildAt(0);
for (int i = 0; i < HANDLE_COUNT; i ++) {
- mDragHandles[i] = getChildAt(i);
+ mDragHandles[i] = content.getChildAt(i);
}
}
- public void setupForWidget(LauncherAppWidgetHostView widgetView, CellLayout cellLayout,
+ public static void showForWidget(LauncherAppWidgetHostView widget, CellLayout cellLayout) {
+ Launcher launcher = Launcher.getLauncher(cellLayout.getContext());
+ AbstractFloatingView.closeAllOpenViews(launcher);
+
+ DragLayer dl = launcher.getDragLayer();
+ AppWidgetResizeFrame frame = (AppWidgetResizeFrame) launcher.getLayoutInflater()
+ .inflate(R.layout.app_widget_resize_frame, dl, false);
+ frame.setupForWidget(widget, cellLayout, dl);
+ ((DragLayer.LayoutParams) frame.getLayoutParams()).customPosition = true;
+
+ dl.addView(frame);
+ frame.mIsOpen = true;
+ frame.snapToWidget(false);
+ }
+
+ private void setupForWidget(LauncherAppWidgetHostView widgetView, CellLayout cellLayout,
DragLayer dragLayer) {
mCellLayout = cellLayout;
mWidgetView = widgetView;
@@ -126,14 +139,8 @@ public class AppWidgetResizeFrame extends FrameLayout
mMinHSpan = info.minSpanX;
mMinVSpan = info.minSpanY;
- if (!info.isCustomWidget) {
- mWidgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(getContext(),
- widgetView.getAppWidgetInfo().provider, null);
- } else {
- Resources r = getContext().getResources();
- int padding = r.getDimensionPixelSize(R.dimen.default_widget_padding);
- mWidgetPadding = new Rect(padding, padding, padding, padding);
- }
+ mWidgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(getContext(),
+ widgetView.getAppWidgetInfo().provider, null);
if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) {
mDragHandles[INDEX_TOP].setVisibility(GONE);
@@ -391,7 +398,7 @@ public class AppWidgetResizeFrame extends FrameLayout
out.bottom = out.top + height;
}
- public void snapToWidget(boolean animate) {
+ private void snapToWidget(boolean animate) {
getSnappedRectRelativeToDragLayer(sTmpRect);
int newWidth = sTmpRect.width();
int newHeight = sTmpRect.height();
@@ -455,7 +462,7 @@ public class AppWidgetResizeFrame extends FrameLayout
public boolean onKey(View v, int keyCode, KeyEvent event) {
// Clear the frame and give focus to the widget host view when a directional key is pressed.
if (FocusLogic.shouldConsume(keyCode)) {
- mDragLayer.clearResizeFrame();
+ close(false);
mWidgetView.requestFocus();
return true;
}
@@ -505,9 +512,25 @@ public class AppWidgetResizeFrame extends FrameLayout
if (ev.getAction() == MotionEvent.ACTION_DOWN && handleTouchDown(ev)) {
return true;
}
+ close(false);
return false;
}
+ @Override
+ protected void handleClose(boolean animate) {
+ mDragLayer.removeView(this);
+ }
+
+ @Override
+ public void logActionCommand(int command) {
+ // TODO: Log this case.
+ }
+
+ @Override
+ protected boolean isOfType(int type) {
+ return (type & TYPE_WIDGET_RESIZE_FRAME) != 0;
+ }
+
/**
* A mutable class for describing the range of two int values.
*/
diff --git a/src/com/android/launcher3/AutoInstallsLayout.java b/src/com/android/launcher3/AutoInstallsLayout.java
index d82579bf7..162aa0889 100644
--- a/src/com/android/launcher3/AutoInstallsLayout.java
+++ b/src/com/android/launcher3/AutoInstallsLayout.java
@@ -28,7 +28,9 @@ import android.content.res.XmlResourceParser;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
+import android.os.Process;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
@@ -433,8 +435,10 @@ public class AutoInstallsLayout {
return -1;
}
- mValues.put(LauncherSettings.Favorites.ICON,
- Utilities.flattenBitmap(LauncherIcons.createIconBitmap(icon, mContext)));
+ // Auto installs should always support the current platform version.
+ mValues.put(LauncherSettings.Favorites.ICON, Utilities.flattenBitmap(
+ LauncherIcons.createBadgedIconBitmap(
+ icon, Process.myUserHandle(), mContext, Build.VERSION.SDK_INT)));
mValues.put(Favorites.ICON_PACKAGE, mIconRes.getResourcePackageName(iconId));
mValues.put(Favorites.ICON_RESOURCE, mIconRes.getResourceName(iconId));
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index ac842f92e..485125e03 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -496,11 +496,17 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver {
public PreloadIconDrawable applyProgressLevel(int progressLevel) {
if (getTag() instanceof ItemInfoWithIcon) {
ItemInfoWithIcon info = (ItemInfoWithIcon) getTag();
- setContentDescription(progressLevel > 0
- ? getContext().getString(R.string.app_downloading_title, info.title,
- NumberFormat.getPercentInstance().format(progressLevel * 0.01))
- : getContext().getString(R.string.app_waiting_download_title, info.title));
-
+ if (progressLevel >= 100) {
+ setContentDescription(info.contentDescription != null
+ ? info.contentDescription : "");
+ } else if (progressLevel > 0) {
+ setContentDescription(getContext()
+ .getString(R.string.app_downloading_title, info.title,
+ NumberFormat.getPercentInstance().format(progressLevel * 0.01)));
+ } else {
+ setContentDescription(getContext()
+ .getString(R.string.app_waiting_download_title, info.title));
+ }
if (mIcon != null) {
final PreloadIconDrawable preloadDrawable;
if (mIcon instanceof PreloadIconDrawable) {
diff --git a/src/com/android/launcher3/ButtonDropTarget.java b/src/com/android/launcher3/ButtonDropTarget.java
index 632e49059..375930062 100644
--- a/src/com/android/launcher3/ButtonDropTarget.java
+++ b/src/com/android/launcher3/ButtonDropTarget.java
@@ -178,7 +178,7 @@ public abstract class ButtonDropTarget extends TextView
@Override
public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
- mActive = supportsDrop(dragObject.dragSource, dragObject.dragInfo);
+ mActive = supportsDrop(dragObject.dragInfo);
mDrawable.setColorFilter(null);
if (mCurrentColorAnim != null) {
mCurrentColorAnim.cancel();
@@ -194,10 +194,10 @@ public abstract class ButtonDropTarget extends TextView
@Override
public final boolean acceptDrop(DragObject dragObject) {
- return supportsDrop(dragObject.dragSource, dragObject.dragInfo);
+ return supportsDrop(dragObject.dragInfo);
}
- protected abstract boolean supportsDrop(DragSource source, ItemInfo info);
+ protected abstract boolean supportsDrop(ItemInfo info);
@Override
public boolean isDropEnabled() {
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index f83574808..d92b934d1 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -355,10 +355,6 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
mShortcutsAndWidgets.setLayerType(hasLayer ? LAYER_TYPE_HARDWARE : LAYER_TYPE_NONE, sPaint);
}
- public void buildHardwareLayer() {
- mShortcutsAndWidgets.buildLayer();
- }
-
public void setCellDimensions(int width, int height) {
mFixedCellWidth = mCellWidth = width;
mFixedCellHeight = mCellHeight = height;
diff --git a/src/com/android/launcher3/CustomAppWidget.java b/src/com/android/launcher3/CustomAppWidget.java
deleted file mode 100644
index 1b4ed79c0..000000000
--- a/src/com/android/launcher3/CustomAppWidget.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.android.launcher3;
-
-public interface CustomAppWidget {
- public String getLabel();
- public int getPreviewImage();
- public int getIcon();
- public int getWidgetLayout();
-
- public int getSpanX();
- public int getSpanY();
- public int getMinSpanX();
- public int getMinSpanY();
- public int getResizeMode();
-}
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index 4dcb64f01..fdd4f34bd 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -46,7 +46,7 @@ public class DeleteDropTarget extends ButtonDropTarget {
@Override
public void onDragStart(DropTarget.DragObject dragObject, DragOptions options) {
super.onDragStart(dragObject, options);
- setTextBasedOnDragSource(dragObject.dragSource);
+ setTextBasedOnDragSource(dragObject.dragInfo);
}
/** @return true for items that should have a "Remove" action in accessibility. */
@@ -57,16 +57,16 @@ public class DeleteDropTarget extends ButtonDropTarget {
}
@Override
- protected boolean supportsDrop(DragSource source, ItemInfo info) {
+ protected boolean supportsDrop(ItemInfo info) {
return true;
}
/**
- * Set the drop target's text to either "Remove" or "Cancel" depending on the drag source.
+ * Set the drop target's text to either "Remove" or "Cancel" depending on the drag item.
*/
- public void setTextBasedOnDragSource(DragSource dragSource) {
+ private void setTextBasedOnDragSource(ItemInfo item) {
if (!TextUtils.isEmpty(mText)) {
- mText = getResources().getString(dragSource.supportsDeleteDropTarget()
+ mText = getResources().getString(item.id != ItemInfo.NO_ID
? R.string.remove_drop_target_label
: android.R.string.cancel);
requestLayout();
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index dec0a92a9..8f7e8822b 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -277,8 +277,12 @@ public class DeviceProfile {
DeviceProfile profile = new DeviceProfile(context, inv, mwSize, mwSize, mwSize.x, mwSize.y,
isLandscape);
- // Hide labels on the workspace.
- profile.adjustToHideWorkspaceLabels();
+ // If there isn't enough vertical cell padding with the labels displayed, hide the labels.
+ float workspaceCellPaddingY = profile.getCellSize().y - profile.iconSizePx
+ - iconDrawablePaddingPx - profile.iconTextSizePx;
+ if (workspaceCellPaddingY < profile.iconDrawablePaddingPx * 2) {
+ profile.adjustToHideWorkspaceLabels();
+ }
// We use these scales to measure and layout the widgets using their full invariant profile
// sizes and then draw them scaled and centered to fit in their multi-window mode cellspans.
@@ -350,9 +354,18 @@ public class DeviceProfile {
iconTextSizePx = (int) (Utilities.pxFromSp(inv.iconTextSize, dm) * scale);
iconDrawablePaddingPx = (int) (iconDrawablePaddingOriginalPx * scale);
- cellWidthPx = iconSizePx + iconDrawablePaddingPx;
cellHeightPx = iconSizePx + iconDrawablePaddingPx
+ Utilities.calculateTextHeight(iconTextSizePx);
+ int cellYPadding = (getCellSize().y - cellHeightPx) / 2;
+ if (iconDrawablePaddingPx > cellYPadding && !isVerticalBarLayout()
+ && !inMultiWindowMode()) {
+ // Ensures that the label is closer to its corresponding icon. This is not an issue
+ // with vertical bar layout or multi-window mode since the issue is handled separately
+ // with their calls to {@link #adjustToHideWorkspaceLabels}.
+ cellHeightPx -= (iconDrawablePaddingPx - cellYPadding);
+ iconDrawablePaddingPx = cellYPadding;
+ }
+ cellWidthPx = iconSizePx + iconDrawablePaddingPx;
// All apps
allAppsIconTextSizePx = iconTextSizePx;
@@ -755,11 +768,14 @@ public class DeviceProfile {
return new int[] { padding.left - mInsets.left, padding.right + mInsets.left};
}
+ public boolean inMultiWindowMode() {
+ return this != inv.landscapeProfile && this != inv.portraitProfile;
+ }
+
public boolean shouldIgnoreLongPressToOverview(float touchX) {
- boolean inMultiWindowMode = this != inv.landscapeProfile && this != inv.portraitProfile;
boolean touchedLhsEdge = mInsets.left == 0 && touchX < edgeMarginPx;
boolean touchedRhsEdge = mInsets.right == 0 && touchX > (widthPx - edgeMarginPx);
- return !inMultiWindowMode && (touchedLhsEdge || touchedRhsEdge);
+ return !inMultiWindowMode() && (touchedLhsEdge || touchedRhsEdge);
}
private static Context getContext(Context c, int orientation) {
diff --git a/src/com/android/launcher3/DragSource.java b/src/com/android/launcher3/DragSource.java
index dcd8f589a..c6106c23e 100644
--- a/src/com/android/launcher3/DragSource.java
+++ b/src/com/android/launcher3/DragSource.java
@@ -27,22 +27,6 @@ import com.android.launcher3.logging.UserEventDispatcher.LogContainerProvider;
public interface DragSource extends LogContainerProvider {
/**
- * @return whether items dragged from this source supports 'App Info'
- */
- boolean supportsAppInfoDropTarget();
-
- /**
- * @return whether items dragged from this source supports 'Delete' drop target (e.g. to remove
- * a shortcut.) If this returns false, the drop target will say "Cancel" instead of "Remove."
- */
- boolean supportsDeleteDropTarget();
-
- /*
- * @return the scale of the icons over the workspace icon size
- */
- float getIntrinsicIconScaleFactor();
-
- /**
* A callback made back to the source after an item from this source has been dropped on a
* DropTarget.
*/
diff --git a/src/com/android/launcher3/ExtendedEditText.java b/src/com/android/launcher3/ExtendedEditText.java
index 596aa8f7b..403c8b8ba 100644
--- a/src/com/android/launcher3/ExtendedEditText.java
+++ b/src/com/android/launcher3/ExtendedEditText.java
@@ -16,12 +16,16 @@
package com.android.launcher3;
import android.content.Context;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.DragEvent;
import android.view.KeyEvent;
+import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
+import com.android.launcher3.util.UiThreadHelper;
+
/**
* The edit text that reports back when the back key has been pressed.
@@ -102,8 +106,7 @@ public class ExtendedEditText extends EditText {
}
public void dispatchBackKey() {
- ((InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE))
- .hideSoftInputFromWindow(getWindowToken(), 0);
+ UiThreadHelper.hideKeyboardAsync(getContext(), getWindowToken());
if (mBackKeyListener != null) {
mBackKeyListener.onBackKey();
}
@@ -121,4 +124,17 @@ public class ExtendedEditText extends EditText {
public boolean isSuggestionsEnabled() {
return !mForceDisableSuggestions && super.isSuggestionsEnabled();
}
+
+ public void reset() {
+ if (!TextUtils.isEmpty(getText())) {
+ setText("");
+ }
+ if (isFocused()) {
+ View nextFocus = focusSearch(View.FOCUS_DOWN);
+ if (nextFocus != null) {
+ nextFocus.requestFocus();
+ }
+ }
+ UiThreadHelper.hideKeyboardAsync(getContext(), getWindowToken());
+ }
}
diff --git a/src/com/android/launcher3/FirstFrameAnimatorHelper.java b/src/com/android/launcher3/FirstFrameAnimatorHelper.java
index 3cbc989eb..cea7e431a 100644
--- a/src/com/android/launcher3/FirstFrameAnimatorHelper.java
+++ b/src/com/android/launcher3/FirstFrameAnimatorHelper.java
@@ -24,6 +24,7 @@ import android.view.View;
import android.view.ViewPropertyAnimator;
import android.view.ViewTreeObserver;
import com.android.launcher3.util.Thunk;
+import com.android.launcher3.util.TraceHelper;
/*
* This is a helper class that listens to updates from the corresponding animation.
@@ -71,15 +72,12 @@ public class FirstFrameAnimatorHelper extends AnimatorListenerAdapter
if (sGlobalDrawListener != null) {
view.getViewTreeObserver().removeOnDrawListener(sGlobalDrawListener);
}
+
+ TraceHelper.beginSection("TICK");
sGlobalDrawListener = new ViewTreeObserver.OnDrawListener() {
- private long mTime = System.currentTimeMillis();
public void onDraw() {
sGlobalFrameCounter++;
- if (DEBUG) {
- long newTime = System.currentTimeMillis();
- Log.d(TAG, "TICK " + (newTime - mTime));
- mTime = newTime;
- }
+ TraceHelper.partitionSection("TICK", "Frame drawn");
}
};
view.getViewTreeObserver().addOnDrawListener(sGlobalDrawListener);
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index af3abebb4..09f9e827c 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -16,16 +16,9 @@
package com.android.launcher3;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ArgbEvaluator;
-import android.animation.ValueAnimator;
import android.content.Context;
-import android.graphics.Color;
import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.support.v4.graphics.ColorUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
@@ -35,11 +28,9 @@ import android.widget.FrameLayout;
import android.widget.TextView;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.dynamicui.ExtractedColors;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
-import com.android.launcher3.util.Themes;
public class Hotseat extends FrameLayout
implements UserEventDispatcher.LogContainerProvider {
@@ -51,12 +42,6 @@ public class Hotseat extends FrameLayout
@ViewDebug.ExportedProperty(category = "launcher")
private final boolean mHasVerticalHotseat;
- @ViewDebug.ExportedProperty(category = "launcher")
- private int mBackgroundColor;
- @ViewDebug.ExportedProperty(category = "launcher")
- private ColorDrawable mBackground;
- private ValueAnimator mBackgroundColorAnimator;
-
public Hotseat(Context context) {
this(context, null);
}
@@ -69,12 +54,6 @@ public class Hotseat extends FrameLayout
super(context, attrs, defStyle);
mLauncher = Launcher.getLauncher(context);
mHasVerticalHotseat = mLauncher.getDeviceProfile().isVerticalBarLayout();
- mBackgroundColor = ColorUtils.setAlphaComponent(
- Themes.getAttrColor(context, android.R.attr.colorPrimary), 0);
- mBackground = new ColorDrawable(mBackgroundColor);
- if (!FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
- setBackground(mBackground);
- }
}
public CellLayout getLayout() {
@@ -149,7 +128,6 @@ public class Hotseat extends FrameLayout
allAppsButton.setOnKeyListener(new HotseatIconKeyEventListener());
if (mLauncher != null) {
mLauncher.setAllAppsButton(allAppsButton);
- allAppsButton.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
allAppsButton.setOnClickListener(mLauncher);
allAppsButton.setOnFocusChangeListener(mLauncher.mFocusHandler);
}
@@ -178,49 +156,4 @@ public class Hotseat extends FrameLayout
target.gridY = info.cellY;
targetParent.containerType = ContainerType.HOTSEAT;
}
-
- public void updateColor(ExtractedColors extractedColors, boolean animate) {
- if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
- // not hotseat visible
- return;
- }
- if (!mHasVerticalHotseat) {
- int color = extractedColors.getColor(ExtractedColors.HOTSEAT_INDEX);
- if (mBackgroundColorAnimator != null) {
- mBackgroundColorAnimator.cancel();
- }
- if (!animate) {
- setBackgroundColor(color);
- } else {
- mBackgroundColorAnimator = ValueAnimator.ofInt(mBackgroundColor, color);
- mBackgroundColorAnimator.setEvaluator(new ArgbEvaluator());
- mBackgroundColorAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- mBackground.setColor((Integer) animation.getAnimatedValue());
- }
- });
- mBackgroundColorAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mBackgroundColorAnimator = null;
- }
- });
- mBackgroundColorAnimator.start();
- }
- mBackgroundColor = color;
- }
- }
-
- public void setBackgroundTransparent(boolean enable) {
- if (enable) {
- mBackground.setAlpha(0);
- } else {
- mBackground.setAlpha(255);
- }
- }
-
- public int getBackgroundDrawableColor() {
- return mBackgroundColor;
- }
}
diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java
index 6f86954dc..573e8a256 100644
--- a/src/com/android/launcher3/IconCache.java
+++ b/src/com/android/launcher3/IconCache.java
@@ -123,7 +123,7 @@ public class IconCache {
}
private Drawable getFullResDefaultActivityIcon() {
- return getFullResIcon(Resources.getSystem(), Utilities.isAtLeastO() ?
+ return getFullResIcon(Resources.getSystem(), Utilities.ATLEAST_OREO ?
android.R.drawable.sym_def_app_icon : android.R.mipmap.sym_def_app_icon);
}
diff --git a/src/com/android/launcher3/InfoDropTarget.java b/src/com/android/launcher3/InfoDropTarget.java
index f919dd052..eb6a7045e 100644
--- a/src/com/android/launcher3/InfoDropTarget.java
+++ b/src/com/android/launcher3/InfoDropTarget.java
@@ -99,8 +99,8 @@ public class InfoDropTarget extends UninstallDropTarget {
}
@Override
- protected boolean supportsDrop(DragSource source, ItemInfo info) {
- return source.supportsAppInfoDropTarget() && supportsDrop(getContext(), info);
+ protected boolean supportsDrop(ItemInfo info) {
+ return supportsDrop(getContext(), info);
}
public static boolean supportsDrop(Context context, ItemInfo info) {
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index d7bebd1b1..7a431986d 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -85,7 +85,9 @@ public class InvariantDeviceProfile {
* Number of icons inside the hotseat area.
*/
public int numHotseatIcons;
+
int defaultLayoutId;
+ int demoModeLayoutId;
public DeviceProfile landscapeProfile;
public DeviceProfile portraitProfile;
@@ -99,11 +101,11 @@ public class InvariantDeviceProfile {
this(p.name, p.minWidthDps, p.minHeightDps, p.numRows, p.numColumns,
p.numFolderRows, p.numFolderColumns, p.minAllAppsPredictionColumns,
p.iconSize, p.landscapeIconSize, p.iconTextSize, p.numHotseatIcons,
- p.defaultLayoutId);
+ p.defaultLayoutId, p.demoModeLayoutId);
}
InvariantDeviceProfile(String n, float w, float h, int r, int c, int fr, int fc, int maapc,
- float is, float lis, float its, int hs, int dlId) {
+ float is, float lis, float its, int hs, int dlId, int dmlId) {
name = n;
minWidthDps = w;
minHeightDps = h;
@@ -117,6 +119,7 @@ public class InvariantDeviceProfile {
iconTextSize = its;
numHotseatIcons = hs;
defaultLayoutId = dlId;
+ demoModeLayoutId = dmlId;
}
@TargetApi(23)
@@ -144,6 +147,7 @@ public class InvariantDeviceProfile {
numColumns = closestProfile.numColumns;
numHotseatIcons = closestProfile.numHotseatIcons;
defaultLayoutId = closestProfile.defaultLayoutId;
+ demoModeLayoutId = closestProfile.demoModeLayoutId;
numFolderRows = closestProfile.numFolderRows;
numFolderColumns = closestProfile.numFolderColumns;
minAllAppsPredictionColumns = closestProfile.minAllAppsPredictionColumns;
@@ -208,7 +212,8 @@ public class InvariantDeviceProfile {
a.getFloat(R.styleable.InvariantDeviceProfile_landscapeIconSize, iconSize),
a.getFloat(R.styleable.InvariantDeviceProfile_iconTextSize, 0),
a.getInt(R.styleable.InvariantDeviceProfile_numHotseatIcons, numColumns),
- a.getResourceId(R.styleable.InvariantDeviceProfile_defaultLayoutId, 0)));
+ a.getResourceId(R.styleable.InvariantDeviceProfile_defaultLayoutId, 0),
+ a.getResourceId(R.styleable.InvariantDeviceProfile_demoModeLayoutId, 0)));
a.recycle();
}
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index c22a04aa9..ba31926c2 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -16,6 +16,9 @@
package com.android.launcher3;
+import static com.android.launcher3.util.RunnableWithId.RUNNABLE_ID_BIND_APPS;
+import static com.android.launcher3.util.RunnableWithId.RUNNABLE_ID_BIND_WIDGETS;
+
import android.Manifest;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -53,8 +56,6 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Process;
import android.os.StrictMode;
-import android.os.SystemClock;
-import android.os.Trace;
import android.os.UserHandle;
import android.support.annotation.Nullable;
import android.text.Selection;
@@ -73,7 +74,6 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -91,13 +91,13 @@ import com.android.launcher3.anim.AnimationLayerSet;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.LauncherAppsCompatVO;
+import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.dragndrop.DragView;
import com.android.launcher3.dragndrop.PinItemDragListener;
-import com.android.launcher3.dynamicui.ExtractedColors;
import com.android.launcher3.dynamicui.WallpaperColorInfo;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon;
@@ -118,7 +118,6 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
import com.android.launcher3.util.ActivityResultInfo;
-import com.android.launcher3.util.RunnableWithId;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.ComponentKeyMapper;
import com.android.launcher3.util.ItemInfoMatcher;
@@ -126,30 +125,30 @@ import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.PendingRequestArgs;
+import com.android.launcher3.util.RunnableWithId;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.TestingUtils;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.Thunk;
+import com.android.launcher3.util.TraceHelper;
+import com.android.launcher3.util.UiThreadHelper;
import com.android.launcher3.util.ViewOnDrawExecutor;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import com.android.launcher3.widget.PendingAddWidgetInfo;
import com.android.launcher3.widget.WidgetAddFlowHandler;
import com.android.launcher3.widget.WidgetHostViewLoader;
import com.android.launcher3.widget.WidgetsContainerView;
+import com.android.launcher3.widget.custom.CustomWidgetParser;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executor;
-import static com.android.launcher3.util.RunnableWithId.RUNNABLE_ID_BIND_APPS;
-import static com.android.launcher3.util.RunnableWithId.RUNNABLE_ID_BIND_WIDGETS;
-
/**
* Default launcher application.
*/
@@ -161,9 +160,7 @@ public class Launcher extends BaseActivity
public static final String TAG = "Launcher";
static final boolean LOGD = false;
- static final boolean DEBUG_WIDGETS = false;
static final boolean DEBUG_STRICT_MODE = false;
- static final boolean DEBUG_RESUME_TIME = false;
private static final int REQUEST_CREATE_SHORTCUT = 1;
private static final int REQUEST_CREATE_APPWIDGET = 5;
@@ -222,8 +219,6 @@ public class Launcher extends BaseActivity
private static final int NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS = 5;
@Thunk static final int NEW_APPS_ANIMATION_DELAY = 500;
- private final ExtractedColors mExtractedColors = new ExtractedColors();
-
@Thunk Workspace mWorkspace;
private View mLauncherView;
@Thunk DragLayer mDragLayer;
@@ -251,6 +246,10 @@ public class Launcher extends BaseActivity
// Main container view and the model for the widget tray screen.
@Thunk WidgetsContainerView mWidgetsView;
+ // We need to store the orientation Launcher was created with, due to a bug (b/64916689)
+ // that results in widgets being inflated in the wrong orientation.
+ private int mOrientation;
+
// We set the state in both onCreate and then onNewIntent in some cases, which causes both
// scroll issues (because the workspace may not have been measured yet) and extra work.
// Instead, just save the state that we need to restore Launcher to, and commit it in onResume.
@@ -279,8 +278,6 @@ public class Launcher extends BaseActivity
private PopupDataProvider mPopupDataProvider;
- private View.OnTouchListener mHapticFeedbackTouchListener;
-
// Determines how long to wait after a rotation before restoring the screen orientation to
// match the sensor state.
private static final int RESTORE_SCREEN_ORIENTATION_DELAY = 500;
@@ -296,28 +293,11 @@ public class Launcher extends BaseActivity
// the press state and keep this reference to reset the press state when we return to launcher.
private BubbleTextView mWaitingForResume;
- protected static final HashMap<String, CustomAppWidget> sCustomAppWidgets =
- new HashMap<>();
-
- static {
- if (TestingUtils.ENABLE_CUSTOM_WIDGET_TEST) {
- TestingUtils.addDummyWidget(sCustomAppWidgets);
- }
- }
-
// Exiting spring loaded mode happens with a delay. This runnable object triggers the
// state transition. If another state transition happened during this delay,
// simply unregister this runnable.
private Runnable mExitSpringLoadedModeRunnable;
- @Thunk final Runnable mBuildLayersRunnable = new Runnable() {
- public void run() {
- if (mWorkspace != null) {
- mWorkspace.buildPageHardwareLayers();
- }
- }
- };
-
// Activity result which needs to be processed after workspace has loaded.
private ActivityResultInfo mPendingActivityResult;
/**
@@ -358,9 +338,7 @@ public class Launcher extends BaseActivity
.penaltyDeath()
.build());
}
- if (LauncherAppState.PROFILE_STARTUP) {
- Trace.beginSection("Launcher-onCreate");
- }
+ TraceHelper.beginSection("Launcher-onCreate");
if (mLauncherCallbacks != null) {
mLauncherCallbacks.preOnCreate();
@@ -371,6 +349,7 @@ public class Launcher extends BaseActivity
overrideTheme(wallpaperColorInfo.isDark(), wallpaperColorInfo.supportsDarkText());
super.onCreate(savedInstanceState);
+ TraceHelper.partitionSection("Launcher-onCreate", "super call");
LauncherAppState app = LauncherAppState.getInstance(this);
@@ -383,6 +362,7 @@ public class Launcher extends BaseActivity
mDeviceProfile = mDeviceProfile.getMultiWindowProfile(this, mwSize);
}
+ mOrientation = getResources().getConfiguration().orientation;
mSharedPrefs = Utilities.getPrefs(this);
mIsSafeModeEnabled = getPackageManager().isSafeMode();
mModel = app.setLauncher(this);
@@ -411,7 +391,6 @@ public class Launcher extends BaseActivity
setupViews();
mDeviceProfile.layout(this, false /* notifyListeners */);
- loadExtractedColorsAndColorItems();
mPopupDataProvider = new PopupDataProvider(this);
@@ -420,10 +399,6 @@ public class Launcher extends BaseActivity
restoreState(savedInstanceState);
- if (LauncherAppState.PROFILE_STARTUP) {
- Trace.endSection();
- }
-
// We only load the page synchronously if the user rotates (or triggers a
// configuration change) while launcher is in the foreground
int currentScreen = PagedView.INVALID_RESTORE_PAGE;
@@ -478,6 +453,8 @@ public class Launcher extends BaseActivity
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onCreate(savedInstanceState);
}
+
+ TraceHelper.endSection("Launcher-onCreate");
}
@Override
@@ -499,27 +476,12 @@ public class Launcher extends BaseActivity
}
@Override
- public void onExtractedColorsChanged() {
- loadExtractedColorsAndColorItems();
- mExtractedColors.notifyChange();
- }
-
- @Override
public void onAppWidgetHostReset() {
if (mAppWidgetHost != null) {
mAppWidgetHost.startListening();
}
}
- private void loadExtractedColorsAndColorItems() {
- // TODO: do this in pre-N as well, once the extraction part is complete.
- if (Utilities.ATLEAST_NOUGAT) {
- mExtractedColors.load(this);
- mHotseat.updateColor(mExtractedColors, !mPaused);
- mWorkspace.getPageIndicator().updateColor(mExtractedColors);
- }
- }
-
private LauncherCallbacks mLauncherCallbacks;
public void onPostCreate(Bundle savedInstanceState) {
@@ -892,34 +854,23 @@ public class Launcher extends BaseActivity
@Override
protected void onResume() {
- long startTime = 0;
- if (DEBUG_RESUME_TIME) {
- startTime = System.currentTimeMillis();
- Log.v(TAG, "Launcher.onResume()");
- }
-
+ TraceHelper.beginSection("ON_RESUME");
if (mLauncherCallbacks != null) {
mLauncherCallbacks.preOnResume();
}
-
super.onResume();
+ TraceHelper.partitionSection("ON_RESUME", "superCall");
+
getUserEventDispatcher().resetElapsedSessionMillis();
// Restore the previous launcher state
if (mOnResumeState == State.WORKSPACE) {
showWorkspace(false);
} else if (mOnResumeState == State.APPS) {
- boolean launchedFromApp = (mWaitingForResume != null);
- // Don't update the predicted apps if the user is returning to launcher in the apps
- // view after launching an app, as they may be depending on the UI to be static to
- // switch to another app, otherwise, if it was
- showAppsView(false /* animated */, !launchedFromApp /* updatePredictedApps */);
+ showAppsView(false /* animated */);
} else if (mOnResumeState == State.WIDGETS) {
showWidgetsView(false, false);
}
- if (mOnResumeState != State.APPS) {
- tryAndUpdatePredictedApps();
- }
mOnResumeState = State.NONE;
mPaused = false;
@@ -931,19 +882,10 @@ public class Launcher extends BaseActivity
if (mBindOnResumeCallbacks.size() > 0) {
// We might have postponed some bind calls until onResume (see waitUntilResume) --
// execute them here
- long startTimeCallbacks = 0;
- if (DEBUG_RESUME_TIME) {
- startTimeCallbacks = System.currentTimeMillis();
- }
-
for (int i = 0; i < mBindOnResumeCallbacks.size(); i++) {
mBindOnResumeCallbacks.get(i).run();
}
mBindOnResumeCallbacks.clear();
- if (DEBUG_RESUME_TIME) {
- Log.d(TAG, "Time spent processing callbacks in onResume: " +
- (System.currentTimeMillis() - startTimeCallbacks));
- }
}
if (mOnResumeCallbacks.size() > 0) {
for (int i = 0; i < mOnResumeCallbacks.size(); i++) {
@@ -959,20 +901,7 @@ public class Launcher extends BaseActivity
mWaitingForResume.setStayPressed(false);
}
- // It is possible that widgets can receive updates while launcher is not in the foreground.
- // Consequently, the widgets will be inflated in the orientation of the foreground activity
- // (framework issue). On resuming, we ensure that any widgets are inflated for the current
- // orientation.
- if (!isWorkspaceLoading()) {
- getWorkspace().reinflateWidgetsIfNecessary();
- }
-
- if (DEBUG_RESUME_TIME) {
- Log.d(TAG, "Time spent in onResume: " + (System.currentTimeMillis() - startTime));
- }
-
updateInteraction(Workspace.State.NORMAL, mWorkspace.getState());
- mWorkspace.onResume();
// Process any items that were added while Launcher was away.
InstallShortcutReceiver.disableAndFlushInstallQueue(
@@ -988,6 +917,9 @@ public class Launcher extends BaseActivity
mLauncherCallbacks.onResume();
}
+ clearTypedText();
+
+ TraceHelper.endSection("ON_RESUME");
}
@Override
@@ -1050,7 +982,7 @@ public class Launcher extends BaseActivity
// On O and above we there is always some setting present settings (add icon to
// home screen or icon badging). On earlier APIs we will have the allow rotation
// setting, on devices with a locked orientation,
- return Utilities.isAtLeastO() || !getResources().getBoolean(R.bool.allow_rotation);
+ return Utilities.ATLEAST_OREO || !getResources().getBoolean(R.bool.allow_rotation);
}
}
@@ -1117,9 +1049,6 @@ public class Launcher extends BaseActivity
// Close any open floating view
AbstractFloatingView.closeAllOpenViews(this);
- // Stop resizing any widgets
- mWorkspace.exitWidgetResizeMode();
-
// Show the overview mode if we are on the workspace
if (mState == State.WORKSPACE && !mWorkspace.isInOverviewMode() &&
!mWorkspace.isSwitchingState()) {
@@ -1234,7 +1163,6 @@ public class Launcher extends BaseActivity
onClickWallpaperPicker(view);
}
}.attachTo(wallpaperButton);
- wallpaperButton.setOnTouchListener(getHapticFeedbackTouchListener());
// Bind widget button actions
mWidgetsButton = findViewById(R.id.widget_button);
@@ -1244,7 +1172,6 @@ public class Launcher extends BaseActivity
onClickAddWidgetButton(view);
}
}.attachTo(mWidgetsButton);
- mWidgetsButton.setOnTouchListener(getHapticFeedbackTouchListener());
// Bind settings actions
View settingsButton = findViewById(R.id.settings_button);
@@ -1256,7 +1183,6 @@ public class Launcher extends BaseActivity
onClickSettingsButton(view);
}
}.attachTo(settingsButton);
- settingsButton.setOnTouchListener(getHapticFeedbackTouchListener());
} else {
settingsButton.setVisibility(View.GONE);
}
@@ -1322,7 +1248,7 @@ public class Launcher extends BaseActivity
CellLayout layout = getCellLayout(container, screenId);
ShortcutInfo info = null;
- if (Utilities.isAtLeastO()) {
+ if (Utilities.ATLEAST_OREO) {
info = LauncherAppsCompatVO.createShortcutInfoFromPinItemRequest(
this, LauncherAppsCompatVO.getPinItemRequest(data), 0);
}
@@ -1408,17 +1334,13 @@ public class Launcher extends BaseActivity
appWidgetInfo = mAppWidgetManager.getLauncherAppWidgetInfo(appWidgetId);
}
- if (appWidgetInfo.isCustomWidget) {
- appWidgetId = LauncherAppWidgetInfo.CUSTOM_WIDGET_ID;
- }
-
LauncherAppWidgetInfo launcherInfo;
launcherInfo = new LauncherAppWidgetInfo(appWidgetId, appWidgetInfo.provider);
launcherInfo.spanX = itemInfo.spanX;
launcherInfo.spanY = itemInfo.spanY;
launcherInfo.minSpanX = itemInfo.minSpanX;
launcherInfo.minSpanY = itemInfo.minSpanY;
- launcherInfo.user = appWidgetInfo.getUser();
+ launcherInfo.user = appWidgetInfo.getProfile();
getModelWriter().addItemToDatabase(launcherInfo,
itemInfo.container, itemInfo.screenId, itemInfo.cellX, itemInfo.cellY);
@@ -1444,8 +1366,6 @@ public class Launcher extends BaseActivity
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (Intent.ACTION_SCREEN_OFF.equals(action)) {
- mDragLayer.clearResizeFrame();
-
// Reset AllApps to its initial state only if we are not in the middle of
// processing a multi-step drop
if (mAppsView != null && mWidgetsView != null && mPendingRequestArgs == null) {
@@ -1500,44 +1420,6 @@ public class Launcher extends BaseActivity
}
}
- public void onWindowVisibilityChanged(int visibility) {
- // The following code used to be in onResume, but it turns out onResume is called when
- // you're in All Apps and click home to go to the workspace. onWindowVisibilityChanged
- // is a more appropriate event to handle
- if (visibility == View.VISIBLE) {
- if (!mWorkspaceLoading) {
- final ViewTreeObserver observer = mWorkspace.getViewTreeObserver();
- // We want to let Launcher draw itself at least once before we force it to build
- // layers on all the workspace pages, so that transitioning to Launcher from other
- // apps is nice and speedy.
- observer.addOnDrawListener(new ViewTreeObserver.OnDrawListener() {
- private boolean mStarted = false;
- public void onDraw() {
- if (mStarted) return;
- mStarted = true;
- // We delay the layer building a bit in order to give
- // other message processing a time to run. In particular
- // this avoids a delay in hiding the IME if it was
- // currently shown, because doing that may involve
- // some communication back with the app.
- mWorkspace.postDelayed(mBuildLayersRunnable, 500);
- final ViewTreeObserver.OnDrawListener listener = this;
- mWorkspace.post(new Runnable() {
- public void run() {
- if (mWorkspace != null &&
- mWorkspace.getViewTreeObserver() != null) {
- mWorkspace.getViewTreeObserver().
- removeOnDrawListener(listener);
- }
- }
- });
- }
- });
- }
- clearTypedText();
- }
- }
-
public DragLayer getDragLayer() {
return mDragLayer;
}
@@ -1582,12 +1464,11 @@ public class Launcher extends BaseActivity
return mSharedPrefs;
}
+ public int getOrientation() { return mOrientation; }
+
@Override
protected void onNewIntent(Intent intent) {
- long startTime = 0;
- if (DEBUG_RESUME_TIME) {
- startTime = System.currentTimeMillis();
- }
+ TraceHelper.beginSection("NEW_INTENT");
super.onNewIntent(intent);
boolean alreadyOnHome = mHasFocus && ((intent.getFlags() &
@@ -1608,17 +1489,9 @@ public class Launcher extends BaseActivity
// Note: There should be at most one log per method call. This is enforced implicitly
// by using if-else statements.
UserEventDispatcher ued = getUserEventDispatcher();
-
- // TODO: Log this case.
- mWorkspace.exitWidgetResizeMode();
-
AbstractFloatingView topOpenView = AbstractFloatingView.getTopOpenView(this);
- if (topOpenView instanceof PopupContainerWithArrow) {
- ued.logActionCommand(Action.Command.HOME_INTENT,
- topOpenView.getExtendedTouchView(), ContainerType.DEEPSHORTCUTS);
- } else if (topOpenView instanceof Folder) {
- ued.logActionCommand(Action.Command.HOME_INTENT,
- ((Folder) topOpenView).getFolderIcon(), ContainerType.FOLDER);
+ if (topOpenView != null) {
+ topOpenView.logActionCommand(Action.Command.HOME_INTENT);
} else if (alreadyOnHome) {
ued.logActionCommand(Action.Command.HOME_INTENT,
mWorkspace.getState().containerType, mWorkspace.getCurrentPage());
@@ -1638,9 +1511,7 @@ public class Launcher extends BaseActivity
final View v = getWindow().peekDecorView();
if (v != null && v.getWindowToken() != null) {
- InputMethodManager imm = (InputMethodManager) getSystemService(
- INPUT_METHOD_SERVICE);
- imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
+ UiThreadHelper.hideKeyboardAsync(this, v.getWindowToken());
}
// Reset the apps view
@@ -1684,9 +1555,7 @@ public class Launcher extends BaseActivity
}
}
- if (DEBUG_RESUME_TIME) {
- Log.d(TAG, "Time spent in onNewIntent: " + (System.currentTimeMillis() - startTime));
- }
+ TraceHelper.endSection("NEW_INTENT");
}
@Override
@@ -1727,7 +1596,6 @@ public class Launcher extends BaseActivity
super.onDestroy();
unregisterReceiver(mReceiver);
- mWorkspace.removeCallbacks(mBuildLayersRunnable);
mWorkspace.removeFolderListeners();
// Stop callbacks from LauncherModel
@@ -1968,7 +1836,7 @@ public class Launcher extends BaseActivity
*/
private void addAppWidgetFromDrop(PendingAddWidgetInfo info) {
AppWidgetHostView hostView = info.boundWidget;
- int appWidgetId;
+ final int appWidgetId;
WidgetAddFlowHandler addFlowHandler = info.getHandler();
if (hostView != null) {
// In the case where we've prebound the widget, we remove it from the DragLayer
@@ -1985,7 +1853,13 @@ public class Launcher extends BaseActivity
} else {
// In this case, we either need to start an activity to get permission to bind
// the widget, or we need to start an activity to configure the widget, or both.
- appWidgetId = getAppWidgetHost().allocateAppWidgetId();
+ if (FeatureFlags.ENABLE_CUSTOM_WIDGETS &&
+ info.itemType == LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET) {
+ appWidgetId = CustomWidgetParser.getWidgetIdForCustomProvider(
+ this, info.componentName);
+ } else {
+ appWidgetId = getAppWidgetHost().allocateAppWidgetId();
+ }
Bundle options = info.bindOptions;
boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed(
@@ -2094,18 +1968,7 @@ public class Launcher extends BaseActivity
UserEventDispatcher ued = getUserEventDispatcher();
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(this);
if (topView != null) {
- if (topView.getActiveTextView() != null) {
- topView.getActiveTextView().dispatchBackKey();
- } else {
- if (topView instanceof PopupContainerWithArrow) {
- ued.logActionCommand(Action.Command.BACK,
- topView.getExtendedTouchView(), ContainerType.DEEPSHORTCUTS);
- } else if (topView instanceof Folder) {
- ued.logActionCommand(Action.Command.BACK,
- ((Folder) topView).getFolderIcon(), ContainerType.FOLDER);
- }
- topView.close(true);
- }
+ topView.onBackPressed();
} else if (isAppsViewVisible()) {
ued.logActionCommand(Action.Command.BACK, ContainerType.ALLAPPS);
showWorkspace(true);
@@ -2116,9 +1979,6 @@ public class Launcher extends BaseActivity
ued.logActionCommand(Action.Command.BACK, ContainerType.OVERVIEW);
showWorkspace(true);
} else {
- // TODO: Log this case.
- mWorkspace.exitWidgetResizeMode();
-
// Back button is a no-op here, but give at least some feedback for the button press
mWorkspace.showOutlinesTemporarily();
}
@@ -2232,7 +2092,7 @@ public class Launcher extends BaseActivity
if (!isAppsViewVisible()) {
getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
ControlType.ALL_APPS_BUTTON);
- showAppsView(true /* animated */, true /* updatePredictedApps */);
+ showAppsView(true /* animated */);
} else {
showWorkspace(true);
}
@@ -2427,22 +2287,6 @@ public class Launcher extends BaseActivity
startActivity(intent, getActivityLaunchOptions(v));
}
- public View.OnTouchListener getHapticFeedbackTouchListener() {
- if (mHapticFeedbackTouchListener == null) {
- mHapticFeedbackTouchListener = new View.OnTouchListener() {
- @SuppressLint("ClickableViewAccessibility")
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) {
- v.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
- }
- return false;
- }
- };
- }
- return mHapticFeedbackTouchListener;
- }
-
@Override
public void onAccessibilityStateChanged(boolean enabled) {
mDragLayer.onAccessibilityStateChanged(enabled);
@@ -2813,11 +2657,8 @@ public class Launcher extends BaseActivity
/**
* Shows the apps view.
*/
- public void showAppsView(boolean animated, boolean updatePredictedApps) {
+ public void showAppsView(boolean animated) {
markAppsViewShown();
- if (updatePredictedApps) {
- tryAndUpdatePredictedApps();
- }
showAppsOrWidgets(State.APPS, animated);
}
@@ -2937,7 +2778,7 @@ public class Launcher extends BaseActivity
public void exitSpringLoadedDragMode() {
if (mState == State.APPS_SPRING_LOADED) {
- showAppsView(true /* animated */, false /* updatePredictedApps */);
+ showAppsView(true /* animated */);
} else if (mState == State.WIDGETS_SPRING_LOADED) {
showWidgetsView(true, false);
} else if (mState == State.WORKSPACE_SPRING_LOADED) {
@@ -2945,19 +2786,6 @@ public class Launcher extends BaseActivity
}
}
- /**
- * Updates the set of predicted apps if it hasn't been updated since the last time Launcher was
- * resumed.
- */
- public void tryAndUpdatePredictedApps() {
- if (mLauncherCallbacks != null) {
- List<ComponentKeyMapper<AppInfo>> apps = mLauncherCallbacks.getPredictedApps();
- if (apps != null) {
- mAppsView.setPredictedApps(apps);
- }
- }
- }
-
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
final boolean result = super.dispatchPopulateAccessibilityEvent(event);
@@ -3063,10 +2891,7 @@ public class Launcher extends BaseActivity
* Implementation of the method from LauncherModel.Callbacks.
*/
public void startBinding() {
- if (LauncherAppState.PROFILE_STARTUP) {
- Trace.beginSection("Starting page bind");
- }
-
+ TraceHelper.beginSection("startBinding");
AbstractFloatingView.closeAllOpenViews(this);
setWorkspaceLoading(true);
@@ -3078,9 +2903,7 @@ public class Launcher extends BaseActivity
if (mHotseat != null) {
mHotseat.resetLayout();
}
- if (LauncherAppState.PROFILE_STARTUP) {
- Trace.endSection();
- }
+ TraceHelper.endSection("startBinding");
}
@Override
@@ -3192,7 +3015,8 @@ public class Launcher extends BaseActivity
(FolderInfo) item);
break;
}
- case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: {
+ case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET:
+ case LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET: {
view = inflateAppWidget((LauncherAppWidgetInfo) item);
if (view == null) {
continue;
@@ -3283,10 +3107,7 @@ public class Launcher extends BaseActivity
return view;
}
- final long start = DEBUG_WIDGETS ? SystemClock.uptimeMillis() : 0;
- if (DEBUG_WIDGETS) {
- Log.d(TAG, "bindAppWidget: " + item);
- }
+ TraceHelper.beginSection("BIND_WIDGET");
final LauncherAppWidgetProviderInfo appWidgetInfo;
@@ -3304,11 +3125,9 @@ public class Launcher extends BaseActivity
if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) &&
(item.restoreStatus != LauncherAppWidgetInfo.RESTORE_COMPLETED)) {
if (appWidgetInfo == null) {
- if (DEBUG_WIDGETS) {
- Log.d(TAG, "Removing restored widget: id=" + item.appWidgetId
- + " belongs to component " + item.providerName
- + ", as the provider is null");
- }
+ Log.d(TAG, "Removing restored widget: id=" + item.appWidgetId
+ + " belongs to component " + item.providerName
+ + ", as the provider is null");
getModelWriter().deleteItemFromDatabase(item);
return null;
}
@@ -3369,11 +3188,6 @@ public class Launcher extends BaseActivity
final AppWidgetHostView view;
if (item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
- if (DEBUG_WIDGETS) {
- Log.d(TAG, "bindAppWidget: id=" + item.appWidgetId + " belongs to component "
- + appWidgetInfo.provider);
- }
-
// Verify that we own the widget
if (appWidgetInfo == null) {
FileLog.e(TAG, "Removing invalid widget: id=" + item.appWidgetId);
@@ -3389,10 +3203,7 @@ public class Launcher extends BaseActivity
}
prepareAppWidget(view, item);
- if (DEBUG_WIDGETS) {
- Log.d(TAG, "bound widget id="+item.appWidgetId+" in "
- + (SystemClock.uptimeMillis()-start) + "ms");
- }
+ TraceHelper.endSection("BIND_WIDGET", "id=" + item.appWidgetId);
return view;
}
@@ -3414,7 +3225,10 @@ public class Launcher extends BaseActivity
info.pendingItemInfo = null;
}
- mWorkspace.reinflateWidgetsIfNecessary();
+ if (((PendingAppWidgetHostView) view).isReinflateIfNeeded()) {
+ view.reinflate();
+ }
+
getModelWriter().updateItemInDatabase(info);
return info;
}
@@ -3478,9 +3292,7 @@ public class Launcher extends BaseActivity
if (waitUntilResume(r)) {
return;
}
- if (LauncherAppState.PROFILE_STARTUP) {
- Trace.beginSection("Page bind completed");
- }
+ TraceHelper.beginSection("finishBindingItems");
mWorkspace.restoreInstanceStateForRemainingPages();
setWorkspaceLoading(false);
@@ -3499,9 +3311,7 @@ public class Launcher extends BaseActivity
if (mLauncherCallbacks != null) {
mLauncherCallbacks.finishBindingItems(false);
}
- if (LauncherAppState.PROFILE_STARTUP) {
- Trace.endSection();
- }
+ TraceHelper.endSection("finishBindingItems");
}
private boolean canRunNewAppsAnimation() {
@@ -3693,7 +3503,6 @@ public class Launcher extends BaseActivity
// Update AllApps
if (mAppsView != null) {
mAppsView.removeApps(appInfos);
- tryAndUpdatePredictedApps();
}
}
@@ -3771,7 +3580,8 @@ public class Launcher extends BaseActivity
}
private boolean shouldShowDiscoveryBounce() {
- return mState == State.WORKSPACE && !mSharedPrefs.getBoolean(APPS_VIEW_SHOWN, false);
+ UserManagerCompat um = UserManagerCompat.getInstance(this);
+ return mState == State.WORKSPACE && !mSharedPrefs.getBoolean(APPS_VIEW_SHOWN, false) && !um.isDemoUser();
}
/**
@@ -3856,7 +3666,7 @@ public class Launcher extends BaseActivity
switch (keyCode) {
case KeyEvent.KEYCODE_A:
if (mState == State.WORKSPACE) {
- showAppsView(true, true);
+ showAppsView(true);
return true;
}
break;
@@ -3882,14 +3692,6 @@ public class Launcher extends BaseActivity
return super.onKeyShortcut(keyCode, event);
}
- public static CustomAppWidget getCustomAppWidget(String name) {
- return sCustomAppWidgets.get(name);
- }
-
- public static HashMap<String, CustomAppWidget> getCustomAppWidgets() {
- return sCustomAppWidgets;
- }
-
public static Launcher getLauncher(Context context) {
if (context instanceof Launcher) {
return (Launcher) context;
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index 1ffe41bc6..dfb30fd35 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -28,7 +28,6 @@ import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.dynamicui.ExtractionUtils;
import com.android.launcher3.notification.NotificationListener;
import com.android.launcher3.util.ConfigMonitor;
import com.android.launcher3.util.Preconditions;
@@ -42,8 +41,6 @@ import static com.android.launcher3.SettingsActivity.NOTIFICATION_BADGING;
public class LauncherAppState {
- public static final boolean PROFILE_STARTUP = FeatureFlags.IS_DOGFOOD_BUILD;
-
// We do not need any synchronization for this variable as its only written on UI thread.
private static LauncherAppState INSTANCE;
@@ -111,18 +108,11 @@ public class LauncherAppState {
filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
- // For extracting colors from the wallpaper
- if (Utilities.ATLEAST_NOUGAT) {
- // TODO: add a broadcast entry to the manifest for pre-N.
- filter.addAction(Intent.ACTION_WALLPAPER_CHANGED);
- }
mContext.registerReceiver(mModel, filter);
UserManagerCompat.getInstance(mContext).enableAndResetCache();
new ConfigMonitor(mContext).register();
- ExtractionUtils.startColorExtractionServiceIfNecessary(mContext);
-
if (!mContext.getResources().getBoolean(R.bool.notification_badging_enabled)) {
mNotificationBadgingObserver = null;
} else {
diff --git a/src/com/android/launcher3/LauncherAppWidgetHost.java b/src/com/android/launcher3/LauncherAppWidgetHost.java
index 5573c5c15..70440fa30 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHost.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHost.java
@@ -116,13 +116,12 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
public AppWidgetHostView createView(Context context, int appWidgetId,
LauncherAppWidgetProviderInfo appWidget) {
- if (appWidget.isCustomWidget) {
+ if (appWidget.isCustomWidget()) {
LauncherAppWidgetHostView lahv = new LauncherAppWidgetHostView(context);
LayoutInflater inflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(appWidget.initialLayout, lahv);
lahv.setAppWidget(0, appWidget);
- lahv.updateLastInflationOrientation();
return lahv;
} else {
try {
diff --git a/src/com/android/launcher3/LauncherAppWidgetHostView.java b/src/com/android/launcher3/LauncherAppWidgetHostView.java
index c7b778252..6f953e5f0 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHostView.java
@@ -19,6 +19,7 @@ package com.android.launcher3;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Handler;
@@ -58,10 +59,14 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView
private final CheckLongPressHelper mLongPressHelper;
private final StylusEventHelper mStylusEventHelper;
- private final Context mContext;
+ private final Launcher mLauncher;
+
+ private static final int DONT_REINFLATE = 0;
+ private static final int REINFLATE_ON_RESUME = 1;
+ private static final int REINFLATE_ON_CONFIG_CHANGE = 2;
@ViewDebug.ExportedProperty(category = "launcher")
- private int mPreviousOrientation;
+ private int mReinflateStatus;
private float mSlop;
@@ -85,14 +90,14 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView
public LauncherAppWidgetHostView(Context context) {
super(context);
- mContext = context;
+ mLauncher = Launcher.getLauncher(context);
mLongPressHelper = new CheckLongPressHelper(this, this);
mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
mInflater = LayoutInflater.from(context);
- setAccessibilityDelegate(Launcher.getLauncher(context).getAccessibilityDelegate());
+ setAccessibilityDelegate(mLauncher.getAccessibilityDelegate());
setBackgroundResource(R.drawable.widget_internal_focus_bg);
- if (Utilities.isAtLeastO()) {
+ if (Utilities.ATLEAST_OREO) {
setExecutor(Utilities.THREAD_POOL_EXECUTOR);
}
}
@@ -112,18 +117,28 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView
return mInflater.inflate(R.layout.appwidget_error, this, false);
}
- public void updateLastInflationOrientation() {
- mPreviousOrientation = mContext.getResources().getConfiguration().orientation;
- }
-
@Override
public void updateAppWidget(RemoteViews remoteViews) {
- // Store the orientation in which the widget was inflated
- updateLastInflationOrientation();
super.updateAppWidget(remoteViews);
// The provider info or the views might have changed.
checkIfAutoAdvance();
+
+ // It is possible that widgets can receive updates while launcher is not in the foreground.
+ // Consequently, the widgets will be inflated for the orientation of the foreground activity
+ // (framework issue). On resuming, we ensure that any widgets are inflated for the current
+ // orientation.
+ if (mReinflateStatus == DONT_REINFLATE && !isSameOrientation()) {
+ mReinflateStatus = REINFLATE_ON_RESUME;
+ if (!mLauncher.waitUntilResume(new ReInflateRunnable())) {
+ mReinflateStatus = REINFLATE_ON_CONFIG_CHANGE;
+ }
+ }
+ }
+
+ private boolean isSameOrientation() {
+ return mLauncher.getResources().getConfiguration().orientation ==
+ mLauncher.getOrientation();
}
private boolean checkScrollableRecursively(ViewGroup viewGroup) {
@@ -142,15 +157,6 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView
return false;
}
- public boolean isReinflateRequired() {
- // Re-inflate is required if the orientation has changed since last inflated.
- int orientation = mContext.getResources().getConfiguration().orientation;
- if (mPreviousOrientation != orientation) {
- return true;
- }
- return false;
- }
-
public boolean onInterceptTouchEvent(MotionEvent ev) {
// Just in case the previous long press hasn't been cleared, we make sure to start fresh
// on touch down.
@@ -474,4 +480,45 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView
public PointF getTranslationForCentering() {
return mTranslationForCentering;
}
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ if (mReinflateStatus == REINFLATE_ON_CONFIG_CHANGE) {
+ // We are finally in the same orientation
+ reinflateIfNecessary();
+ }
+ }
+
+ private void reinflateIfNecessary() {
+ if (!isSameOrientation()) {
+ // We cannot reinflate yet, wait until next config change
+ mReinflateStatus = REINFLATE_ON_CONFIG_CHANGE;
+ return;
+ }
+
+ mReinflateStatus = DONT_REINFLATE;
+ if (isAttachedToWindow()) {
+ LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) getTag();
+ reinflate();
+ }
+ }
+
+ public void reinflate() {
+ LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) getTag();
+ // Remove and rebind the current widget (which was inflated in the wrong
+ // orientation), but don't delete it from the database
+ mLauncher.removeItem(this, info, false /* deleteFromDb */);
+ mLauncher.bindAppWidget(info);
+ }
+
+ private class ReInflateRunnable implements Runnable {
+ @Override
+ public void run() {
+ if (mReinflateStatus == REINFLATE_ON_RESUME) {
+ reinflateIfNecessary();
+ }
+ }
+ }
}
diff --git a/src/com/android/launcher3/LauncherAppWidgetInfo.java b/src/com/android/launcher3/LauncherAppWidgetInfo.java
index 6f23e56b3..051846c87 100644
--- a/src/com/android/launcher3/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher3/LauncherAppWidgetInfo.java
@@ -71,7 +71,7 @@ public class LauncherAppWidgetInfo extends ItemInfo {
/**
* Indicates that this is a locally defined widget and hence has no system allocated id.
*/
- static final int CUSTOM_WIDGET_ID = -100;
+ public static final int CUSTOM_WIDGET_ID = -100;
/**
* Identifier for this widget when talking with
@@ -104,15 +104,15 @@ public class LauncherAppWidgetInfo extends ItemInfo {
private boolean mHasNotifiedInitialWidgetSizeChanged;
public LauncherAppWidgetInfo(int appWidgetId, ComponentName providerName) {
- if (appWidgetId == CUSTOM_WIDGET_ID) {
+ this.appWidgetId = appWidgetId;
+ this.providerName = providerName;
+
+ if (isCustomWidget()) {
itemType = LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
} else {
itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
}
- this.appWidgetId = appWidgetId;
- this.providerName = providerName;
-
// Since the widget isn't instantiated yet, we don't know these values. Set them to -1
// to indicate that they should be calculated based on the layout and minWidth/minHeight
spanX = -1;
@@ -128,7 +128,7 @@ public class LauncherAppWidgetInfo extends ItemInfo {
}
public boolean isCustomWidget() {
- return appWidgetId == CUSTOM_WIDGET_ID;
+ return appWidgetId <= CUSTOM_WIDGET_ID;
}
@Override
diff --git a/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java b/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java
index 6cb703b43..c7139925c 100644
--- a/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java
+++ b/src/com/android/launcher3/LauncherAppWidgetProviderInfo.java
@@ -2,15 +2,11 @@ package com.android.launcher3;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
-import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Point;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
import android.os.Parcel;
-import android.os.Process;
-import android.os.UserHandle;
/**
* This class is a thin wrapper around the framework AppWidgetProviderInfo class. This class affords
@@ -20,7 +16,7 @@ import android.os.UserHandle;
*/
public class LauncherAppWidgetProviderInfo extends AppWidgetProviderInfo {
- public boolean isCustomWidget = false;
+ public static final String CLS_CUSTOM_WIDGET_PREFIX = "#custom-widget-";
public int spanX;
public int spanY;
@@ -48,20 +44,10 @@ public class LauncherAppWidgetProviderInfo extends AppWidgetProviderInfo {
return launcherInfo;
}
- private LauncherAppWidgetProviderInfo(Parcel in) {
- super(in);
- }
-
- public LauncherAppWidgetProviderInfo(Context context, CustomAppWidget widget) {
- isCustomWidget = true;
+ protected LauncherAppWidgetProviderInfo() {}
- provider = new ComponentName(context, widget.getClass().getName());
- icon = widget.getIcon();
- label = widget.getLabel();
- previewImage = widget.getPreviewImage();
- initialLayout = widget.getWidgetLayout();
- resizeMode = widget.getResizeMode();
- initSpans(context);
+ protected LauncherAppWidgetProviderInfo(Parcel in) {
+ super(in);
}
public void initSpans(Context context) {
@@ -97,34 +83,15 @@ public class LauncherAppWidgetProviderInfo extends AppWidgetProviderInfo {
}
public String getLabel(PackageManager packageManager) {
- if (isCustomWidget) {
- return Utilities.trim(label);
- }
return super.loadLabel(packageManager);
}
- public Drawable getIcon(Context context, IconCache cache) {
- if (isCustomWidget) {
- return cache.getFullResIcon(provider.getPackageName(), icon);
- }
- return super.loadIcon(context, LauncherAppState.getIDP(context).fillResIconDpi);
- }
-
- public String toString(PackageManager pm) {
- if (isCustomWidget) {
- return "WidgetProviderInfo(" + provider + ")";
- }
- return String.format("WidgetProviderInfo provider:%s package:%s short:%s label:%s",
- provider.toString(), provider.getPackageName(), provider.getShortClassName(), getLabel(pm));
- }
-
- public Point getMinSpans(InvariantDeviceProfile idp, Context context) {
- return new Point(
- (resizeMode & RESIZE_HORIZONTAL) != 0 ? minSpanX : -1,
- (resizeMode & RESIZE_VERTICAL) != 0 ? minSpanY : -1);
+ public Point getMinSpans() {
+ return new Point((resizeMode & RESIZE_HORIZONTAL) != 0 ? minSpanX : -1,
+ (resizeMode & RESIZE_VERTICAL) != 0 ? minSpanY : -1);
}
- public UserHandle getUser() {
- return isCustomWidget ? Process.myUserHandle() : getProfile();
+ public boolean isCustomWidget() {
+ return provider.getClassName().startsWith(CLS_CUSTOM_WIDGET_PREFIX);
}
}
diff --git a/src/com/android/launcher3/LauncherCallbacks.java b/src/com/android/launcher3/LauncherCallbacks.java
index d1e2b621a..2c9a23fa9 100644
--- a/src/com/android/launcher3/LauncherCallbacks.java
+++ b/src/com/android/launcher3/LauncherCallbacks.java
@@ -19,14 +19,10 @@ package com.android.launcher3;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
-import android.view.View;
-
-import com.android.launcher3.util.ComponentKeyMapper;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.List;
/**
* LauncherCallbacks is an interface used to extend the Launcher activity. It includes many hooks
@@ -87,5 +83,4 @@ public interface LauncherCallbacks {
*/
boolean shouldMoveToDefaultScreenOnHomeIntent();
boolean hasSettings();
- List<ComponentKeyMapper<AppInfo>> getPredictedApps();
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index a906b00f1..74a5bac99 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -37,7 +37,6 @@ import android.util.Pair;
import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
import com.android.launcher3.compat.UserManagerCompat;
-import com.android.launcher3.dynamicui.ExtractionUtils;
import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.model.AddWorkspaceItemsTask;
import com.android.launcher3.model.BgDataModel;
@@ -406,8 +405,6 @@ public class LauncherModel extends BroadcastReceiver
enqueueModelUpdateTask(new UserLockStateChangedTask(user));
}
}
- } else if (Intent.ACTION_WALLPAPER_CHANGED.equals(action)) {
- ExtractionUtils.startColorExtractionServiceIfNecessary(context);
}
}
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index dc83f36ad..25a698b15 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -55,7 +55,6 @@ import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.LauncherSettings.WorkspaceScreens;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.dynamicui.ExtractionUtils;
import com.android.launcher3.graphics.IconShapeOverride;
import com.android.launcher3.logging.FileLog;
import com.android.launcher3.model.DbDowngradeHelper;
@@ -149,9 +148,6 @@ public class LauncherProvider extends ContentProvider {
*/
protected synchronized void createDbIfNotExists() {
if (mOpenHelper == null) {
- if (LauncherAppState.PROFILE_STARTUP) {
- Trace.beginSection("Opening workspace DB");
- }
mOpenHelper = new DatabaseHelper(getContext(), mListenerHandler);
if (RestoreDbTask.isPending(getContext())) {
@@ -162,10 +158,6 @@ public class LauncherProvider extends ContentProvider {
// executed again.
RestoreDbTask.setPending(getContext(), false);
}
-
- if (LauncherAppState.PROFILE_STARTUP) {
- Trace.endSection();
- }
}
}
@@ -372,19 +364,6 @@ public class LauncherProvider extends ContentProvider {
createDbIfNotExists();
switch (method) {
- case LauncherSettings.Settings.METHOD_SET_EXTRACTED_COLORS_AND_WALLPAPER_ID: {
- String extractedColors = extras.getString(
- LauncherSettings.Settings.EXTRA_EXTRACTED_COLORS);
- int wallpaperId = extras.getInt(LauncherSettings.Settings.EXTRA_WALLPAPER_ID);
- Utilities.getPrefs(getContext()).edit()
- .putString(ExtractionUtils.EXTRACTED_COLORS_PREFERENCE_KEY, extractedColors)
- .putInt(ExtractionUtils.WALLPAPER_ID_PREFERENCE_KEY, wallpaperId)
- .apply();
- mListenerHandler.sendEmptyMessage(ChangeListenerWrapper.MSG_EXTRACTED_COLORS_CHANGED);
- Bundle result = new Bundle();
- result.putString(LauncherSettings.Settings.EXTRA_VALUE, extractedColors);
- return result;
- }
case LauncherSettings.Settings.METHOD_CLEAR_EMPTY_DB_FLAG: {
clearFlagEmptyDbCreated();
return null;
@@ -552,7 +531,14 @@ public class LauncherProvider extends ContentProvider {
}
private DefaultLayoutParser getDefaultLayoutParser(AppWidgetHost widgetHost) {
- int defaultLayout = LauncherAppState.getIDP(getContext()).defaultLayoutId;
+ InvariantDeviceProfile idp = LauncherAppState.getIDP(getContext());
+ int defaultLayout = idp.defaultLayoutId;
+
+ UserManagerCompat um = UserManagerCompat.getInstance(getContext());
+ if (um.isDemoUser() && idp.demoModeLayoutId != 0) {
+ defaultLayout = idp.demoModeLayoutId;
+ }
+
return new DefaultLayoutParser(getContext(), widgetHost,
mOpenHelper, getContext().getResources(), defaultLayout);
}
@@ -1153,8 +1139,7 @@ public class LauncherProvider extends ContentProvider {
private static class ChangeListenerWrapper implements Handler.Callback {
private static final int MSG_LAUNCHER_PROVIDER_CHANGED = 1;
- private static final int MSG_EXTRACTED_COLORS_CHANGED = 2;
- private static final int MSG_APP_WIDGET_HOST_RESET = 3;
+ private static final int MSG_APP_WIDGET_HOST_RESET = 2;
private LauncherProviderChangeListener mListener;
@@ -1165,9 +1150,6 @@ public class LauncherProvider extends ContentProvider {
case MSG_LAUNCHER_PROVIDER_CHANGED:
mListener.onLauncherProviderChanged();
break;
- case MSG_EXTRACTED_COLORS_CHANGED:
- mListener.onExtractedColorsChanged();
- break;
case MSG_APP_WIDGET_HOST_RESET:
mListener.onAppWidgetHostReset();
break;
diff --git a/src/com/android/launcher3/LauncherProviderChangeListener.java b/src/com/android/launcher3/LauncherProviderChangeListener.java
index 704481232..024308863 100644
--- a/src/com/android/launcher3/LauncherProviderChangeListener.java
+++ b/src/com/android/launcher3/LauncherProviderChangeListener.java
@@ -9,7 +9,5 @@ public interface LauncherProviderChangeListener {
void onLauncherProviderChanged();
- void onExtractedColorsChanged();
-
void onAppWidgetHostReset();
}
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 87f62eb01..3b337ef18 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -304,11 +304,6 @@ public class LauncherSettings {
public static final String METHOD_LOAD_DEFAULT_FAVORITES = "load_default_favorites";
- public static final String METHOD_SET_EXTRACTED_COLORS_AND_WALLPAPER_ID =
- "set_extracted_colors_and_wallpaper_id_setting";
- public static final String EXTRA_EXTRACTED_COLORS = "extra_extractedColors";
- public static final String EXTRA_WALLPAPER_ID = "extra_wallpaperId";
-
public static final String METHOD_REMOVE_GHOST_WIDGETS = "remove_ghost_widgets";
public static final String EXTRA_VALUE = "value";
diff --git a/src/com/android/launcher3/PendingAppWidgetHostView.java b/src/com/android/launcher3/PendingAppWidgetHostView.java
index de424aba1..b86d41318 100644
--- a/src/com/android/launcher3/PendingAppWidgetHostView.java
+++ b/src/com/android/launcher3/PendingAppWidgetHostView.java
@@ -110,9 +110,7 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView
mClickListener = l;
}
- @Override
- public boolean isReinflateRequired() {
- // Re inflate is required any time the widget restore status changes
+ public boolean isReinflateIfNeeded() {
return mStartState != mInfo.restoreStatus;
}
diff --git a/src/com/android/launcher3/SessionCommitReceiver.java b/src/com/android/launcher3/SessionCommitReceiver.java
index 8caba75cd..edb7ff533 100644
--- a/src/com/android/launcher3/SessionCommitReceiver.java
+++ b/src/com/android/launcher3/SessionCommitReceiver.java
@@ -59,7 +59,7 @@ public class SessionCommitReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- if (!isEnabled(context) || !Utilities.isAtLeastO()) {
+ if (!isEnabled(context) || !Utilities.ATLEAST_OREO) {
// User has decided to not add icons on homescreen.
return;
}
@@ -92,7 +92,7 @@ public class SessionCommitReceiver extends BroadcastReceiver {
}
public static void applyDefaultUserPrefs(final Context context) {
- if (!Utilities.isAtLeastO()) {
+ if (!Utilities.ATLEAST_OREO) {
return;
}
SharedPreferences prefs = Utilities.getPrefs(context);
diff --git a/src/com/android/launcher3/SettingsActivity.java b/src/com/android/launcher3/SettingsActivity.java
index 5bdc1f5bd..d40ac8f97 100644
--- a/src/com/android/launcher3/SettingsActivity.java
+++ b/src/com/android/launcher3/SettingsActivity.java
@@ -94,7 +94,7 @@ public class SettingsActivity extends Activity {
ButtonPreference iconBadgingPref =
(ButtonPreference) findPreference(ICON_BADGING_PREFERENCE_KEY);
- if (!Utilities.isAtLeastO()) {
+ if (!Utilities.ATLEAST_OREO) {
getPreferenceScreen().removePreference(
findPreference(SessionCommitReceiver.ADD_ICON_PREFERENCE_KEY));
getPreferenceScreen().removePreference(iconBadgingPref);
diff --git a/src/com/android/launcher3/UninstallDropTarget.java b/src/com/android/launcher3/UninstallDropTarget.java
index 84d6a9b34..3f7de0604 100644
--- a/src/com/android/launcher3/UninstallDropTarget.java
+++ b/src/com/android/launcher3/UninstallDropTarget.java
@@ -21,6 +21,7 @@ import java.net.URISyntaxException;
public class UninstallDropTarget extends ButtonDropTarget {
private static final String TAG = "UninstallDropTarget";
+ private static Boolean sUninstallDisabled;
public UninstallDropTarget(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -43,18 +44,27 @@ public class UninstallDropTarget extends ButtonDropTarget {
}
@Override
- protected boolean supportsDrop(DragSource source, ItemInfo info) {
+ protected boolean supportsDrop(ItemInfo info) {
return supportsDrop(getContext(), info);
}
public static boolean supportsDrop(Context context, ItemInfo info) {
- UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- Bundle restrictions = userManager.getUserRestrictions();
- if (restrictions.getBoolean(UserManager.DISALLOW_APPS_CONTROL, false)
- || restrictions.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS, false)) {
+ if (sUninstallDisabled == null) {
+ UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ Bundle restrictions = userManager.getUserRestrictions();
+ sUninstallDisabled = restrictions.getBoolean(UserManager.DISALLOW_APPS_CONTROL, false)
+ || restrictions.getBoolean(UserManager.DISALLOW_UNINSTALL_APPS, false);
+ }
+ if (sUninstallDisabled) {
return false;
}
+ if (info instanceof AppInfo) {
+ AppInfo appInfo = (AppInfo) info;
+ if (appInfo.isSystemApp != AppInfo.FLAG_SYSTEM_UNKNOWN) {
+ return (appInfo.isSystemApp & AppInfo.FLAG_SYSTEM_NO) != 0;
+ }
+ }
return getUninstallTarget(context, info) != null;
}
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 3aa2db000..71677782d 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -83,15 +83,17 @@ public final class Utilities {
private static final Matrix sMatrix = new Matrix();
private static final Matrix sInverseMatrix = new Matrix();
- public static boolean isAtLeastO() {
- return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
- }
+ public static final boolean ATLEAST_OREO_MR1 =
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1;
+
+ public static final boolean ATLEAST_OREO =
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
public static final boolean ATLEAST_NOUGAT_MR1 =
- Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1;
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1;
public static final boolean ATLEAST_NOUGAT =
- Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
+ Build.VERSION.SDK_INT >= Build.VERSION_CODES.N;
public static final boolean ATLEAST_MARSHMALLOW =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
@@ -307,6 +309,9 @@ public final class Utilities {
float highScore = -1;
int bestHue = -1;
+ int[] pixels = new int[samples];
+ int pixelCount = 0;
+
for (int y = 0; y < height; y += sampleStride) {
for (int x = 0; x < width; x += sampleStride) {
int argb = bitmap.getPixel(x, y);
@@ -324,6 +329,9 @@ public final class Utilities {
// Defensively avoid array bounds violations.
continue;
}
+ if (pixelCount < samples) {
+ pixels[pixelCount++] = rgb;
+ }
float score = hsv[1] * hsv[2];
hueScoreHistogram[hue] += score;
if (hueScoreHistogram[hue] > highScore) {
@@ -333,31 +341,29 @@ public final class Utilities {
}
}
- SparseArray<Float> rgbScores = new SparseArray<Float>();
+ SparseArray<Float> rgbScores = new SparseArray<>();
int bestColor = 0xff000000;
highScore = -1;
// Go back over the RGB colors that match the winning hue,
// creating a histogram of weighted s*v scores, for up to 100*100 [s,v] buckets.
// The highest-scoring RGB color wins.
- for (int y = 0; y < height; y += sampleStride) {
- for (int x = 0; x < width; x += sampleStride) {
- int rgb = bitmap.getPixel(x, y) | 0xff000000;
- Color.colorToHSV(rgb, hsv);
- int hue = (int) hsv[0];
- if (hue == bestHue) {
- float s = hsv[1];
- float v = hsv[2];
- int bucket = (int) (s * 100) + (int) (v * 10000);
- // Score by cumulative saturation * value.
- float score = s * v;
- Float oldTotal = rgbScores.get(bucket);
- float newTotal = oldTotal == null ? score : oldTotal + score;
- rgbScores.put(bucket, newTotal);
- if (newTotal > highScore) {
- highScore = newTotal;
- // All the colors in the winning bucket are very similar. Last in wins.
- bestColor = rgb;
- }
+ for (int i = 0; i < pixelCount; i++) {
+ int rgb = pixels[i];
+ Color.colorToHSV(rgb, hsv);
+ int hue = (int) hsv[0];
+ if (hue == bestHue) {
+ float s = hsv[1];
+ float v = hsv[2];
+ int bucket = (int) (s * 100) + (int) (v * 10000);
+ // Score by cumulative saturation * value.
+ float score = s * v;
+ Float oldTotal = rgbScores.get(bucket);
+ float newTotal = oldTotal == null ? score : oldTotal + score;
+ rgbScores.put(bucket, newTotal);
+ if (newTotal > highScore) {
+ highScore = newTotal;
+ // All the colors in the winning bucket are very similar. Last in wins.
+ bestColor = rgb;
}
}
}
diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java
index a65ea9b10..f150c89c1 100644
--- a/src/com/android/launcher3/WidgetPreviewLoader.java
+++ b/src/com/android/launcher3/WidgetPreviewLoader.java
@@ -22,7 +22,6 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
-import android.os.Build;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.UserHandle;
@@ -412,7 +411,8 @@ public class WidgetPreviewLoader {
// Draw icon in the center.
try {
- Drawable icon = info.getIcon(launcher, mIconCache);
+ Drawable icon =
+ mIconCache.getFullResIcon(info.provider.getPackageName(), info.icon);
if (icon != null) {
int appIconSize = launcher.getDeviceProfile().iconSizePx;
int iconSize = (int) Math.min(appIconSize * scale,
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 59437f608..95f748400 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -228,7 +228,6 @@ public class Workspace extends PagedView
private State mState = State.NORMAL;
private boolean mIsSwitchingState = false;
- boolean mAnimatingViewIntoPlace = false;
boolean mChildrenLayersEnabled = true;
private boolean mStripScreensOnPageStopMoving = false;
@@ -252,8 +251,6 @@ public class Workspace extends PagedView
private boolean mAddToExistingFolderOnDrop = false;
private float mMaxDistanceForFolderCreation;
- private final Canvas mCanvas = new Canvas();
-
// Variables relating to touch disambiguation (scrolling workspace vs. scrolling a widget)
private float mXDown;
private float mYDown;
@@ -351,12 +348,9 @@ public class Workspace extends PagedView
/**
* Estimates the size of an item using spans: hSpan, vSpan.
*
- * @param springLoaded True if we are in spring loaded mode.
- * @param unscaledSize True if caller wants to return the unscaled size
* @return MAX_VALUE for each dimension if unsuccessful.
*/
- public int[] estimateItemSize(ItemInfo itemInfo, boolean springLoaded, boolean unscaledSize) {
- float shrinkFactor = mLauncher.getDeviceProfile().workspaceSpringLoadShrinkFactor;
+ public int[] estimateItemSize(ItemInfo itemInfo) {
int[] size = new int[2];
if (getChildCount() > 0) {
// Use the first page to estimate the child position
@@ -373,15 +367,10 @@ public class Workspace extends PagedView
size[0] = r.width();
size[1] = r.height();
- if (isWidget && unscaledSize) {
+ if (isWidget) {
size[0] /= scale;
size[1] /= scale;
}
-
- if (springLoaded) {
- size[0] *= shrinkFactor;
- size[1] *= shrinkFactor;
- }
return size;
} else {
size[0] = Integer.MAX_VALUE;
@@ -408,11 +397,15 @@ public class Workspace extends PagedView
}
if (mOutlineProvider != null) {
- // The outline is used to visualize where the item will land if dropped
- mOutlineProvider.generateDragOutline(mCanvas);
+ if (dragObject.dragView != null) {
+ Bitmap preview = dragObject.dragView.getPreviewBitmap();
+
+ // The outline is used to visualize where the item will land if dropped
+ mOutlineProvider.generateDragOutline(preview);
+ }
}
- updateChildrenLayersEnabled(false);
+ updateChildrenLayersEnabled();
mLauncher.lockScreenOrientation();
mLauncher.onInteractionBegin();
// Prevent any Un/InstallShortcutReceivers from updating the db while we are dragging
@@ -465,7 +458,7 @@ public class Workspace extends PagedView
removeExtraEmptyScreen(true, mDragSourceInternal != null);
}
- updateChildrenLayersEnabled(false);
+ updateChildrenLayersEnabled();
mLauncher.unlockScreenOrientation(false);
// Re-enable any Un/InstallShortcutReceiver and now process any queued items
@@ -1022,10 +1015,6 @@ public class Workspace extends PagedView
|| (mTransitionProgress > FINISHED_SWITCHING_STATE_TRANSITION_PROGRESS);
}
- protected void onWindowVisibilityChanged (int visibility) {
- mLauncher.onWindowVisibilityChanged(visibility);
- }
-
@Override
public boolean dispatchUnhandledMove(View focused, int direction) {
if (workspaceInModalState() || !isFinishedSwitchingState()) {
@@ -1054,30 +1043,6 @@ public class Workspace extends PagedView
return super.onInterceptTouchEvent(ev);
}
- protected void reinflateWidgetsIfNecessary() {
- final int clCount = getChildCount();
- for (int i = 0; i < clCount; i++) {
- CellLayout cl = (CellLayout) getChildAt(i);
- ShortcutAndWidgetContainer swc = cl.getShortcutsAndWidgets();
- final int itemCount = swc.getChildCount();
- for (int j = 0; j < itemCount; j++) {
- View v = swc.getChildAt(j);
-
- if (v instanceof LauncherAppWidgetHostView
- && v.getTag() instanceof LauncherAppWidgetInfo) {
- LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) v.getTag();
- LauncherAppWidgetHostView lahv = (LauncherAppWidgetHostView) v;
- if (lahv.isReinflateRequired()) {
- // Remove and rebind the current widget (which was inflated in the wrong
- // orientation), but don't delete it from the database
- mLauncher.removeItem(lahv, info, false /* deleteFromDb */);
- mLauncher.bindAppWidget(info);
- }
- }
- }
- }
- }
-
@Override
protected void determineScrollingStart(MotionEvent ev) {
if (!isFinishedSwitchingState()) return;
@@ -1115,12 +1080,12 @@ public class Workspace extends PagedView
protected void onPageBeginTransition() {
super.onPageBeginTransition();
- updateChildrenLayersEnabled(false);
+ updateChildrenLayersEnabled();
}
protected void onPageEndTransition() {
super.onPageEndTransition();
- updateChildrenLayersEnabled(false);
+ updateChildrenLayersEnabled();
if (mDragController.isDragging()) {
if (workspaceInModalState()) {
@@ -1465,10 +1430,6 @@ public class Workspace extends PagedView
mWallpaperOffset.setWindowToken(null);
}
- protected void onResume() {
- mWallpaperOffset.onResume();
- }
-
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
if (mUnlockWallpaperFromDefaultPageOnLayout) {
@@ -1500,9 +1461,9 @@ public class Workspace extends PagedView
return mState == State.NORMAL || mState == State.SPRING_LOADED;
}
- @Thunk void updateChildrenLayersEnabled(boolean force) {
+ private void updateChildrenLayersEnabled() {
boolean small = mState == State.OVERVIEW || mIsSwitchingState;
- boolean enableChildrenLayers = force || small || mAnimatingViewIntoPlace || isPageInTransition();
+ boolean enableChildrenLayers = small || isPageInTransition();
if (enableChildrenLayers != mChildrenLayersEnabled) {
mChildrenLayersEnabled = enableChildrenLayers;
@@ -1568,19 +1529,6 @@ public class Workspace extends PagedView
}
}
- public void buildPageHardwareLayers() {
- // force layers to be enabled just for the call to buildLayer
- updateChildrenLayersEnabled(true);
- if (getWindowToken() != null) {
- final int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- CellLayout cl = (CellLayout) getChildAt(i);
- cl.buildHardwareLayer();
- }
- }
- updateChildrenLayersEnabled(false);
- }
-
protected void onWallpaperTap(MotionEvent ev) {
final int[] position = mTempXY;
getLocationOnScreen(position);
@@ -1599,11 +1547,6 @@ public class Workspace extends PagedView
mOutlineProvider = outlineProvider;
}
- public void exitWidgetResizeMode() {
- DragLayer dragLayer = mLauncher.getDragLayer();
- dragLayer.clearResizeFrame();
- }
-
public void onStartReordering() {
super.onStartReordering();
// Reordering handles its own animations, disable the automatic ones.
@@ -1779,12 +1722,12 @@ public class Workspace extends PagedView
}
invalidate(); // This will call dispatchDraw(), which calls getVisiblePages().
- updateChildrenLayersEnabled(false);
+ updateChildrenLayersEnabled();
}
public void onEndStateTransition() {
mIsSwitchingState = false;
- updateChildrenLayersEnabled(false);
+ updateChildrenLayersEnabled();
mForceDrawAdjacentPages = false;
mTransitionProgress = 1;
}
@@ -1833,7 +1776,7 @@ public class Workspace extends PagedView
mOutlineProvider = previewProvider;
// The drag bitmap follows the touch point around on the screen
- final Bitmap b = previewProvider.createDragBitmap(mCanvas);
+ final Bitmap b = previewProvider.createDragBitmap();
int halfPadding = previewProvider.previewPadding / 2;
float scale = previewProvider.getScaleAndPosition(b, mTempXY);
@@ -1880,8 +1823,7 @@ public class Workspace extends PagedView
DragView dv = mDragController.startDrag(b, dragLayerX, dragLayerY, source,
dragObject, dragVisualizeOffset, dragRect, scale, dragOptions);
- dv.setIntrinsicIconScaleFactor(source.getIntrinsicIconScaleFactor());
- b.recycle();
+ dv.setIntrinsicIconScaleFactor(dragOptions.intrinsicIconScaleFactor);
return dv;
}
@@ -1893,6 +1835,7 @@ public class Workspace extends PagedView
/**
* {@inheritDoc}
*/
+ @Override
public boolean acceptDrop(DragObject d) {
// If it's an external drop (e.g. from All Apps), check if it should be accepted
CellLayout dropTargetLayout = mDropToLayout;
@@ -2244,8 +2187,7 @@ public class Workspace extends PagedView
mDelayedResizeRunnable = new Runnable() {
public void run() {
if (!isPageInTransition()) {
- DragLayer dragLayer = mLauncher.getDragLayer();
- dragLayer.addResizeFrame(hostView, cellLayout);
+ AppWidgetResizeFrame.showForWidget(hostView, cellLayout);
}
}
};
@@ -2269,16 +2211,6 @@ public class Workspace extends PagedView
}
final CellLayout parent = (CellLayout) cell.getParent().getParent();
- // Prepare it to be animated into its new position
- // This must be called after the view has been re-parented
- final Runnable onCompleteRunnable = new Runnable() {
- @Override
- public void run() {
- mAnimatingViewIntoPlace = false;
- updateChildrenLayersEnabled(false);
- }
- };
- mAnimatingViewIntoPlace = true;
if (d.dragView.hasDrawn()) {
if (droppedOnOriginalCellDuringTransition) {
// Animate the item to its original position, while simultaneously exiting
@@ -2297,12 +2229,11 @@ public class Workspace extends PagedView
if (isWidget) {
int animationType = resizeOnDrop ? ANIMATE_INTO_POSITION_AND_RESIZE :
ANIMATE_INTO_POSITION_AND_DISAPPEAR;
- animateWidgetDrop(info, parent, d.dragView,
- onCompleteRunnable, animationType, cell, false);
+ animateWidgetDrop(info, parent, d.dragView, null, animationType, cell, false);
} else {
int duration = snapScreen < 0 ? -1 : ADJACENT_SCREEN_DROP_DURATION;
mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, cell, duration,
- onCompleteRunnable, this);
+ null, this);
}
} else {
d.deferDragViewCleanupPostAnimation = false;
@@ -2992,7 +2923,7 @@ public class Workspace extends PagedView
}
public Bitmap createWidgetBitmap(ItemInfo widgetInfo, View layout) {
- int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(widgetInfo, false, true);
+ int[] unScaledSize = estimateItemSize(widgetInfo);
int visibility = layout.getVisibility();
layout.setVisibility(VISIBLE);
@@ -3000,12 +2931,9 @@ public class Workspace extends PagedView
int height = MeasureSpec.makeMeasureSpec(unScaledSize[1], MeasureSpec.EXACTLY);
Bitmap b = Bitmap.createBitmap(unScaledSize[0], unScaledSize[1],
Bitmap.Config.ARGB_8888);
- mCanvas.setBitmap(b);
-
layout.measure(width, height);
layout.layout(0, 0, unScaledSize[0], unScaledSize[1]);
- layout.draw(mCanvas);
- mCanvas.setBitmap(null);
+ layout.draw(new Canvas(b));
layout.setVisibility(visibility);
return b;
}
@@ -3157,7 +3085,7 @@ public class Workspace extends PagedView
// hardware layers on children are enabled on startup, but should be disabled until
// needed
- updateChildrenLayersEnabled(false);
+ updateChildrenLayersEnabled();
}
/**
@@ -3256,21 +3184,6 @@ public class Workspace extends PagedView
}
}
- @Override
- public float getIntrinsicIconScaleFactor() {
- return 1f;
- }
-
- @Override
- public boolean supportsAppInfoDropTarget() {
- return true;
- }
-
- @Override
- public boolean supportsDeleteDropTarget() {
- return true;
- }
-
public boolean isDropEnabled() {
return true;
}
@@ -3641,7 +3554,7 @@ public class Workspace extends PagedView
.getInstance(mLauncher).findProvider(item.providerName, item.user);
} else {
widgetInfo = AppWidgetManagerCompat.getInstance(mLauncher)
- .getAppWidgetInfo(item.appWidgetId);
+ .getLauncherAppWidgetInfo(item.appWidgetId);
}
if (widgetInfo != null) {
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 4eba5c6df..d63ae4189 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -115,13 +115,6 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
}
/**
- * Sets the current set of predicted apps.
- */
- public void setPredictedApps(List<ComponentKeyMapper<AppInfo>> apps) {
- mApps.setPredictedApps(apps);
- }
-
- /**
* Sets the current set of apps.
*/
public void setApps(List<AppInfo> apps) {
@@ -290,24 +283,12 @@ public class AllAppsContainerView extends BaseContainerView implements DragSourc
dragController.removeDragListener(this);
}
});
- mLauncher.getWorkspace().beginDragShared(v, this, new DragOptions());
- return false;
- }
- @Override
- public boolean supportsAppInfoDropTarget() {
- return true;
- }
-
- @Override
- public boolean supportsDeleteDropTarget() {
- return false;
- }
-
- @Override
- public float getIntrinsicIconScaleFactor() {
DeviceProfile grid = mLauncher.getDeviceProfile();
- return (float) grid.allAppsIconSizePx / grid.iconSizePx;
+ DragOptions options = new DragOptions();
+ options.intrinsicIconScaleFactor = (float) grid.allAppsIconSizePx / grid.iconSizePx;
+ mLauncher.getWorkspace().beginDragShared(v, this, options);
+ return false;
}
@Override
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 3364c61ee..b844ba303 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -6,14 +6,11 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
-import android.graphics.Color;
import android.support.animation.SpringAnimation;
-import android.support.v4.graphics.ColorUtils;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
-import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import com.android.launcher3.AbstractFloatingView;
@@ -46,12 +43,8 @@ import com.android.launcher3.util.TouchController;
public class AllAppsTransitionController implements TouchController, SwipeDetector.Listener,
SearchUiManager.OnScrollRangeChangeListener {
- private static final String TAG = "AllAppsTrans";
- private static final boolean DBG = false;
-
private final Interpolator mWorkspaceAccelnterpolator = new AccelerateInterpolator(2f);
private final Interpolator mHotseatAccelInterpolator = new AccelerateInterpolator(1.5f);
- private final Interpolator mDecelInterpolator = new DecelerateInterpolator(3f);
private final Interpolator mFastOutSlowInInterpolator = new FastOutSlowInInterpolator();
private final SwipeDetector.ScrollInterpolator mScrollInterpolator
= new SwipeDetector.ScrollInterpolator();
@@ -60,10 +53,8 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect
private static final int SINGLE_FRAME_MS = 16;
private AllAppsContainerView mAppsView;
- private int mAllAppsBackgroundColor;
private Workspace mWorkspace;
private Hotseat mHotseat;
- private int mHotseatBackgroundColor;
private AllAppsCaretController mCaretController;
@@ -112,7 +103,6 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect
mProgress = 1f;
mEvaluator = new ArgbEvaluator();
- mAllAppsBackgroundColor = Themes.getAttrColor(l, android.R.attr.colorPrimary);
mIsDarkTheme = Themes.getAttrBoolean(mLauncher, R.attr.isMainColorDark);
}
@@ -226,7 +216,7 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect
Action.Direction.UP,
containerType);
}
- mLauncher.showAppsView(true /* animated */, false /* updatePredictedApps */);
+ mLauncher.showAppsView(true /* animated */);
if (hasSpringAnimationHandler()) {
mSpringAnimationHandler.add(mSearchSpring, true /* setDefaultValues */);
// The icons are moving upwards, so we go to 0 from 1. (y-axis 1 is below 0.)
@@ -249,7 +239,7 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect
Action.Direction.UP,
containerType);
}
- mLauncher.showAppsView(true, /* animated */ false /* updatePredictedApps */);
+ mLauncher.showAppsView(true /* animated */);
}
}
}
@@ -266,29 +256,13 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect
// Initialize values that should not change until #onDragEnd
mStatusBarHeight = mLauncher.getDragLayer().getInsets().top;
mHotseat.setVisibility(View.VISIBLE);
- mHotseatBackgroundColor = mHotseat.getBackgroundDrawableColor();
- mHotseat.setBackgroundTransparent(true /* transparent */);
- if (!mLauncher.isAllAppsVisible()) {
- mLauncher.tryAndUpdatePredictedApps();
- mAppsView.setVisibility(View.VISIBLE);
- if (!FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
- mAppsView.setRevealDrawableColor(mHotseatBackgroundColor);
- }
- }
+ mAppsView.setVisibility(View.VISIBLE);
}
}
private void updateLightStatusBar(float shift) {
- // Do not modify status bar on landscape as all apps is not full bleed.
- if (!FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS
- && mLauncher.getDeviceProfile().isVerticalBarLayout()) {
- return;
- }
-
// Use a light system UI (dark icons) if all apps is behind at least half of the status bar.
- boolean forceChange = FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS ?
- shift <= mShiftRange / 4 :
- shift <= mStatusBarHeight / 2;
+ boolean forceChange = shift <= mShiftRange / 4;
if (forceChange) {
mLauncher.getSystemUiController().updateUiState(
SystemUiController.UI_STATE_ALL_APPS, !mIsDarkTheme);
@@ -301,8 +275,7 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect
private void updateAllAppsBg(float progress) {
// gradient
if (mGradientView == null) {
- mGradientView = (GradientView) mLauncher.findViewById(R.id.gradient_bg);
- mGradientView.setVisibility(View.VISIBLE);
+ mGradientView = mLauncher.findViewById(R.id.gradient_bg);
}
mGradientView.setProgress(progress);
}
@@ -320,17 +293,7 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect
float workspaceAlpha = mWorkspaceAccelnterpolator.getInterpolation(workspaceHotseatAlpha);
float hotseatAlpha = mHotseatAccelInterpolator.getInterpolation(workspaceHotseatAlpha);
- int color = (Integer) mEvaluator.evaluate(mDecelInterpolator.getInterpolation(alpha),
- mHotseatBackgroundColor, mAllAppsBackgroundColor);
- int bgAlpha = Color.alpha((int) mEvaluator.evaluate(alpha,
- mHotseatBackgroundColor, mAllAppsBackgroundColor));
-
- if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
- updateAllAppsBg(alpha);
- } else {
- mAppsView.setRevealDrawableColor(ColorUtils.setAlphaComponent(color, bgAlpha));
- }
-
+ updateAllAppsBg(alpha);
mAppsView.getContentView().setAlpha(alpha);
mAppsView.setTranslationY(shiftCurrent);
@@ -530,7 +493,6 @@ public class AllAppsTransitionController implements TouchController, SwipeDetect
public void finishPullDown() {
mAppsView.setVisibility(View.INVISIBLE);
- mHotseat.setBackgroundTransparent(false /* transparent */);
mHotseat.setVisibility(View.VISIBLE);
mAppsView.reset();
if (hasSpringAnimationHandler()) {
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index 6bbe3ea55..f0b650bd2 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -362,9 +362,12 @@ public class AlphabeticalAppsList {
int size = apps.size();
for (int i = 0; i < size; ++i) {
AppInfo info = apps.get(i);
- AdapterItem appItem = AdapterItem.asPredictedApp(i, "", info, i);
- appItem.rowAppIndex = i;
- mAdapterItems.set(i, appItem);
+ AdapterItem orgItem = mAdapterItems.get(i);
+ AdapterItem newItem = AdapterItem.asPredictedApp(orgItem.position, "", info,
+ orgItem.appIndex);
+ newItem.rowAppIndex = orgItem.rowAppIndex;
+
+ mAdapterItems.set(i, newItem);
mFilteredApps.set(i, info);
mAdapter.notifyItemChanged(i);
}
diff --git a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
index 63aa7be3a..bf03a0ee1 100644
--- a/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
+++ b/src/com/android/launcher3/allapps/search/AllAppsSearchBarController.java
@@ -15,16 +15,13 @@
*/
package com.android.launcher3.allapps.search;
-import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.KeyEvent;
-import android.view.View;
import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
@@ -50,7 +47,6 @@ public class AllAppsSearchBarController
protected String mQuery;
protected SearchAlgorithm mSearchAlgorithm;
- protected InputMethodManager mInputMethodManager;
public void setVisibility(int visibility) {
mInput.setVisibility(visibility);
@@ -68,10 +64,6 @@ public class AllAppsSearchBarController
mInput.addTextChangedListener(this);
mInput.setOnEditorActionListener(this);
mInput.setOnBackKeyListener(this);
-
- mInputMethodManager = (InputMethodManager)
- mInput.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
-
mSearchAlgorithm = searchAlgorithm;
}
@@ -137,22 +129,9 @@ public class AllAppsSearchBarController
* Resets the search bar state.
*/
public void reset() {
- unfocusSearchField();
mCb.clearSearchResult();
- mInput.setText("");
+ mInput.reset();
mQuery = null;
- hideKeyboard();
- }
-
- protected void hideKeyboard() {
- mInputMethodManager.hideSoftInputFromWindow(mInput.getWindowToken(), 0);
- }
-
- protected void unfocusSearchField() {
- View nextFocus = mInput.focusSearch(View.FOCUS_DOWN);
- if (nextFocus != null) {
- nextFocus.requestFocus();
- }
}
/**
diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompat.java b/src/com/android/launcher3/compat/AppWidgetManagerCompat.java
index 4e00eae9d..fd1f0cca2 100644
--- a/src/com/android/launcher3/compat/AppWidgetManagerCompat.java
+++ b/src/com/android/launcher3/compat/AppWidgetManagerCompat.java
@@ -24,10 +24,13 @@ import android.os.Bundle;
import android.os.UserHandle;
import android.support.annotation.Nullable;
+import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.Utilities;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageUserKey;
+import com.android.launcher3.widget.custom.CustomWidgetParser;
import java.util.HashMap;
import java.util.List;
@@ -40,7 +43,7 @@ public abstract class AppWidgetManagerCompat {
public static AppWidgetManagerCompat getInstance(Context context) {
synchronized (sInstanceLock) {
if (sInstance == null) {
- if (Utilities.isAtLeastO()) {
+ if (Utilities.ATLEAST_OREO) {
sInstance = new AppWidgetManagerCompatVO(context.getApplicationContext());
} else {
sInstance = new AppWidgetManagerCompatVL(context.getApplicationContext());
@@ -58,12 +61,13 @@ public abstract class AppWidgetManagerCompat {
mAppWidgetManager = AppWidgetManager.getInstance(context);
}
- public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
- return mAppWidgetManager.getAppWidgetInfo(appWidgetId);
- }
-
public LauncherAppWidgetProviderInfo getLauncherAppWidgetInfo(int appWidgetId) {
- AppWidgetProviderInfo info = getAppWidgetInfo(appWidgetId);
+ if (FeatureFlags.ENABLE_CUSTOM_WIDGETS
+ && appWidgetId <= LauncherAppWidgetInfo.CUSTOM_WIDGET_ID) {
+ return CustomWidgetParser.getWidgetProvider(mContext, appWidgetId);
+ }
+
+ AppWidgetProviderInfo info = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
return info == null ? null : LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, info);
}
diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java b/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java
index cb3bd6c7d..843028503 100644
--- a/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java
+++ b/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java
@@ -20,14 +20,17 @@ import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
import android.os.Bundle;
+import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.support.annotation.Nullable;
+import com.android.launcher3.LauncherAppWidgetInfo;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageUserKey;
+import com.android.launcher3.widget.custom.CustomWidgetParser;
import java.util.ArrayList;
import java.util.Collections;
@@ -54,6 +57,10 @@ class AppWidgetManagerCompatVL extends AppWidgetManagerCompat {
for (UserHandle user : mUserManager.getUserProfiles()) {
providers.addAll(mAppWidgetManager.getInstalledProvidersForProfile(user));
}
+
+ if (FeatureFlags.ENABLE_CUSTOM_WIDGETS) {
+ providers.addAll(CustomWidgetParser.getCustomWidgets(mContext));
+ }
return providers;
}
// Only get providers for the given package/user.
@@ -65,6 +72,11 @@ class AppWidgetManagerCompatVL extends AppWidgetManagerCompat {
iterator.remove();
}
}
+
+ if (FeatureFlags.ENABLE_CUSTOM_WIDGETS && Process.myUserHandle().equals(packageUser.mUser)
+ && mContext.getPackageName().equals(packageUser.mPackageName)) {
+ providers.addAll(CustomWidgetParser.getCustomWidgets(mContext));
+ }
return providers;
}
@@ -74,6 +86,11 @@ class AppWidgetManagerCompatVL extends AppWidgetManagerCompat {
if (FeatureFlags.GO_DISABLE_WIDGETS) {
return false;
}
+
+ if (FeatureFlags.ENABLE_CUSTOM_WIDGETS
+ && appWidgetId <= LauncherAppWidgetInfo.CUSTOM_WIDGET_ID) {
+ return true;
+ }
return mAppWidgetManager.bindAppWidgetIdIfAllowed(
appWidgetId, info.getProfile(), info.provider, options);
}
@@ -89,6 +106,15 @@ class AppWidgetManagerCompatVL extends AppWidgetManagerCompat {
return LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, info);
}
}
+
+ if (FeatureFlags.ENABLE_CUSTOM_WIDGETS && Process.myUserHandle().equals(user)) {
+ for (LauncherAppWidgetProviderInfo info :
+ CustomWidgetParser.getCustomWidgets(mContext)) {
+ if (info.provider.equals(provider)) {
+ return info;
+ }
+ }
+ }
return null;
}
@@ -104,6 +130,13 @@ class AppWidgetManagerCompatVL extends AppWidgetManagerCompat {
result.put(new ComponentKey(info.provider, user), info);
}
}
+
+ if (FeatureFlags.ENABLE_CUSTOM_WIDGETS) {
+ for (LauncherAppWidgetProviderInfo info :
+ CustomWidgetParser.getCustomWidgets(mContext)) {
+ result.put(new ComponentKey(info.provider, info.getProfile()), info);
+ }
+ }
return result;
}
}
diff --git a/src/com/android/launcher3/compat/LauncherAppsCompat.java b/src/com/android/launcher3/compat/LauncherAppsCompat.java
index 75a2a5d18..2cac536f6 100644
--- a/src/com/android/launcher3/compat/LauncherAppsCompat.java
+++ b/src/com/android/launcher3/compat/LauncherAppsCompat.java
@@ -53,7 +53,7 @@ public abstract class LauncherAppsCompat {
public static LauncherAppsCompat getInstance(Context context) {
synchronized (sInstanceLock) {
if (sInstance == null) {
- if (Utilities.isAtLeastO()) {
+ if (Utilities.ATLEAST_OREO) {
sInstance = new LauncherAppsCompatVO(context.getApplicationContext());
} else {
sInstance = new LauncherAppsCompatVL(context.getApplicationContext());
diff --git a/src/com/android/launcher3/compat/WallpaperManagerCompat.java b/src/com/android/launcher3/compat/WallpaperManagerCompat.java
index cbcabdf9b..00258c7da 100644
--- a/src/com/android/launcher3/compat/WallpaperManagerCompat.java
+++ b/src/com/android/launcher3/compat/WallpaperManagerCompat.java
@@ -31,10 +31,10 @@ public abstract class WallpaperManagerCompat {
if (sInstance == null) {
context = context.getApplicationContext();
- if (Utilities.isAtLeastO()) {
+ if (Utilities.ATLEAST_OREO) {
try {
sInstance = new WallpaperManagerCompatVOMR1(context);
- } catch (Exception e) {
+ } catch (Throwable e) {
// The wallpaper APIs do not yet exist
}
}
diff --git a/src/com/android/launcher3/compat/WallpaperManagerCompatVL.java b/src/com/android/launcher3/compat/WallpaperManagerCompatVL.java
index 8e572ee1a..4cc70d367 100644
--- a/src/com/android/launcher3/compat/WallpaperManagerCompatVL.java
+++ b/src/com/android/launcher3/compat/WallpaperManagerCompatVL.java
@@ -15,6 +15,10 @@
*/
package com.android.launcher3.compat;
+import static android.app.WallpaperManager.FLAG_SYSTEM;
+
+import static com.android.launcher3.Utilities.getDevicePrefs;
+
import android.app.WallpaperInfo;
import android.app.WallpaperManager;
import android.app.job.JobInfo;
@@ -38,7 +42,6 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.ParcelFileDescriptor;
import android.support.annotation.Nullable;
-import android.support.v7.graphics.Palette;
import android.util.Log;
import android.util.Pair;
@@ -46,12 +49,6 @@ import com.android.launcher3.Utilities;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-import static android.app.WallpaperManager.FLAG_SYSTEM;
-import static com.android.launcher3.Utilities.getDevicePrefs;
public class WallpaperManagerCompatVL extends WallpaperManagerCompat {
@@ -260,27 +257,8 @@ public class WallpaperManagerCompatVL extends WallpaperManagerCompat {
String value = VERSION_PREFIX + wallpaperId;
if (bitmap != null) {
- Palette palette = Palette.from(bitmap).generate();
- bitmap.recycle();
-
- StringBuilder builder = new StringBuilder(value);
- List<Pair<Integer,Integer>> colorsToOccurrences = new ArrayList<>();
- for (Palette.Swatch swatch : palette.getSwatches()) {
- colorsToOccurrences.add(new Pair(swatch.getRgb(), swatch.getPopulation()));
- }
-
- Collections.sort(colorsToOccurrences, new Comparator<Pair<Integer, Integer>>() {
- @Override
- public int compare(Pair<Integer, Integer> a, Pair<Integer, Integer> b) {
- return b.second - a.second;
- }
- });
-
- for (int i=0; i < Math.min(3, colorsToOccurrences.size()); i++) {
- builder.append(',').append(colorsToOccurrences.get(i).first);
- }
-
- value = builder.toString();
+ int color = Utilities.findDominantColorByHue(bitmap, MAX_WALLPAPER_EXTRACTION_AREA);
+ value += "," + color;
}
// Send the result
diff --git a/src/com/android/launcher3/compat/WallpaperManagerCompatVOMR1.java b/src/com/android/launcher3/compat/WallpaperManagerCompatVOMR1.java
index 28b780a38..524f266fc 100644
--- a/src/com/android/launcher3/compat/WallpaperManagerCompatVOMR1.java
+++ b/src/com/android/launcher3/compat/WallpaperManagerCompatVOMR1.java
@@ -35,8 +35,9 @@ public class WallpaperManagerCompatVOMR1 extends WallpaperManagerCompat {
private final WallpaperManager mWm;
private Method mWCColorHintsMethod;
- WallpaperManagerCompatVOMR1(Context context) throws Exception {
+ WallpaperManagerCompatVOMR1(Context context) throws Throwable {
mWm = context.getSystemService(WallpaperManager.class);
+ String className = WallpaperColors.class.getName();
try {
mWCColorHintsMethod = WallpaperColors.class.getDeclaredMethod("getColorHints");
} catch (Exception exc) {
diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java
index 5adeec1c6..8a1bc6388 100644
--- a/src/com/android/launcher3/config/BaseFlags.java
+++ b/src/com/android/launcher3/config/BaseFlags.java
@@ -39,8 +39,6 @@ abstract class BaseFlags {
public static final boolean LAUNCHER3_UPDATE_SOFT_INPUT_MODE = false;
// When enabled the promise icon is visible in all apps while installation an app.
public static final boolean LAUNCHER3_PROMISE_APPS_IN_ALL_APPS = false;
- // When enabled uses the AllAppsRadialGradientAndScrimDrawable for all apps
- public static final boolean LAUNCHER3_GRADIENT_ALL_APPS = true;
// When enabled allows use of physics based motions in the Launcher.
public static final boolean LAUNCHER3_PHYSICS = true;
// When enabled allows use of spring motions on the icons.
@@ -50,16 +48,15 @@ abstract class BaseFlags {
public static final boolean QSB_ON_FIRST_SCREEN = true;
// When enabled the all-apps icon is not added to the hotseat.
public static final boolean NO_ALL_APPS_ICON = true;
- // When enabled the status bar may show dark icons based on the top of the wallpaper.
- public static final boolean LIGHT_STATUS_BAR = false;
// When enabled, icons not supporting {@link AdaptiveIconDrawable} will be wrapped in {@link FixedScaleDrawable}.
public static final boolean LEGACY_ICON_TREATMENT = true;
// When enabled, adaptive icons would have shadows baked when being stored to icon cache.
public static final boolean ADAPTIVE_ICON_SHADOW = true;
// When enabled, app discovery will be enabled if service is implemented
public static final boolean DISCOVERY_ENABLED = false;
- // When enabled, the qsb will be moved to the hotseat.
- public static final boolean QSB_IN_HOTSEAT = true;
+
+ // When true, custom widgets are loaded using CustomWidgetParser.
+ public static final boolean ENABLE_CUSTOM_WIDGETS = false;
// Features to control Launcher3Go behavior
public static final boolean GO_DISABLE_WIDGETS = false;
diff --git a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
index d0f2629aa..727fb51ce 100644
--- a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
@@ -159,21 +159,6 @@ public abstract class BaseItemDragListener implements
}
@Override
- public boolean supportsAppInfoDropTarget() {
- return false;
- }
-
- @Override
- public boolean supportsDeleteDropTarget() {
- return false;
- }
-
- @Override
- public float getIntrinsicIconScaleFactor() {
- return 1f;
- }
-
- @Override
public void onDropCompleted(View target, DropTarget.DragObject d, boolean isFlingToDelete,
boolean success) {
if (isFlingToDelete || !success || (target != mLauncher.getWorkspace() &&
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index b8527148b..a7ed87fb6 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -27,7 +27,6 @@ import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
-import android.view.inputmethod.InputMethodManager;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget;
@@ -39,6 +38,7 @@ import com.android.launcher3.accessibility.DragViewStateAnnouncer;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.util.TouchController;
+import com.android.launcher3.util.UiThreadHelper;
import java.util.ArrayList;
@@ -138,8 +138,7 @@ public class DragController implements DragDriver.EventListener, TouchController
}
// Hide soft keyboard, if visible
- mLauncher.getSystemService(InputMethodManager.class)
- .hideSoftInputFromWindow(mWindowToken, 0);
+ UiThreadHelper.hideKeyboardAsync(mLauncher, mWindowToken);
mOptions = options;
if (mOptions.systemDndStartPoint != null) {
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index fde7995ce..60ce3c36a 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -24,13 +24,11 @@ import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
-import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.Region;
import android.support.v4.graphics.ColorUtils;
import android.util.AttributeSet;
import android.view.KeyEvent;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -42,13 +40,10 @@ import android.widget.FrameLayout;
import android.widget.TextView;
import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.AppWidgetResizeFrame;
import com.android.launcher3.CellLayout;
import com.android.launcher3.DropTargetBar;
-import com.android.launcher3.ExtendedEditText;
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherAppWidgetHostView;
import com.android.launcher3.PinchToOverviewListener;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutAndWidgetContainer;
@@ -59,11 +54,9 @@ import com.android.launcher3.dynamicui.WallpaperColorInfo;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
-import com.android.launcher3.logging.LoggerUtils;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.util.TouchController;
-import com.android.launcher3.widget.WidgetsBottomSheet;
import java.util.ArrayList;
@@ -81,10 +74,6 @@ public class DragLayer extends InsettableFrameLayout {
private Launcher mLauncher;
- // Variables relating to resizing widgets
- private final boolean mIsRtl;
- private AppWidgetResizeFrame mCurrentResizeFrame;
-
// Variables relating to animation of views after drop
private ValueAnimator mDropAnim = null;
private final TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
@@ -105,7 +94,6 @@ public class DragLayer extends InsettableFrameLayout {
private float mBackgroundAlpha = 0;
// Related to adjacent page hints
- private final Rect mScrollChildPosition = new Rect();
private final ViewGroupFocusHelper mFocusIndicatorHelper;
private final WallpaperColorInfo mWallpaperColorInfo;
@@ -129,7 +117,6 @@ public class DragLayer extends InsettableFrameLayout {
setMotionEventSplittingEnabled(false);
setChildrenDrawingOrderEnabled(true);
- mIsRtl = Utilities.isRtl(getResources());
mFocusIndicatorHelper = new ViewGroupFocusHelper(this);
mWallpaperColorInfo = WallpaperColorInfo.getInstance(getContext());
}
@@ -159,10 +146,6 @@ public class DragLayer extends InsettableFrameLayout {
? null : new PinchToOverviewListener(mLauncher);
}
- public boolean isEventOverPageIndicator(MotionEvent ev) {
- return isEventOverView(mLauncher.getWorkspace().getPageIndicator(), ev);
- }
-
public boolean isEventOverHotseat(MotionEvent ev) {
return isEventOverView(mLauncher.getHotseat(), ev);
}
@@ -180,36 +163,6 @@ public class DragLayer extends InsettableFrameLayout {
return mHitRect.contains((int) ev.getX(), (int) ev.getY());
}
- private boolean handleTouchDown(MotionEvent ev, boolean intercept) {
- AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mLauncher);
- if (topView != null && intercept) {
- ExtendedEditText textView = topView.getActiveTextView();
- if (textView != null) {
- if (!isEventOverView(textView, ev)) {
- textView.dispatchBackKey();
- return true;
- }
- } else if (!isEventOverView(topView, ev)) {
- if (isInAccessibleDrag()) {
- // Do not close the container if in drag and drop.
- if (!isEventOverDropTargetBar(ev)) {
- return true;
- }
- } else {
- mLauncher.getUserEventDispatcher().logActionTapOutside(
- LoggerUtils.newContainerTarget(topView.getLogContainerType()));
- topView.close(true);
-
- // We let touches on the original icon go through so that users can launch
- // the app with one tap if they don't find a shortcut they want.
- View extendedTouch = topView.getExtendedTouchView();
- return extendedTouch == null || !isEventOverView(extendedTouch, ev);
- }
- }
- }
- return false;
- }
-
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int action = ev.getAction();
@@ -219,9 +172,6 @@ public class DragLayer extends InsettableFrameLayout {
// dray layer even if mAllAppsController is NOT the active controller.
// TODO: handle other input other than touch
mAllAppsController.cancelDiscoveryAnimation();
- if (handleTouchDown(ev, true)) {
- return true;
- }
} else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
if (mTouchCompleteListener != null) {
mTouchCompleteListener.onTouchComplete();
@@ -230,12 +180,10 @@ public class DragLayer extends InsettableFrameLayout {
}
mActiveController = null;
- if (mCurrentResizeFrame != null
- && mCurrentResizeFrame.onControllerInterceptTouchEvent(ev)) {
- mActiveController = mCurrentResizeFrame;
+ AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mLauncher);
+ if (topView != null && topView.onControllerInterceptTouchEvent(ev)) {
+ mActiveController = topView;
return true;
- } else {
- clearResizeFrame();
}
if (mDragController.onControllerInterceptTouchEvent(ev)) {
@@ -248,12 +196,6 @@ public class DragLayer extends InsettableFrameLayout {
return true;
}
- WidgetsBottomSheet widgetsBottomSheet = WidgetsBottomSheet.getOpen(mLauncher);
- if (widgetsBottomSheet != null && widgetsBottomSheet.onControllerInterceptTouchEvent(ev)) {
- mActiveController = widgetsBottomSheet;
- return true;
- }
-
if (mPinchListener != null && mPinchListener.onControllerInterceptTouchEvent(ev)) {
// Stop listening for scrolling etc. (onTouchEvent() handles the rest of the pinch.)
mActiveController = mPinchListener;
@@ -357,12 +299,7 @@ public class DragLayer extends InsettableFrameLayout {
@Override
public boolean onTouchEvent(MotionEvent ev) {
int action = ev.getAction();
-
- if (action == MotionEvent.ACTION_DOWN) {
- if (handleTouchDown(ev, false)) {
- return true;
- }
- } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+ if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
if (mTouchCompleteListener != null) {
mTouchCompleteListener.onTouchComplete();
}
@@ -542,25 +479,6 @@ public class DragLayer extends InsettableFrameLayout {
}
}
- public void clearResizeFrame() {
- if (mCurrentResizeFrame != null) {
- removeView(mCurrentResizeFrame);
- mCurrentResizeFrame = null;
- }
- }
-
- public void addResizeFrame(LauncherAppWidgetHostView widget, CellLayout cellLayout) {
- clearResizeFrame();
-
- mCurrentResizeFrame = (AppWidgetResizeFrame) LayoutInflater.from(mLauncher)
- .inflate(R.layout.app_widget_resize_frame, this, false);
- mCurrentResizeFrame.setupForWidget(widget, cellLayout, this);
- ((LayoutParams) mCurrentResizeFrame.getLayoutParams()).customPosition = true;
-
- addView(mCurrentResizeFrame);
- mCurrentResizeFrame.snapToWidget(false);
- }
-
public void animateViewIntoPosition(DragView dragView, final int[] pos, float alpha,
float scaleX, float scaleY, int animationEndStyle, Runnable onFinishRunnable,
int duration) {
diff --git a/src/com/android/launcher3/dragndrop/DragOptions.java b/src/com/android/launcher3/dragndrop/DragOptions.java
index 9433aadc7..f108f8b53 100644
--- a/src/com/android/launcher3/dragndrop/DragOptions.java
+++ b/src/com/android/launcher3/dragndrop/DragOptions.java
@@ -34,6 +34,9 @@ public class DragOptions {
/** Determines when a pre-drag should transition to a drag. By default, this is immediate. */
public PreDragCondition preDragCondition = null;
+ /** Scale of the icons over the workspace icon size. */
+ public float intrinsicIconScaleFactor = 1f;
+
/**
* Specifies a condition that must be met before DragListener#onDragStart() is called.
* By default, there is no condition and onDragStart() is called immediately following
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index e81e2a386..17fad8496 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -169,7 +169,7 @@ public class DragView extends View {
}
});
- mBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight());
+ mBitmap = bitmap;
setDragRegion(new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()));
// The point in our scaled bitmap that the touch events are located
@@ -193,7 +193,7 @@ public class DragView extends View {
*/
@TargetApi(Build.VERSION_CODES.O)
public void setItemInfo(final ItemInfo info) {
- if (!(FeatureFlags.LAUNCHER3_SPRING_ICONS && Utilities.isAtLeastO())) {
+ if (!(FeatureFlags.LAUNCHER3_SPRING_ICONS && Utilities.ATLEAST_OREO)) {
return;
}
if (info.itemType != LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
@@ -427,6 +427,10 @@ public class DragView extends View {
return mDragRegion;
}
+ public Bitmap getPreviewBitmap() {
+ return mBitmap;
+ }
+
@Override
protected void onDraw(Canvas canvas) {
mHasDrawn = true;
diff --git a/src/com/android/launcher3/dragndrop/PinItemDragListener.java b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
index c8d3890ba..b9d97ac5a 100644
--- a/src/com/android/launcher3/dragndrop/PinItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/PinItemDragListener.java
@@ -128,7 +128,7 @@ public class PinItemDragListener extends BaseItemDragListener implements Parcela
}
public static boolean handleDragRequest(Launcher launcher, Intent intent) {
- if (!Utilities.isAtLeastO()) {
+ if (!Utilities.ATLEAST_OREO) {
return false;
}
if (intent == null || !Intent.ACTION_MAIN.equals(intent.getAction())) {
diff --git a/src/com/android/launcher3/dynamicui/ColorExtractionService.java b/src/com/android/launcher3/dynamicui/ColorExtractionService.java
deleted file mode 100644
index b9dd3b588..000000000
--- a/src/com/android/launcher3/dynamicui/ColorExtractionService.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.dynamicui;
-
-import android.annotation.TargetApi;
-import android.app.WallpaperManager;
-import android.app.job.JobParameters;
-import android.app.job.JobService;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.BitmapRegionDecoder;
-import android.graphics.Rect;
-import android.graphics.drawable.BitmapDrawable;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.HandlerThread;
-import android.os.ParcelFileDescriptor;
-import android.support.v7.graphics.Palette;
-import android.util.Log;
-
-import com.android.launcher3.LauncherProvider;
-import com.android.launcher3.LauncherSettings;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
-import com.android.launcher3.config.FeatureFlags;
-
-import java.io.IOException;
-
-/**
- * Extracts colors from the wallpaper, and saves results to {@link LauncherProvider}.
- */
-public class ColorExtractionService extends JobService {
-
- private static final String TAG = "ColorExtractionService";
- private static final boolean DEBUG = false;
-
- /** The fraction of the wallpaper to extract colors for use on the hotseat. */
- private static final float HOTSEAT_FRACTION = 1f / 4;
-
- private HandlerThread mWorkerThread;
- private Handler mWorkerHandler;
-
- @Override
- public void onCreate() {
- super.onCreate();
- mWorkerThread = new HandlerThread("ColorExtractionService");
- mWorkerThread.start();
- mWorkerHandler = new Handler(mWorkerThread.getLooper());
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- mWorkerThread.quit();
- }
-
- @Override
- public boolean onStartJob(final JobParameters jobParameters) {
- if (DEBUG) Log.d(TAG, "onStartJob");
- mWorkerHandler.post(new Runnable() {
- @Override
- public void run() {
- WallpaperManager wallpaperManager = WallpaperManager.getInstance(
- ColorExtractionService.this);
- int wallpaperId = ExtractionUtils.getWallpaperId(wallpaperManager);
-
- ExtractedColors extractedColors = new ExtractedColors();
- if (wallpaperManager.getWallpaperInfo() != null) {
- // We can't extract colors from live wallpapers; always use the default color.
- extractedColors.updateHotseatPalette(null);
-
- if (FeatureFlags.QSB_IN_HOTSEAT || FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
- extractedColors.updateWallpaperThemePalette(null);
- }
- } else {
- // We extract colors for the hotseat and status bar separately,
- // since they only consider part of the wallpaper.
- extractedColors.updateHotseatPalette(getHotseatPalette());
-
- if (FeatureFlags.LIGHT_STATUS_BAR) {
- extractedColors.updateStatusBarPalette(getStatusBarPalette());
- }
-
- if (FeatureFlags.QSB_IN_HOTSEAT || FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
- extractedColors.updateWallpaperThemePalette(getWallpaperPalette());
- }
- }
-
- // Save the extracted colors and wallpaper id to LauncherProvider.
- String colorsString = extractedColors.encodeAsString();
- Bundle extras = new Bundle();
- extras.putInt(LauncherSettings.Settings.EXTRA_WALLPAPER_ID, wallpaperId);
- extras.putString(LauncherSettings.Settings.EXTRA_EXTRACTED_COLORS, colorsString);
- getContentResolver().call(
- LauncherSettings.Settings.CONTENT_URI,
- LauncherSettings.Settings.METHOD_SET_EXTRACTED_COLORS_AND_WALLPAPER_ID,
- null, extras);
- jobFinished(jobParameters, false /* needsReschedule */);
- if (DEBUG) Log.d(TAG, "job finished!");
- }
- });
- return true;
- }
-
- @Override
- public boolean onStopJob(JobParameters jobParameters) {
- if (DEBUG) Log.d(TAG, "onStopJob");
- mWorkerHandler.removeCallbacksAndMessages(null);
- return true;
- }
-
- @TargetApi(Build.VERSION_CODES.N)
- private Palette getHotseatPalette() {
- WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
- if (Utilities.ATLEAST_NOUGAT) {
- try (ParcelFileDescriptor fd = wallpaperManager
- .getWallpaperFile(WallpaperManager.FLAG_SYSTEM)) {
- BitmapRegionDecoder decoder = BitmapRegionDecoder
- .newInstance(fd.getFileDescriptor(), false);
- int height = decoder.getHeight();
- Rect decodeRegion = new Rect(0, (int) (height * (1f - HOTSEAT_FRACTION)),
- decoder.getWidth(), height);
- Bitmap bitmap = decoder.decodeRegion(decodeRegion, null);
- decoder.recycle();
- if (bitmap != null) {
- return Palette.from(bitmap).clearFilters().generate();
- }
- } catch (IOException | NullPointerException e) {
- Log.e(TAG, "Fetching partial bitmap failed, trying old method", e);
- }
- }
-
- Bitmap wallpaper = ((BitmapDrawable) wallpaperManager.getDrawable()).getBitmap();
- return Palette.from(wallpaper)
- .setRegion(0, (int) (wallpaper.getHeight() * (1f - HOTSEAT_FRACTION)),
- wallpaper.getWidth(), wallpaper.getHeight())
- .clearFilters()
- .generate();
- }
-
- @TargetApi(Build.VERSION_CODES.N)
- private Palette getStatusBarPalette() {
- WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
- int statusBarHeight = getResources()
- .getDimensionPixelSize(R.dimen.status_bar_height);
-
- if (Utilities.ATLEAST_NOUGAT) {
- try (ParcelFileDescriptor fd = wallpaperManager
- .getWallpaperFile(WallpaperManager.FLAG_SYSTEM)) {
- BitmapRegionDecoder decoder = BitmapRegionDecoder
- .newInstance(fd.getFileDescriptor(), false);
- Rect decodeRegion = new Rect(0, 0,
- decoder.getWidth(), statusBarHeight);
- Bitmap bitmap = decoder.decodeRegion(decodeRegion, null);
- decoder.recycle();
- if (bitmap != null) {
- return Palette.from(bitmap).clearFilters().generate();
- }
- } catch (IOException | NullPointerException e) {
- Log.e(TAG, "Fetching partial bitmap failed, trying old method", e);
- }
- }
-
- Bitmap wallpaper = ((BitmapDrawable) wallpaperManager.getDrawable()).getBitmap();
- return Palette.from(wallpaper)
- .setRegion(0, 0, wallpaper.getWidth(), statusBarHeight)
- .clearFilters()
- .generate();
- }
-
- @TargetApi(Build.VERSION_CODES.N)
- private Palette getWallpaperPalette() {
- WallpaperManager wallpaperManager = WallpaperManager.getInstance(this);
- if (Utilities.ATLEAST_NOUGAT) {
- try (ParcelFileDescriptor fd = wallpaperManager
- .getWallpaperFile(WallpaperManager.FLAG_SYSTEM)) {
- Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fd.getFileDescriptor());
- if (bitmap != null) {
- return Palette.from(bitmap).clearFilters().generate();
- }
- } catch (IOException | NullPointerException e) {
- Log.e(TAG, "Fetching partial bitmap failed, trying old method", e);
- }
- }
-
- Bitmap wallpaper = ((BitmapDrawable) wallpaperManager.getDrawable()).getBitmap();
- return Palette.from(wallpaper).clearFilters().generate();
- }
-}
diff --git a/src/com/android/launcher3/dynamicui/ExtractedColors.java b/src/com/android/launcher3/dynamicui/ExtractedColors.java
deleted file mode 100644
index 2d8bb869f..000000000
--- a/src/com/android/launcher3/dynamicui/ExtractedColors.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.dynamicui;
-
-import android.app.WallpaperManager;
-import android.content.Context;
-import android.graphics.Color;
-import android.support.annotation.Nullable;
-import android.support.v4.graphics.ColorUtils;
-import android.support.v7.graphics.Palette;
-import android.util.Log;
-
-import com.android.launcher3.Utilities;
-import com.android.launcher3.config.FeatureFlags;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-
-/**
- * Saves and loads colors extracted from the wallpaper, as well as the associated wallpaper id.
- */
-public class ExtractedColors {
- private static final String TAG = "ExtractedColors";
-
- public static final int DEFAULT_LIGHT = Color.WHITE;
- public static final int DEFAULT_DARK = Color.BLACK;
-
- // These color profile indices should NOT be changed, since they are used when saving and
- // loading extracted colors. New colors should always be added at the end.
- public static final int VERSION_INDEX = 0;
- public static final int HOTSEAT_INDEX = 1;
- public static final int STATUS_BAR_INDEX = 2;
- public static final int WALLPAPER_VIBRANT_INDEX = 3;
- public static final int ALLAPPS_GRADIENT_MAIN_INDEX = 4;
- public static final int ALLAPPS_GRADIENT_SECONDARY_INDEX = 5;
-
- private static final int VERSION;
- private static final int[] DEFAULT_VALUES;
-
- static {
- if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
- VERSION = 3;
- DEFAULT_VALUES = new int[] {
- VERSION, // VERSION_INDEX
- 0x40FFFFFF, // HOTSEAT_INDEX: White with 25% alpha
- DEFAULT_DARK, // STATUS_BAR_INDEX
- 0xFFCCCCCC, // WALLPAPER_VIBRANT_INDEX
- 0xFF000000, // ALLAPPS_GRADIENT_MAIN_INDEX
- 0xFF000000 // ALLAPPS_GRADIENT_SECONDARY_INDEX
- };
- } else if (FeatureFlags.QSB_IN_HOTSEAT) {
- VERSION = 2;
- DEFAULT_VALUES = new int[] {
- VERSION, // VERSION_INDEX
- 0x40FFFFFF, // HOTSEAT_INDEX: White with 25% alpha
- DEFAULT_DARK, // STATUS_BAR_INDEX
- 0xFFCCCCCC, // WALLPAPER_VIBRANT_INDEX
- };
- } else {
- VERSION = 1;
- DEFAULT_VALUES = new int[] {
- VERSION, // VERSION_INDEX
- 0x40FFFFFF, // HOTSEAT_INDEX: White with 25% alpha
- DEFAULT_DARK, // STATUS_BAR_INDEX
- };
- }
- }
-
- private static final String COLOR_SEPARATOR = ",";
-
- private final ArrayList<OnChangeListener> mListeners = new ArrayList<>();
- private final int[] mColors;
-
- public ExtractedColors() {
- // The first entry is reserved for the version number.
- mColors = Arrays.copyOf(DEFAULT_VALUES, DEFAULT_VALUES.length);
- }
-
- public void setColorAtIndex(int index, int color) {
- if (index > VERSION_INDEX && index < mColors.length) {
- mColors[index] = color;
- } else {
- Log.e(TAG, "Attempted to set a color at an invalid index " + index);
- }
- }
-
- /**
- * Encodes {@link #mColors} as a comma-separated String.
- */
- String encodeAsString() {
- StringBuilder colorsStringBuilder = new StringBuilder();
- for (int color : mColors) {
- colorsStringBuilder.append(color).append(COLOR_SEPARATOR);
- }
- return colorsStringBuilder.toString();
- }
-
- /**
- * Loads colors and wallpaper id from {@link Utilities#getPrefs(Context)}.
- * These were saved there in {@link ColorExtractionService}.
- */
- public void load(Context context) {
- String encodedString = Utilities.getPrefs(context).getString(
- ExtractionUtils.EXTRACTED_COLORS_PREFERENCE_KEY, VERSION + "");
-
- String[] splitColorsString = encodedString.split(COLOR_SEPARATOR);
- if (splitColorsString.length == DEFAULT_VALUES.length &&
- Integer.parseInt(splitColorsString[VERSION_INDEX]) == VERSION) {
- // Parse and apply the saved values.
- for (int i = 0; i < mColors.length; i++) {
- mColors[i] = Integer.parseInt(splitColorsString[i]);
- }
- } else {
- // Leave the values as default values as the saved values may not be compatible.
- ExtractionUtils.startColorExtractionService(context);
- }
- }
-
- /** @param index must be one of the index values defined at the top of this class. */
- public int getColor(int index) {
- return mColors[index];
- }
-
- /**
- * The hotseat's color is defined as follows:
- * - 12% black for super light wallpaper
- * - 18% white for super dark
- * - 25% white otherwise
- */
- public void updateHotseatPalette(Palette hotseatPalette) {
- int hotseatColor;
- if (hotseatPalette != null && ExtractionUtils.isSuperLight(hotseatPalette)) {
- hotseatColor = ColorUtils.setAlphaComponent(Color.BLACK, (int) (0.12f * 255));
- } else if (hotseatPalette != null && ExtractionUtils.isSuperDark(hotseatPalette)) {
- hotseatColor = ColorUtils.setAlphaComponent(Color.WHITE, (int) (0.18f * 255));
- } else {
- hotseatColor = DEFAULT_VALUES[HOTSEAT_INDEX];
- }
- setColorAtIndex(HOTSEAT_INDEX, hotseatColor);
- }
-
- public void updateStatusBarPalette(Palette statusBarPalette) {
- setColorAtIndex(STATUS_BAR_INDEX, ExtractionUtils.isSuperLight(statusBarPalette) ?
- DEFAULT_LIGHT : DEFAULT_DARK);
- }
-
- public void updateWallpaperThemePalette(@Nullable Palette wallpaperPalette) {
- int defaultColor = DEFAULT_VALUES[WALLPAPER_VIBRANT_INDEX];
- setColorAtIndex(WALLPAPER_VIBRANT_INDEX, wallpaperPalette == null
- ? defaultColor : wallpaperPalette.getVibrantColor(defaultColor));
- }
-
- public void addOnChangeListener(OnChangeListener listener) {
- mListeners.add(listener);
- }
-
- public void notifyChange() {
- for (OnChangeListener listener : mListeners) {
- listener.onExtractedColorsChanged();
- }
- }
-
- /**
- * Interface for listening for extracted color changes
- */
- public interface OnChangeListener {
-
- void onExtractedColorsChanged();
- }
-}
diff --git a/src/com/android/launcher3/dynamicui/ExtractionUtils.java b/src/com/android/launcher3/dynamicui/ExtractionUtils.java
deleted file mode 100644
index cc0e0bed1..000000000
--- a/src/com/android/launcher3/dynamicui/ExtractionUtils.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.launcher3.dynamicui;
-
-import android.annotation.TargetApi;
-import android.app.WallpaperManager;
-import android.app.job.JobInfo;
-import android.app.job.JobScheduler;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.graphics.Color;
-import android.os.Build;
-import android.support.v4.graphics.ColorUtils;
-import android.support.v7.graphics.Palette;
-
-import com.android.launcher3.Utilities;
-import com.android.launcher3.config.FeatureFlags;
-
-import java.util.List;
-
-/**
- * Contains helper fields and methods related to extracting colors from the wallpaper.
- */
-public class ExtractionUtils {
- public static final String EXTRACTED_COLORS_PREFERENCE_KEY = "pref_extractedColors";
- public static final String WALLPAPER_ID_PREFERENCE_KEY = "pref_wallpaperId";
-
- private static final float MIN_CONTRAST_RATIO = 2f;
-
- /**
- * Extract colors in the :wallpaper-chooser process, if the wallpaper id has changed.
- * When the new colors are saved in the LauncherProvider,
- * Launcher will be notified in Launcher#onSettingsChanged(String, String).
- */
- public static void startColorExtractionServiceIfNecessary(final Context context) {
- if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
- return;
- }
- // Run on a background thread, since the service is asynchronous anyway.
- Utilities.THREAD_POOL_EXECUTOR.execute(new Runnable() {
- @Override
- public void run() {
- if (hasWallpaperIdChanged(context)) {
- startColorExtractionService(context);
- }
- }
- });
- }
-
- /** Starts the {@link ColorExtractionService} without checking the wallpaper id */
- public static void startColorExtractionService(Context context) {
- if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
- return;
- }
- JobScheduler jobScheduler = (JobScheduler) context.getSystemService(
- Context.JOB_SCHEDULER_SERVICE);
- jobScheduler.schedule(new JobInfo.Builder(Utilities.COLOR_EXTRACTION_JOB_ID,
- new ComponentName(context, ColorExtractionService.class))
- .setMinimumLatency(0).build());
- }
-
- private static boolean hasWallpaperIdChanged(Context context) {
- if (!Utilities.ATLEAST_NOUGAT) {
- // TODO: update an id in sharedprefs in onWallpaperChanged broadcast, and read it here.
- return false;
- }
- final SharedPreferences sharedPrefs = Utilities.getPrefs(context);
- int wallpaperId = getWallpaperId(WallpaperManager.getInstance(context));
- int savedWallpaperId = sharedPrefs.getInt(ExtractionUtils.WALLPAPER_ID_PREFERENCE_KEY, -1);
- return wallpaperId != savedWallpaperId;
- }
-
- @TargetApi(Build.VERSION_CODES.N)
- public static int getWallpaperId(WallpaperManager wallpaperManager) {
- return Utilities.ATLEAST_NOUGAT ?
- wallpaperManager.getWallpaperId(WallpaperManager.FLAG_SYSTEM) : -1;
- }
-
- public static boolean isSuperLight(Palette p) {
- return !isLegibleOnWallpaper(Color.WHITE, p.getSwatches());
- }
-
- public static boolean isSuperDark(Palette p) {
- return !isLegibleOnWallpaper(Color.BLACK, p.getSwatches());
- }
-
- /**
- * Given a color, returns true if that color is legible on
- * the given wallpaper color swatches, else returns false.
- */
- private static boolean isLegibleOnWallpaper(int color, List<Palette.Swatch> wallpaperSwatches) {
- int legiblePopulation = 0;
- int illegiblePopulation = 0;
- for (Palette.Swatch swatch : wallpaperSwatches) {
- if (isLegible(color, swatch.getRgb())) {
- legiblePopulation += swatch.getPopulation();
- } else {
- illegiblePopulation += swatch.getPopulation();
- }
- }
- return legiblePopulation > illegiblePopulation;
- }
-
- /** @return Whether the foreground color is legible on the background color. */
- private static boolean isLegible(int foreground, int background) {
- background = ColorUtils.setAlphaComponent(background, 255);
- return ColorUtils.calculateContrast(foreground, background) >= MIN_CONTRAST_RATIO;
- }
-
-}
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index b7f8f3e2e..0932b7411 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -32,6 +32,7 @@ import android.view.FocusFinder;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewDebug;
import android.view.accessibility.AccessibilityEvent;
@@ -66,6 +67,7 @@ import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragController.DragListener;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragOptions;
+import com.android.launcher3.logging.LoggerUtils;
import com.android.launcher3.pageindicators.PageIndicatorDots;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
@@ -368,11 +370,6 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
return false;
}
- @Override
- public ExtendedEditText getActiveTextView() {
- return isEditingName() ? mFolderName : null;
- }
-
public FolderIcon getFolderIcon() {
return mFolderIcon;
}
@@ -709,6 +706,7 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
mContent.setCurrentPage(0);
}
+ @Override
public boolean acceptDrop(DragObject d) {
final ItemInfo item = d.dragInfo;
final int itemType = item.itemType;
@@ -941,21 +939,6 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
}
}
- @Override
- public float getIntrinsicIconScaleFactor() {
- return 1f;
- }
-
- @Override
- public boolean supportsAppInfoDropTarget() {
- return true;
- }
-
- @Override
- public boolean supportsDeleteDropTarget() {
- return true;
- }
-
private void updateItemLocationsInDatabaseBatch() {
ArrayList<View> list = getItemsInReadingOrder();
ArrayList<ItemInfo> items = new ArrayList<ItemInfo>();
@@ -1532,7 +1515,45 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
}
@Override
- public int getLogContainerType() {
- return ContainerType.FOLDER;
+ public void logActionCommand(int command) {
+ mLauncher.getUserEventDispatcher().logActionCommand(
+ command, getFolderIcon(), ContainerType.FOLDER);
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (isEditingName()) {
+ mFolderName.dispatchBackKey();
+ } else {
+ super.onBackPressed();
+ }
+ }
+
+ @Override
+ public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ DragLayer dl = mLauncher.getDragLayer();
+
+ if (isEditingName()) {
+ if (!dl.isEventOverView(mFolderName, ev)) {
+ mFolderName.dispatchBackKey();
+ return true;
+ }
+ return false;
+ } else if (!dl.isEventOverView(this, ev)) {
+ if (mLauncher.getAccessibilityDelegate().isInAccessibleDrag()) {
+ // Do not close the container if in drag and drop.
+ if (!dl.isEventOverView(mLauncher.getDropTargetBar(), ev)) {
+ return true;
+ }
+ } else {
+ mLauncher.getUserEventDispatcher().logActionTapOutside(
+ LoggerUtils.newContainerTarget(ContainerType.FOLDER));
+ close(true);
+ return true;
+ }
+ }
+ }
+ return false;
}
}
diff --git a/src/com/android/launcher3/graphics/DragPreviewProvider.java b/src/com/android/launcher3/graphics/DragPreviewProvider.java
index 10e91c0a8..355c231f3 100644
--- a/src/com/android/launcher3/graphics/DragPreviewProvider.java
+++ b/src/com/android/launcher3/graphics/DragPreviewProvider.java
@@ -18,10 +18,15 @@ package com.android.launcher3.graphics;
import android.content.Context;
import android.graphics.Bitmap;
+import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Region.Op;
import android.graphics.drawable.Drawable;
+import android.os.Handler;
import android.view.View;
import com.android.launcher3.BubbleTextView;
@@ -30,6 +35,9 @@ import com.android.launcher3.LauncherAppWidgetHostView;
import com.android.launcher3.R;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.FolderIcon;
+import com.android.launcher3.util.UiThreadHelper;
+
+import java.nio.ByteBuffer;
/**
* A utility class to generate preview bitmap for dragging.
@@ -45,6 +53,7 @@ public class DragPreviewProvider {
protected final int blurSizeOutline;
+ private OutlineGeneratorCallback mOutlineGeneratorCallback;
public Bitmap generatedDragOutline;
public DragPreviewProvider(View view) {
@@ -106,7 +115,7 @@ public class DragPreviewProvider {
* Returns a new bitmap to show when the {@link #mView} is being dragged around.
* Responsibility for the bitmap is transferred to the caller.
*/
- public Bitmap createDragBitmap(Canvas canvas) {
+ public Bitmap createDragBitmap() {
float scale = 1f;
int width = mView.getWidth();
int height = mView.getHeight();
@@ -124,7 +133,7 @@ public class DragPreviewProvider {
Bitmap b = Bitmap.createBitmap(width + blurSizeOutline, height + blurSizeOutline,
Bitmap.Config.ARGB_8888);
- canvas.setBitmap(b);
+ Canvas canvas = new Canvas(b);
canvas.save();
canvas.scale(scale, scale);
@@ -136,43 +145,13 @@ public class DragPreviewProvider {
return b;
}
- public final void generateDragOutline(Canvas canvas) {
- if (FeatureFlags.IS_DOGFOOD_BUILD && generatedDragOutline != null) {
+ public final void generateDragOutline(Bitmap preview) {
+ if (FeatureFlags.IS_DOGFOOD_BUILD && mOutlineGeneratorCallback != null) {
throw new RuntimeException("Drag outline generated twice");
}
- generatedDragOutline = createDragOutline(canvas);
- }
-
- /**
- * Returns a new bitmap to be used as the object outline, e.g. to visualize the drop location.
- * Responsibility for the bitmap is transferred to the caller.
- */
- public Bitmap createDragOutline(Canvas canvas) {
- float scale = 1f;
- int width = mView.getWidth();
- int height = mView.getHeight();
-
- if (mView instanceof LauncherAppWidgetHostView) {
- scale = ((LauncherAppWidgetHostView) mView).getScaleToFit();
- width = (int) Math.floor(mView.getWidth() * scale);
- height = (int) Math.floor(mView.getHeight() * scale);
- }
-
- Bitmap b = Bitmap.createBitmap(width + blurSizeOutline, height + blurSizeOutline,
- Bitmap.Config.ALPHA_8);
- canvas.setBitmap(b);
-
- canvas.save();
- canvas.scale(scale, scale);
- drawDragView(canvas);
- canvas.restore();
-
- HolographicOutlineHelper.getInstance(mView.getContext())
- .applyExpensiveOutlineWithBlur(b, canvas);
-
- canvas.setBitmap(null);
- return b;
+ mOutlineGeneratorCallback = new OutlineGeneratorCallback(preview);
+ new Handler(UiThreadHelper.getBackgroundLooper()).post(mOutlineGeneratorCallback);
}
protected static Rect getDrawableBounds(Drawable d) {
@@ -201,4 +180,89 @@ public class DragPreviewProvider {
- previewPadding / 2);
return scale;
}
+
+ protected Bitmap convertPreviewToAlphaBitmap(Bitmap preview) {
+ return preview.copy(Bitmap.Config.ALPHA_8, true);
+ }
+
+ private class OutlineGeneratorCallback implements Runnable {
+
+ private final Bitmap mPreviewSnapshot;
+ private final Context mContext;
+
+ OutlineGeneratorCallback(Bitmap preview) {
+ mPreviewSnapshot = preview;
+ mContext = mView.getContext();
+ }
+
+ @Override
+ public void run() {
+ Bitmap preview = convertPreviewToAlphaBitmap(mPreviewSnapshot);
+
+ // We start by removing most of the alpha channel so as to ignore shadows, and
+ // other types of partial transparency when defining the shape of the object
+ byte[] pixels = new byte[preview.getWidth() * preview.getHeight()];
+ ByteBuffer buffer = ByteBuffer.wrap(pixels);
+ buffer.rewind();
+ preview.copyPixelsToBuffer(buffer);
+
+ for (int i = 0; i < pixels.length; i++) {
+ if ((pixels[i] & 0xFF) < 188) {
+ pixels[i] = 0;
+ }
+ }
+
+ buffer.rewind();
+ preview.copyPixelsFromBuffer(buffer);
+
+ final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
+ Canvas canvas = new Canvas();
+
+ // calculate the outer blur first
+ paint.setMaskFilter(new BlurMaskFilter(blurSizeOutline, BlurMaskFilter.Blur.OUTER));
+ int[] outerBlurOffset = new int[2];
+ Bitmap thickOuterBlur = preview.extractAlpha(paint, outerBlurOffset);
+
+ paint.setMaskFilter(new BlurMaskFilter(
+ mContext.getResources().getDimension(R.dimen.blur_size_thin_outline),
+ BlurMaskFilter.Blur.OUTER));
+ int[] brightOutlineOffset = new int[2];
+ Bitmap brightOutline = preview.extractAlpha(paint, brightOutlineOffset);
+
+ // calculate the inner blur
+ canvas.setBitmap(preview);
+ canvas.drawColor(0xFF000000, PorterDuff.Mode.SRC_OUT);
+ paint.setMaskFilter(new BlurMaskFilter(blurSizeOutline, BlurMaskFilter.Blur.NORMAL));
+ int[] thickInnerBlurOffset = new int[2];
+ Bitmap thickInnerBlur = preview.extractAlpha(paint, thickInnerBlurOffset);
+
+ // mask out the inner blur
+ paint.setMaskFilter(null);
+ paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
+ canvas.setBitmap(thickInnerBlur);
+ canvas.drawBitmap(preview, -thickInnerBlurOffset[0],
+ -thickInnerBlurOffset[1], paint);
+ canvas.drawRect(0, 0, -thickInnerBlurOffset[0], thickInnerBlur.getHeight(), paint);
+ canvas.drawRect(0, 0, thickInnerBlur.getWidth(), -thickInnerBlurOffset[1], paint);
+
+ // draw the inner and outer blur
+ paint.setXfermode(null);
+ canvas.setBitmap(preview);
+ canvas.drawColor(0, PorterDuff.Mode.CLEAR);
+ canvas.drawBitmap(thickInnerBlur, thickInnerBlurOffset[0], thickInnerBlurOffset[1],
+ paint);
+ canvas.drawBitmap(thickOuterBlur, outerBlurOffset[0], outerBlurOffset[1], paint);
+
+ // draw the bright outline
+ canvas.drawBitmap(brightOutline, brightOutlineOffset[0], brightOutlineOffset[1], paint);
+
+ // cleanup
+ canvas.setBitmap(null);
+ brightOutline.recycle();
+ thickOuterBlur.recycle();
+ thickInnerBlur.recycle();
+
+ generatedDragOutline = preview;
+ }
+ }
}
diff --git a/src/com/android/launcher3/graphics/DrawableFactory.java b/src/com/android/launcher3/graphics/DrawableFactory.java
index 45344c020..371479b36 100644
--- a/src/com/android/launcher3/graphics/DrawableFactory.java
+++ b/src/com/android/launcher3/graphics/DrawableFactory.java
@@ -80,7 +80,7 @@ public class DrawableFactory {
protected Path getPreloadProgressPath(Context context) {
- if (Utilities.isAtLeastO()) {
+ if (Utilities.ATLEAST_OREO) {
try {
// Try to load the path from Mask Icon
Drawable icon = context.getDrawable(R.drawable.adaptive_icon_drawable_wrapper);
diff --git a/src/com/android/launcher3/graphics/HolographicOutlineHelper.java b/src/com/android/launcher3/graphics/HolographicOutlineHelper.java
index b22182883..9e67f56e3 100644
--- a/src/com/android/launcher3/graphics/HolographicOutlineHelper.java
+++ b/src/com/android/launcher3/graphics/HolographicOutlineHelper.java
@@ -17,7 +17,6 @@
package com.android.launcher3.graphics;
import android.content.Context;
-import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
@@ -31,9 +30,6 @@ import android.util.SparseArray;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.R;
-import com.android.launcher3.config.FeatureFlags;
-
-import java.nio.ByteBuffer;
/**
* Utility class to generate shadow and outline effect, which are used for click feedback
@@ -44,14 +40,9 @@ public class HolographicOutlineHelper {
private static HolographicOutlineHelper sInstance;
private final Canvas mCanvas = new Canvas();
- private final Paint mDrawPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
private final Paint mBlurPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
private final Paint mErasePaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
- private final BlurMaskFilter mMediumOuterBlurMaskFilter;
- private final BlurMaskFilter mThinOuterBlurMaskFilter;
- private final BlurMaskFilter mMediumInnerBlurMaskFilter;
-
private final float mShadowBitmapShift;
private final BlurMaskFilter mShadowBlurMaskFilter;
@@ -59,18 +50,8 @@ public class HolographicOutlineHelper {
private final SparseArray<Bitmap> mBitmapCache = new SparseArray<>(4);
private HolographicOutlineHelper(Context context) {
- Resources res = context.getResources();
-
- float mediumBlur = res.getDimension(R.dimen.blur_size_medium_outline);
- mMediumOuterBlurMaskFilter = new BlurMaskFilter(mediumBlur, BlurMaskFilter.Blur.OUTER);
- mMediumInnerBlurMaskFilter = new BlurMaskFilter(mediumBlur, BlurMaskFilter.Blur.NORMAL);
-
- mThinOuterBlurMaskFilter = new BlurMaskFilter(
- res.getDimension(R.dimen.blur_size_thin_outline), BlurMaskFilter.Blur.OUTER);
-
- mShadowBitmapShift = res.getDimension(R.dimen.blur_size_click_shadow);
+ mShadowBitmapShift = context.getResources().getDimension(R.dimen.blur_size_click_shadow);
mShadowBlurMaskFilter = new BlurMaskFilter(mShadowBitmapShift, BlurMaskFilter.Blur.NORMAL);
-
mErasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
}
@@ -81,75 +62,6 @@ public class HolographicOutlineHelper {
return sInstance;
}
- /**
- * Applies a more expensive and accurate outline to whatever is currently drawn in a specified
- * bitmap.
- */
- public void applyExpensiveOutlineWithBlur(Bitmap srcDst, Canvas srcDstCanvas) {
- if (FeatureFlags.IS_DOGFOOD_BUILD && srcDst.getConfig() != Bitmap.Config.ALPHA_8) {
- throw new RuntimeException("Outline blue is only supported on alpha bitmaps");
- }
-
- // We start by removing most of the alpha channel so as to ignore shadows, and
- // other types of partial transparency when defining the shape of the object
- byte[] pixels = new byte[srcDst.getWidth() * srcDst.getHeight()];
- ByteBuffer buffer = ByteBuffer.wrap(pixels);
- buffer.rewind();
- srcDst.copyPixelsToBuffer(buffer);
-
- for (int i = 0; i < pixels.length; i++) {
- if ((pixels[i] & 0xFF) < 188) {
- pixels[i] = 0;
- }
- }
-
- buffer.rewind();
- srcDst.copyPixelsFromBuffer(buffer);
-
- // calculate the outer blur first
- mBlurPaint.setMaskFilter(mMediumOuterBlurMaskFilter);
- int[] outerBlurOffset = new int[2];
- Bitmap thickOuterBlur = srcDst.extractAlpha(mBlurPaint, outerBlurOffset);
-
- mBlurPaint.setMaskFilter(mThinOuterBlurMaskFilter);
- int[] brightOutlineOffset = new int[2];
- Bitmap brightOutline = srcDst.extractAlpha(mBlurPaint, brightOutlineOffset);
-
- // calculate the inner blur
- srcDstCanvas.setBitmap(srcDst);
- srcDstCanvas.drawColor(0xFF000000, PorterDuff.Mode.SRC_OUT);
- mBlurPaint.setMaskFilter(mMediumInnerBlurMaskFilter);
- int[] thickInnerBlurOffset = new int[2];
- Bitmap thickInnerBlur = srcDst.extractAlpha(mBlurPaint, thickInnerBlurOffset);
-
- // mask out the inner blur
- srcDstCanvas.setBitmap(thickInnerBlur);
- srcDstCanvas.drawBitmap(srcDst, -thickInnerBlurOffset[0],
- -thickInnerBlurOffset[1], mErasePaint);
- srcDstCanvas.drawRect(0, 0, -thickInnerBlurOffset[0], thickInnerBlur.getHeight(),
- mErasePaint);
- srcDstCanvas.drawRect(0, 0, thickInnerBlur.getWidth(), -thickInnerBlurOffset[1],
- mErasePaint);
-
- // draw the inner and outer blur
- srcDstCanvas.setBitmap(srcDst);
- srcDstCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
- srcDstCanvas.drawBitmap(thickInnerBlur, thickInnerBlurOffset[0], thickInnerBlurOffset[1],
- mDrawPaint);
- srcDstCanvas.drawBitmap(thickOuterBlur, outerBlurOffset[0], outerBlurOffset[1],
- mDrawPaint);
-
- // draw the bright outline
- srcDstCanvas.drawBitmap(brightOutline, brightOutlineOffset[0], brightOutlineOffset[1],
- mDrawPaint);
-
- // cleanup
- srcDstCanvas.setBitmap(null);
- brightOutline.recycle();
- thickOuterBlur.recycle();
- thickInnerBlur.recycle();
- }
-
public Bitmap createMediumDropShadow(BubbleTextView view) {
Drawable drawable = view.getIcon();
if (drawable == null) {
diff --git a/src/com/android/launcher3/graphics/IconNormalizer.java b/src/com/android/launcher3/graphics/IconNormalizer.java
index 8ed62bcdc..5ee6a30b7 100644
--- a/src/com/android/launcher3/graphics/IconNormalizer.java
+++ b/src/com/android/launcher3/graphics/IconNormalizer.java
@@ -28,12 +28,15 @@ import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.AdaptiveIconDrawable;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.Utilities;
+import com.android.launcher3.dragndrop.FolderAdaptiveIcon;
+
import java.io.File;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
@@ -231,12 +234,17 @@ public class IconNormalizer {
*/
public synchronized float getScale(@NonNull Drawable d, @Nullable RectF outBounds,
@Nullable Path path, @Nullable boolean[] outMaskShape) {
- if (Utilities.isAtLeastO() && d instanceof AdaptiveIconDrawable &&
- mAdaptiveIconScale != SCALE_NOT_INITIALIZED) {
- if (outBounds != null) {
- outBounds.set(mAdaptiveIconBounds);
+ if (Utilities.ATLEAST_OREO && d instanceof AdaptiveIconDrawable) {
+ if (mAdaptiveIconScale != SCALE_NOT_INITIALIZED) {
+ if (outBounds != null) {
+ outBounds.set(mAdaptiveIconBounds);
+ }
+ return mAdaptiveIconScale;
+ }
+ if (d instanceof FolderAdaptiveIcon) {
+ // Since we just want the scale, avoid heavy drawing operations
+ d = new AdaptiveIconDrawable(new ColorDrawable(Color.BLACK), null);
}
- return mAdaptiveIconScale;
}
int width = d.getIntrinsicWidth();
int height = d.getIntrinsicHeight();
@@ -347,7 +355,7 @@ public class IconNormalizer {
float areaScale = area / (width * height);
// Use sqrt of the final ratio as the images is scaled across both width and height.
float scale = areaScale > scaleRequired ? (float) Math.sqrt(scaleRequired / areaScale) : 1;
- if (Utilities.isAtLeastO() && d instanceof AdaptiveIconDrawable &&
+ if (Utilities.ATLEAST_OREO && d instanceof AdaptiveIconDrawable &&
mAdaptiveIconScale == SCALE_NOT_INITIALIZED) {
mAdaptiveIconScale = scale;
mAdaptiveIconBounds.set(mBounds);
diff --git a/src/com/android/launcher3/graphics/IconShapeOverride.java b/src/com/android/launcher3/graphics/IconShapeOverride.java
index 654fa98bc..223243b7a 100644
--- a/src/com/android/launcher3/graphics/IconShapeOverride.java
+++ b/src/com/android/launcher3/graphics/IconShapeOverride.java
@@ -59,7 +59,7 @@ public class IconShapeOverride {
private static final int RESTART_REQUEST_CODE = 42; // the answer to everything
public static boolean isSupported(Context context) {
- if (!Utilities.isAtLeastO()) {
+ if (!Utilities.ATLEAST_OREO) {
return false;
}
// Only supported when developer settings is enabled
@@ -82,7 +82,7 @@ public class IconShapeOverride {
}
public static void apply(Context context) {
- if (!Utilities.isAtLeastO()) {
+ if (!Utilities.ATLEAST_OREO) {
return;
}
String path = getAppliedValue(context);
diff --git a/src/com/android/launcher3/graphics/LauncherIcons.java b/src/com/android/launcher3/graphics/LauncherIcons.java
index 7c80c3098..d471af6e7 100644
--- a/src/com/android/launcher3/graphics/LauncherIcons.java
+++ b/src/com/android/launcher3/graphics/LauncherIcons.java
@@ -16,10 +16,12 @@
package com.android.launcher3.graphics;
+import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.Intent.ShortcutIconResource;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -70,11 +72,15 @@ public class LauncherIcons {
PackageManager packageManager = context.getPackageManager();
// the resource
try {
- Resources resources = packageManager.getResourcesForApplication(iconRes.packageName);
+ Resources resources = packageManager.getResourcesForApplication(iconRes.resourceName);
if (resources != null) {
final int id = resources.getIdentifier(iconRes.resourceName, null, null);
- return createIconBitmap(resources.getDrawableForDensity(
- id, LauncherAppState.getIDP(context).fillResIconDpi), context);
+ // do not stamp old legacy shortcuts as the app may have already forgotten about it
+ return createBadgedIconBitmap(resources.getDrawableForDensity(
+ id, LauncherAppState.getIDP(context).fillResIconDpi),
+ Process.myUserHandle() /* only available on primary user */,
+ context,
+ 0 /* do not apply legacy treatment */);
}
} catch (Exception e) {
// Icon not found.
@@ -90,11 +96,12 @@ public class LauncherIcons {
if (iconBitmapSize == icon.getWidth() && iconBitmapSize == icon.getHeight()) {
return icon;
}
- return createIconBitmap(new BitmapDrawable(context.getResources(), icon), context);
+ return createIconBitmap(new BitmapDrawable(context.getResources(), icon), context, 1f);
}
/**
- * Returns a bitmap suitable for the all apps view. The icon is badged for {@param user}.
+ * Returns a bitmap suitable for displaying as an icon at various launcher UIs like all apps
+ * view or workspace. The icon is badged for {@param user}.
* The bitmap is also visually normalized with other icons.
*/
public static Bitmap createBadgedIconBitmap(
@@ -104,7 +111,7 @@ public class LauncherIcons {
float scale = 1f;
if (!FeatureFlags.LAUNCHER3_DISABLE_ICON_NORMALIZATION) {
normalizer = IconNormalizer.getInstance(context);
- if (Utilities.isAtLeastO() && iconAppTargetSdk >= Build.VERSION_CODES.O) {
+ if (Utilities.ATLEAST_OREO && iconAppTargetSdk >= Build.VERSION_CODES.O) {
boolean[] outShape = new boolean[1];
AdaptiveIconDrawable dr = (AdaptiveIconDrawable)
context.getDrawable(R.drawable.adaptive_icon_drawable_wrapper).mutate();
@@ -123,28 +130,22 @@ public class LauncherIcons {
}
}
Bitmap bitmap = createIconBitmap(icon, context, scale);
- if (FeatureFlags.ADAPTIVE_ICON_SHADOW && Utilities.isAtLeastO() &&
+ if (FeatureFlags.ADAPTIVE_ICON_SHADOW && Utilities.ATLEAST_OREO &&
icon instanceof AdaptiveIconDrawable) {
bitmap = ShadowGenerator.getInstance(context).recreateIcon(bitmap);
}
- return badgeIconForUser(bitmap, user, context);
- }
- /**
- * Badges the provided icon with the user badge if required.
- */
- public static Bitmap badgeIconForUser(Bitmap icon, UserHandle user, Context context) {
if (user != null && !Process.myUserHandle().equals(user)) {
- BitmapDrawable drawable = new FixedSizeBitmapDrawable(icon);
+ BitmapDrawable drawable = new FixedSizeBitmapDrawable(bitmap);
Drawable badged = context.getPackageManager().getUserBadgedIcon(
drawable, user);
if (badged instanceof BitmapDrawable) {
return ((BitmapDrawable) badged).getBitmap();
} else {
- return createIconBitmap(badged, context);
+ return createIconBitmap(badged, context, 1f);
}
} else {
- return icon;
+ return bitmap;
}
}
@@ -152,19 +153,20 @@ public class LauncherIcons {
* Creates a normalized bitmap suitable for the all apps view. The bitmap is also visually
* normalized with other icons and has enough spacing to add shadow.
*/
- public static Bitmap createScaledBitmapWithoutShadow(Drawable icon, Context context, int iconAppTargetSdk) {
+ public static Bitmap createScaledBitmapWithoutShadow(
+ Drawable icon, Context context, int iconAppTargetSdk) {
RectF iconBounds = new RectF();
IconNormalizer normalizer;
float scale = 1f;
if (!FeatureFlags.LAUNCHER3_DISABLE_ICON_NORMALIZATION) {
normalizer = IconNormalizer.getInstance(context);
- if (Utilities.isAtLeastO() && iconAppTargetSdk >= Build.VERSION_CODES.O) {
+ if (Utilities.ATLEAST_OREO && iconAppTargetSdk >= Build.VERSION_CODES.O) {
boolean[] outShape = new boolean[1];
AdaptiveIconDrawable dr = (AdaptiveIconDrawable)
context.getDrawable(R.drawable.adaptive_icon_drawable_wrapper).mutate();
dr.setBounds(0, 0, 1, 1);
scale = normalizer.getScale(icon, iconBounds, dr.getIconMask(), outShape);
- if (Utilities.isAtLeastO() && FeatureFlags.LEGACY_ICON_TREATMENT &&
+ if (Utilities.ATLEAST_OREO && FeatureFlags.LEGACY_ICON_TREATMENT &&
!outShape[0]) {
Drawable wrappedIcon = wrapToAdaptiveIconDrawable(context, icon, scale);
if (wrappedIcon != icon) {
@@ -181,21 +183,6 @@ public class LauncherIcons {
return createIconBitmap(icon, context, scale);
}
- /**
- * Adds a shadow to the provided icon. It assumes that the icon has already been scaled using
- * {@link #createScaledBitmapWithoutShadow(Drawable, Context, int)}
- */
- public static Bitmap addShadowToIcon(Bitmap icon, Context context) {
- return ShadowGenerator.getInstance(context).recreateIcon(icon);
- }
-
- /**
- * Adds the {@param badge} on top of {@param srcTgt} using the badge dimensions.
- */
- public static Bitmap badgeWithBitmap(Bitmap srcTgt, Bitmap badge, Context context) {
- return badgeWithDrawable(srcTgt, new FastBitmapDrawable(badge), context);
- }
-
public static Bitmap badgeWithDrawable(Bitmap srcTgt, Drawable badge, Context context) {
int badgeSize = context.getResources().getDimensionPixelSize(R.dimen.profile_badge_size);
synchronized (sCanvas) {
@@ -209,26 +196,9 @@ public class LauncherIcons {
}
/**
- * Returns a bitmap suitable for the all apps view.
- */
- public static Bitmap createIconBitmap(Drawable icon, Context context) {
- float scale = 1f;
- if (FeatureFlags.ADAPTIVE_ICON_SHADOW && Utilities.isAtLeastO() &&
- icon instanceof AdaptiveIconDrawable) {
- scale = ShadowGenerator.getScaleForBounds(new RectF(0, 0, 0, 0));
- }
- Bitmap bitmap = createIconBitmap(icon, context, scale);
- if (FeatureFlags.ADAPTIVE_ICON_SHADOW && Utilities.isAtLeastO() &&
- icon instanceof AdaptiveIconDrawable) {
- bitmap = ShadowGenerator.getInstance(context).recreateIcon(bitmap);
- }
- return bitmap;
- }
-
- /**
* @param scale the scale to apply before drawing {@param icon} on the canvas
*/
- public static Bitmap createIconBitmap(Drawable icon, Context context, float scale) {
+ private static Bitmap createIconBitmap(Drawable icon, Context context, float scale) {
synchronized (sCanvas) {
final int iconBitmapSize = LauncherAppState.getIDP(context).iconBitmapSize;
int width = iconBitmapSize;
@@ -271,7 +241,7 @@ public class LauncherIcons {
final int top = (textureHeight-height) / 2;
sOldBounds.set(icon.getBounds());
- if (Utilities.isAtLeastO() && icon instanceof AdaptiveIconDrawable) {
+ if (Utilities.ATLEAST_OREO && icon instanceof AdaptiveIconDrawable) {
int offset = Math.max((int)(ShadowGenerator.BLUR_FACTOR * iconBitmapSize),
Math.min(left, top));
int size = Math.max(width, height);
@@ -295,8 +265,10 @@ public class LauncherIcons {
* shrink the legacy icon and set it as foreground. Use color drawable as background to
* create AdaptiveIconDrawable.
*/
- static Drawable wrapToAdaptiveIconDrawable(Context context, Drawable drawable, float scale) {
- if (!(FeatureFlags.LEGACY_ICON_TREATMENT && Utilities.isAtLeastO())) {
+ @TargetApi(Build.VERSION_CODES.O)
+ private static Drawable wrapToAdaptiveIconDrawable(
+ Context context, Drawable drawable, float scale) {
+ if (!(FeatureFlags.LEGACY_ICON_TREATMENT && Utilities.ATLEAST_OREO)) {
return drawable;
}
@@ -307,7 +279,7 @@ public class LauncherIcons {
FixedScaleDrawable fsd = ((FixedScaleDrawable) iconWrapper.getForeground());
fsd.setDrawable(drawable);
fsd.setScale(scale);
- return (Drawable) iconWrapper;
+ return iconWrapper;
}
} catch (Exception e) {
return drawable;
@@ -326,15 +298,9 @@ public class LauncherIcons {
public static Bitmap createShortcutIcon(ShortcutInfoCompat shortcutInfo, Context context,
final Bitmap fallbackIcon) {
- Provider<Bitmap> fallbackIconProvider = new Provider<Bitmap>() {
- @Override
- public Bitmap get() {
- // If the shortcut is pinned but no longer has an icon in the system,
- // keep the current icon instead of reverting to the default icon.
- return fallbackIcon;
- }
- };
- return createShortcutIcon(shortcutInfo, context, true, fallbackIconProvider);
+ // If the shortcut is pinned but no longer has an icon in the system,
+ // keep the current icon instead of reverting to the default icon.
+ return createShortcutIcon(shortcutInfo, context, true, Provider.of(fallbackIcon));
}
public static Bitmap createShortcutIcon(ShortcutInfoCompat shortcutInfo, Context context,
@@ -360,8 +326,9 @@ public class LauncherIcons {
if (!badged) {
return unbadgedBitmap;
}
- unbadgedBitmap = LauncherIcons.addShadowToIcon(unbadgedBitmap, context);
- return badgeWithBitmap(unbadgedBitmap, getShortcutInfoBadge(shortcutInfo, cache), context);
+ unbadgedBitmap = ShadowGenerator.getInstance(context).recreateIcon(unbadgedBitmap);
+ return badgeWithDrawable(unbadgedBitmap,
+ new FastBitmapDrawable(getShortcutInfoBadge(shortcutInfo, cache)), context);
}
public static Bitmap getShortcutInfoBadge(ShortcutInfoCompat shortcutInfo, IconCache cache) {
diff --git a/src/com/android/launcher3/graphics/ShadowDrawable.java b/src/com/android/launcher3/graphics/ShadowDrawable.java
index ffcedb26a..b40bf7828 100644
--- a/src/com/android/launcher3/graphics/ShadowDrawable.java
+++ b/src/com/android/launcher3/graphics/ShadowDrawable.java
@@ -146,7 +146,7 @@ public class ShadowDrawable extends Drawable {
d.draw(canvas);
}
- if (Utilities.isAtLeastO()) {
+ if (Utilities.ATLEAST_OREO) {
bitmap = bitmap.copy(Bitmap.Config.HARDWARE, false);
}
mState.mLastDrawnBitmap = bitmap;
diff --git a/src/com/android/launcher3/logging/LoggerUtils.java b/src/com/android/launcher3/logging/LoggerUtils.java
index ebb69c43b..81333b1a2 100644
--- a/src/com/android/launcher3/logging/LoggerUtils.java
+++ b/src/com/android/launcher3/logging/LoggerUtils.java
@@ -105,13 +105,13 @@ public class LoggerUtils {
private static String getItemStr(Target t) {
String typeStr = getFieldName(t.itemType, ItemType.class);
if (t.packageNameHash != 0) {
- typeStr += ", packageHash=" + t.packageNameHash;
+ typeStr += ", packageHash=" + t.packageNameHash + ", predictiveRank=" + t.predictedRank;
}
if (t.componentHash != 0) {
- typeStr += ", componentHash=" + t.componentHash;
+ typeStr += ", componentHash=" + t.componentHash + ", predictiveRank=" + t.predictedRank;
}
if (t.intentHash != 0) {
- typeStr += ", intentHash=" + t.intentHash;
+ typeStr += ", intentHash=" + t.intentHash + ", predictiveRank=" + t.predictedRank;
}
return typeStr + ", grid(" + t.gridX + "," + t.gridY + "), span(" + t.spanX + "," + t.spanY
+ "), pageIdx=" + t.pageIndex;
@@ -125,9 +125,11 @@ public class LoggerUtils {
public static Target newItemTarget(ItemInfo info) {
Target t = newTarget(Target.Type.ITEM);
+
switch (info.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
t.itemType = ItemType.APP_ICON;
+ t.predictedRank = -100; // Never assigned
break;
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
t.itemType = ItemType.SHORTCUT;
diff --git a/src/com/android/launcher3/model/GridSizeMigrationTask.java b/src/com/android/launcher3/model/GridSizeMigrationTask.java
index 8de0de053..d9b1a3f9e 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationTask.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationTask.java
@@ -726,7 +726,7 @@ public class GridSizeMigrationTask {
mContext).getLauncherAppWidgetInfo(widgetId);
Point spans = null;
if (pInfo != null) {
- spans = pInfo.getMinSpans(mIdp, mContext);
+ spans = pInfo.getMinSpans();
}
if (spans != null) {
entry.minSpanX = spans.x > 0 ? spans.x : entry.spanX;
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index e1b208a05..5386fb4a5 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -66,6 +66,7 @@ import com.android.launcher3.util.ManagedProfileHeuristic;
import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Provider;
+import com.android.launcher3.util.TraceHelper;
import java.util.ArrayList;
import java.util.Collections;
@@ -85,7 +86,6 @@ import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_I
* - deep shortcuts within apps
*/
public class LoaderTask implements Runnable {
- private static final boolean DEBUG_LOADERS = false;
private static final String TAG = "LoaderTask";
private final LauncherAppState mApp;
@@ -142,73 +142,64 @@ public class LoaderTask implements Runnable {
}
}
+ TraceHelper.beginSection(TAG);
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
- long now = 0;
- if (DEBUG_LOADERS) Log.d(TAG, "step 1.1: loading workspace");
+ TraceHelper.partitionSection(TAG, "step 1.1: loading workspace");
loadWorkspace();
verifyNotStopped();
- if (DEBUG_LOADERS) Log.d(TAG, "step 1.2: bind workspace workspace");
+ TraceHelper.partitionSection(TAG, "step 1.2: bind workspace workspace");
mResults.bindWorkspace();
// Take a break
- if (DEBUG_LOADERS) {
- Log.d(TAG, "step 1 completed, wait for idle");
- now = SystemClock.uptimeMillis();
- }
+ TraceHelper.partitionSection(TAG, "step 1 completed, wait for idle");
waitForIdle();
- if (DEBUG_LOADERS) Log.d(TAG, "Waited " + (SystemClock.uptimeMillis() - now) + "ms");
verifyNotStopped();
// second step
- if (DEBUG_LOADERS) Log.d(TAG, "step 2.1: loading all apps");
+ TraceHelper.partitionSection(TAG, "step 2.1: loading all apps");
loadAllApps();
- if (DEBUG_LOADERS) Log.d(TAG, "step 2.2: Binding all apps");
+ TraceHelper.partitionSection(TAG, "step 2.2: Binding all apps");
verifyNotStopped();
mResults.bindAllApps();
verifyNotStopped();
- if (DEBUG_LOADERS) Log.d(TAG, "step 2.3: Update icon cache");
+ TraceHelper.partitionSection(TAG, "step 2.3: Update icon cache");
updateIconCache();
// Take a break
- if (DEBUG_LOADERS) {
- Log.d(TAG, "step 2 completed, wait for idle");
- now = SystemClock.uptimeMillis();
- }
+ TraceHelper.partitionSection(TAG, "step 2 completed, wait for idle");
waitForIdle();
- if (DEBUG_LOADERS) Log.d(TAG, "Waited " + (SystemClock.uptimeMillis() - now) + "ms");
verifyNotStopped();
// third step
- if (DEBUG_LOADERS) Log.d(TAG, "step 3.1: loading deep shortcuts");
+ TraceHelper.partitionSection(TAG, "step 3.1: loading deep shortcuts");
loadDeepShortcuts();
verifyNotStopped();
- if (DEBUG_LOADERS) Log.d(TAG, "step 3.2: bind deep shortcuts");
+ TraceHelper.partitionSection(TAG, "step 3.2: bind deep shortcuts");
mResults.bindDeepShortcuts();
// Take a break
- if (DEBUG_LOADERS) Log.d(TAG, "step 3 completed, wait for idle");
+ TraceHelper.partitionSection(TAG, "step 3 completed, wait for idle");
waitForIdle();
verifyNotStopped();
// fourth step
- if (DEBUG_LOADERS) Log.d(TAG, "step 4.1: loading widgets");
+ TraceHelper.partitionSection(TAG, "step 4.1: loading widgets");
mBgDataModel.widgetsModel.update(mApp, null);
verifyNotStopped();
- if (DEBUG_LOADERS) Log.d(TAG, "step 4.2: Binding widgets");
+ TraceHelper.partitionSection(TAG, "step 4.2: Binding widgets");
mResults.bindWidgets();
transaction.commit();
} catch (CancellationException e) {
// Loader stopped, ignore
- if (DEBUG_LOADERS) {
- Log.d(TAG, "Loader cancelled", e);
- }
+ TraceHelper.partitionSection(TAG, "Cancelled");
}
+ TraceHelper.endSection(TAG);
}
public synchronized void stopLocked() {
@@ -217,10 +208,6 @@ public class LoaderTask implements Runnable {
}
private void loadWorkspace() {
- if (LauncherAppState.PROFILE_STARTUP) {
- Trace.beginSection("Loading Workspace");
- }
-
final Context context = mApp.getContext();
final ContentResolver contentResolver = context.getContentResolver();
final PackageManagerHelper pmHelper = new PackageManagerHelper(context);
@@ -766,9 +753,6 @@ public class LoaderTask implements Runnable {
LauncherModel.updateWorkspaceScreenOrder(context, mBgDataModel.workspaceScreens);
}
}
- if (LauncherAppState.PROFILE_STARTUP) {
- Trace.endSection();
- }
}
private void updateIconCache() {
@@ -793,21 +777,13 @@ public class LoaderTask implements Runnable {
}
private void loadAllApps() {
- final long loadTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
-
final List<UserHandle> profiles = mUserManager.getUserProfiles();
// Clear the list of apps
mBgAllAppsList.clear();
for (UserHandle user : profiles) {
// Query for the set of apps
- final long qiaTime = DEBUG_LOADERS ? SystemClock.uptimeMillis() : 0;
final List<LauncherActivityInfo> apps = mLauncherApps.getActivityList(null, user);
- if (DEBUG_LOADERS) {
- Log.d(TAG, "getActivityList took "
- + (SystemClock.uptimeMillis()-qiaTime) + "ms for user " + user);
- Log.d(TAG, "getActivityList got " + apps.size() + " apps for user " + user);
- }
// Fail if we don't have any apps
// TODO: Fix this. Only fail for the current user.
if (apps == null || apps.isEmpty()) {
@@ -834,10 +810,6 @@ public class LoaderTask implements Runnable {
}
mBgAllAppsList.added = new ArrayList<>();
- if (DEBUG_LOADERS) {
- Log.d(TAG, "All apps loaded in in "
- + (SystemClock.uptimeMillis() - loadTime) + "ms");
- }
}
private void loadDeepShortcuts() {
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index 13962a259..78ecbc621 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -101,7 +101,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
appsList.addPackage(context, packages[i], mUser);
// Automatically add homescreen icon for work profile apps for below O device.
- if (!Utilities.isAtLeastO() && !Process.myUserHandle().equals(mUser)) {
+ if (!Utilities.ATLEAST_OREO && !Process.myUserHandle().equals(mUser)) {
SessionCommitReceiver.queueAppIconAddition(context, packages[i], mUser);
}
}
@@ -178,6 +178,9 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
if (mOp == OP_ADD || flagOp != FlagOp.NO_OP) {
final ArrayList<ShortcutInfo> updatedShortcuts = new ArrayList<>();
final ArrayList<LauncherAppWidgetInfo> widgets = new ArrayList<>();
+
+ // For system apps, package manager send OP_UPDATE when an app is enabled.
+ final boolean isNewApkAvailable = mOp == OP_ADD || mOp == OP_UPDATE;
synchronized (dataModel) {
for (ItemInfo info : dataModel.itemsIdMap) {
if (info instanceof ShortcutInfo && mUser.equals(info.user)) {
@@ -206,9 +209,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
}
}
- // For system apps, package manager send OP_UPDATE when an
- // app is enabled.
- if (si.isPromise() && (mOp == OP_ADD || mOp == OP_UPDATE)) {
+ if (si.isPromise() && isNewApkAvailable) {
if (si.hasStatusFlag(ShortcutInfo.FLAG_AUTOINSTALL_ICON)) {
// Auto install icon
LauncherAppsCompat launcherApps
@@ -231,10 +232,13 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
continue;
}
}
+ } else {
+ si.status = ShortcutInfo.DEFAULT;
+ infoUpdated = true;
}
}
- if ((mOp == OP_ADD || mOp == OP_UPDATE) &&
+ if (isNewApkAvailable &&
si.itemType == Favorites.ITEM_TYPE_APPLICATION) {
iconCache.getTitleAndIcon(si, si.usingLowResIcon);
infoUpdated = true;
@@ -253,7 +257,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
if (infoUpdated) {
getModelWriter().updateItemInDatabase(si);
}
- } else if (info instanceof LauncherAppWidgetInfo && mOp == OP_ADD) {
+ } else if (info instanceof LauncherAppWidgetInfo && isNewApkAvailable) {
LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) info;
if (mUser.equals(widgetInfo.user)
&& widgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
@@ -342,8 +346,9 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
callbacks.notifyWidgetProvidersChanged();
}
});
- } else if (Utilities.isAtLeastO() && mOp == OP_ADD) {
- // Load widgets for the new package.
+ } else if (Utilities.ATLEAST_OREO && mOp == OP_ADD) {
+ // Load widgets for the new package. Changes due to app updates are handled through
+ // AppWidgetHost events, this is just to initialize the long-press options.
for (int i = 0; i < N; i++) {
dataModel.widgetsModel.update(app, new PackageUserKey(packages[i], mUser));
}
diff --git a/src/com/android/launcher3/notification/NotificationGroup.java b/src/com/android/launcher3/notification/NotificationGroup.java
new file mode 100644
index 000000000..bce211754
--- /dev/null
+++ b/src/com/android/launcher3/notification/NotificationGroup.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.notification;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Contains data related to a group of notifications, like the group summary key and the child keys.
+ */
+public class NotificationGroup {
+ private String mGroupSummaryKey;
+ private Set<String> mChildKeys;
+
+ public NotificationGroup() {
+ mChildKeys = new HashSet<>();
+ }
+
+ public void setGroupSummaryKey(String groupSummaryKey) {
+ mGroupSummaryKey = groupSummaryKey;
+ }
+
+ public String getGroupSummaryKey() {
+ return mGroupSummaryKey;
+ }
+
+ public void addChildKey(String childKey) {
+ mChildKeys.add(childKey);
+ }
+
+ public void removeChildKey(String childKey) {
+ mChildKeys.remove(childKey);
+ }
+
+ public boolean isEmpty() {
+ return mChildKeys.isEmpty();
+ }
+}
diff --git a/src/com/android/launcher3/notification/NotificationInfo.java b/src/com/android/launcher3/notification/NotificationInfo.java
index 1b7c87b22..6e36f4f51 100644
--- a/src/com/android/launcher3/notification/NotificationInfo.java
+++ b/src/com/android/launcher3/notification/NotificationInfo.java
@@ -94,6 +94,9 @@ public class NotificationInfo implements View.OnClickListener {
@Override
public void onClick(View view) {
+ if (intent == null) {
+ return;
+ }
final Launcher launcher = Launcher.getLauncher(view.getContext());
Bundle activityOptions = ActivityOptions.makeClipRevealAnimation(
view, 0, 0, view.getWidth(), view.getHeight()).toBundle();
diff --git a/src/com/android/launcher3/notification/NotificationListener.java b/src/com/android/launcher3/notification/NotificationListener.java
index 91266263f..7b70df77e 100644
--- a/src/com/android/launcher3/notification/NotificationListener.java
+++ b/src/com/android/launcher3/notification/NotificationListener.java
@@ -38,7 +38,9 @@ import com.android.launcher3.util.SettingsObserver;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import static com.android.launcher3.SettingsActivity.NOTIFICATION_BADGING;
@@ -66,6 +68,8 @@ public class NotificationListener extends NotificationListenerService {
private final Handler mWorkerHandler;
private final Handler mUiHandler;
private final Ranking mTempRanking = new Ranking();
+ /** Maps groupKey's to the corresponding group of notifications. */
+ private final Map<String, NotificationGroup> mNotificationGroupMap = new HashMap<>();
private SettingsObserver mNotificationBadgingObserver;
@@ -227,6 +231,15 @@ public class NotificationListener extends NotificationListenerService {
NotificationKeyData.fromNotification(sbn));
mWorkerHandler.obtainMessage(MSG_NOTIFICATION_REMOVED, packageUserKeyAndNotificationKey)
.sendToTarget();
+
+ NotificationGroup notificationGroup = mNotificationGroupMap.get(sbn.getGroupKey());
+ if (notificationGroup != null) {
+ notificationGroup.removeChildKey(sbn.getKey());
+ if (notificationGroup.isEmpty()) {
+ cancelNotification(notificationGroup.getGroupSummaryKey());
+ mNotificationGroupMap.remove(sbn.getGroupKey());
+ }
+ }
}
/** This makes a potentially expensive binder call and should be run on a background thread. */
@@ -264,18 +277,34 @@ public class NotificationListener extends NotificationListenerService {
}
private boolean shouldBeFilteredOut(StatusBarNotification sbn) {
+ Notification notification = sbn.getNotification();
+
+ boolean isGroupHeader = (notification.flags & Notification.FLAG_GROUP_SUMMARY) != 0;
+ if (sbn.isGroup()) {
+ // Maintain group info so we can cancel the summary when the last child is canceled.
+ NotificationGroup notificationGroup = mNotificationGroupMap.get(sbn.getGroupKey());
+ if (notificationGroup == null) {
+ notificationGroup = new NotificationGroup();
+ mNotificationGroupMap.put(sbn.getGroupKey(), notificationGroup);
+ }
+ if (isGroupHeader) {
+ notificationGroup.setGroupSummaryKey(sbn.getKey());
+ } else {
+ notificationGroup.addChildKey(sbn.getKey());
+ }
+ }
+
getCurrentRanking().getRanking(sbn.getKey(), mTempRanking);
if (!mTempRanking.canShowBadge()) {
return true;
}
- Notification notification = sbn.getNotification();
if (mTempRanking.getChannel().getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
// Special filtering for the default, legacy "Miscellaneous" channel.
if ((notification.flags & Notification.FLAG_ONGOING_EVENT) != 0) {
return true;
}
}
- boolean isGroupHeader = (notification.flags & Notification.FLAG_GROUP_SUMMARY) != 0;
+
CharSequence title = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
CharSequence text = notification.extras.getCharSequence(Notification.EXTRA_TEXT);
boolean missingTitleAndText = TextUtils.isEmpty(title) && TextUtils.isEmpty(text);
diff --git a/src/com/android/launcher3/pageindicators/PageIndicator.java b/src/com/android/launcher3/pageindicators/PageIndicator.java
index 47c2ffb38..d6ef5b4c8 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicator.java
@@ -20,8 +20,6 @@ import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.FrameLayout;
-import com.android.launcher3.dynamicui.ExtractedColors;
-
/**
* Base class for a page indicator.
*/
@@ -74,8 +72,6 @@ public abstract class PageIndicator extends FrameLayout {
public void setShouldAutoHide(boolean shouldAutoHide) {}
- public void updateColor(ExtractedColors extractedColors) {}
-
@Override
protected boolean verifyDrawable(Drawable who) {
return super.verifyDrawable(who) || who == getCaretDrawable();
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorCaretLandscape.java b/src/com/android/launcher3/pageindicators/PageIndicatorCaretLandscape.java
index 682d5a967..911be93fc 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorCaretLandscape.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorCaretLandscape.java
@@ -48,7 +48,6 @@ public class PageIndicatorCaretLandscape extends PageIndicator {
setCaretDrawable(caretDrawable);
Launcher l = Launcher.getLauncher(context);
- setOnTouchListener(l.getHapticFeedbackTouchListener());
setOnClickListener(l);
setOnFocusChangeListener(l.mFocusHandler);
}
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java b/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java
index 29834d764..5eedd92fd 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java
@@ -11,9 +11,7 @@ import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.os.Looper;
-import android.support.v4.graphics.ColorUtils;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.Property;
import android.view.ViewConfiguration;
import android.widget.ImageView;
@@ -21,8 +19,6 @@ import android.widget.ImageView;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.dynamicui.ExtractedColors;
import com.android.launcher3.dynamicui.WallpaperColorInfo;
/**
@@ -31,9 +27,6 @@ import com.android.launcher3.dynamicui.WallpaperColorInfo;
* The fraction is 1 / number of pages and the position is based on the progress of the page scroll.
*/
public class PageIndicatorLineCaret extends PageIndicator {
- private static final String TAG = "PageIndicatorLine";
-
- private static final int[] sTempCoords = new int[2];
private static final int LINE_ANIMATE_DURATION = ViewConfiguration.getScrollBarFadeDuration();
private static final int LINE_FADE_DELAY = ViewConfiguration.getScrollDefaultDelay();
@@ -141,7 +134,6 @@ public class PageIndicatorLineCaret extends PageIndicator {
super.onFinishInflate();
mAllAppsHandle = (ImageView) findViewById(R.id.all_apps_handle);
mAllAppsHandle.setImageDrawable(getCaretDrawable());
- mAllAppsHandle.setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
mAllAppsHandle.setOnClickListener(mLauncher);
mAllAppsHandle.setOnFocusChangeListener(mLauncher.mFocusHandler);
mLauncher.setAllAppsButton(mAllAppsHandle);
@@ -219,32 +211,6 @@ public class PageIndicatorLineCaret extends PageIndicator {
}
}
- /**
- * The line's color will be:
- * - mostly opaque white if the hotseat is white (ignoring alpha)
- * - mostly opaque black if the hotseat is black (ignoring alpha)
- */
- public void updateColor(ExtractedColors extractedColors) {
- if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
- return;
- }
- int originalLineAlpha = mLinePaint.getAlpha();
- int color = extractedColors.getColor(ExtractedColors.HOTSEAT_INDEX);
- if (color != Color.TRANSPARENT) {
- color = ColorUtils.setAlphaComponent(color, 255);
- if (color == Color.BLACK) {
- mActiveAlpha = BLACK_ALPHA;
- } else if (color == Color.WHITE) {
- mActiveAlpha = WHITE_ALPHA;
- } else {
- Log.e(TAG, "Setting workspace page indicators to an unsupported color: #"
- + Integer.toHexString(color));
- }
- mLinePaint.setColor(color);
- mLinePaint.setAlpha(originalLineAlpha);
- }
- }
-
private void animateLineToAlpha(int alpha) {
if (alpha == mToAlpha) {
// Ignore the new animation if it is going to the same alpha as the current animation.
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 8441598cf..5c49b4bdf 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -16,6 +16,11 @@
package com.android.launcher3.popup;
+import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS_IF_NOTIFICATIONS;
+import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
+import static com.android.launcher3.userevent.nano.LauncherLogProto.ItemType;
+import static com.android.launcher3.userevent.nano.LauncherLogProto.Target;
+
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@@ -66,6 +71,7 @@ import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.graphics.IconPalette;
import com.android.launcher3.graphics.TriangleShape;
+import com.android.launcher3.logging.LoggerUtils;
import com.android.launcher3.notification.NotificationItemView;
import com.android.launcher3.notification.NotificationKeyData;
import com.android.launcher3.shortcuts.DeepShortcutManager;
@@ -81,11 +87,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-import static com.android.launcher3.popup.PopupPopulator.MAX_SHORTCUTS_IF_NOTIFICATIONS;
-import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
-import static com.android.launcher3.userevent.nano.LauncherLogProto.ItemType;
-import static com.android.launcher3.userevent.nano.LauncherLogProto.Target;
-
/**
* A container for shortcuts to deep links within apps.
*/
@@ -593,11 +594,6 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra
return arrowView;
}
- @Override
- public View getExtendedTouchView() {
- return mOriginalIcon;
- }
-
/**
* Determines when the deferred drag should be started.
*
@@ -797,21 +793,6 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra
}
@Override
- public boolean supportsAppInfoDropTarget() {
- return true;
- }
-
- @Override
- public boolean supportsDeleteDropTarget() {
- return false;
- }
-
- @Override
- public float getIntrinsicIconScaleFactor() {
- return 1f;
- }
-
- @Override
public void onDropCompleted(View target, DropTarget.DragObject d, boolean isFlingToDelete,
boolean success) {
if (!success) {
@@ -950,7 +931,25 @@ public class PopupContainerWithArrow extends AbstractFloatingView implements Dra
}
@Override
- public int getLogContainerType() {
- return ContainerType.DEEPSHORTCUTS;
+ public void logActionCommand(int command) {
+ mLauncher.getUserEventDispatcher().logActionCommand(
+ command, mOriginalIcon, ContainerType.DEEPSHORTCUTS);
+ }
+
+ @Override
+ public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ DragLayer dl = mLauncher.getDragLayer();
+ if (!dl.isEventOverView(this, ev)) {
+ mLauncher.getUserEventDispatcher().logActionTapOutside(
+ LoggerUtils.newContainerTarget(ContainerType.DEEPSHORTCUTS));
+ close(true);
+
+ // We let touches on the original icon go through so that users can launch
+ // the app with one tap if they don't find a shortcut they want.
+ return mOriginalIcon == null || !dl.isEventOverView(mOriginalIcon, ev);
+ }
+ }
+ return false;
}
}
diff --git a/src/com/android/launcher3/qsb/QsbContainerView.java b/src/com/android/launcher3/qsb/QsbContainerView.java
index d26f9f646..65acaa973 100644
--- a/src/com/android/launcher3/qsb/QsbContainerView.java
+++ b/src/com/android/launcher3/qsb/QsbContainerView.java
@@ -36,6 +36,7 @@ import android.widget.FrameLayout;
import com.android.launcher3.AppWidgetResizeFrame;
import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -79,10 +80,15 @@ public class QsbContainerView extends FrameLayout {
private AppWidgetProviderInfo mWidgetInfo;
private QsbWidgetHostView mQsb;
+ // We need to store the orientation here, due to a bug (b/64916689) that results in widgets
+ // being inflated in the wrong orientation.
+ private int mOrientation;
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mQsbWidgetHost = new QsbWidgetHost(getActivity());
+ mOrientation = getContext().getResources().getConfiguration().orientation;
}
private FrameLayout mWrapper;
@@ -193,7 +199,7 @@ public class QsbContainerView extends FrameLayout {
@Override
public void onResume() {
super.onResume();
- if (mQsb != null && mQsb.isReinflateRequired()) {
+ if (mQsb != null && mQsb.isReinflateRequired(mOrientation)) {
rebindFragment();
}
}
diff --git a/src/com/android/launcher3/qsb/QsbWidgetHostView.java b/src/com/android/launcher3/qsb/QsbWidgetHostView.java
index 8b6fa1651..a8a41f664 100644
--- a/src/com/android/launcher3/qsb/QsbWidgetHostView.java
+++ b/src/com/android/launcher3/qsb/QsbWidgetHostView.java
@@ -47,9 +47,9 @@ public class QsbWidgetHostView extends AppWidgetHostView {
}
- public boolean isReinflateRequired() {
+ public boolean isReinflateRequired(int orientation) {
// Re-inflate is required if the orientation has changed since last inflation.
- return mPreviousOrientation != getResources().getConfiguration().orientation;
+ return mPreviousOrientation != orientation;
}
diff --git a/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java b/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java
index e9d2b50ea..cfb9258dd 100644
--- a/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java
+++ b/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java
@@ -26,7 +26,6 @@ import android.view.View;
import com.android.launcher3.Launcher;
import com.android.launcher3.Utilities;
import com.android.launcher3.graphics.DragPreviewProvider;
-import com.android.launcher3.graphics.HolographicOutlineHelper;
/**
* Extension of {@link DragPreviewProvider} which generates bitmaps scaled to the default icon size.
@@ -40,35 +39,17 @@ public class ShortcutDragPreviewProvider extends DragPreviewProvider {
mPositionShift = shift;
}
- @Override
- public Bitmap createDragOutline(Canvas canvas) {
- Bitmap b = drawScaledPreview(canvas, Bitmap.Config.ALPHA_8);
-
- HolographicOutlineHelper.getInstance(mView.getContext())
- .applyExpensiveOutlineWithBlur(b, canvas);
- canvas.setBitmap(null);
- return b;
- }
-
- @Override
- public Bitmap createDragBitmap(Canvas canvas) {
- Bitmap b = drawScaledPreview(canvas, Bitmap.Config.ARGB_8888);
- canvas.setBitmap(null);
- return b;
- }
-
- private Bitmap drawScaledPreview(Canvas canvas, Bitmap.Config config) {
+ public Bitmap createDragBitmap() {
Drawable d = mView.getBackground();
Rect bounds = getDrawableBounds(d);
int size = Launcher.getLauncher(mView.getContext()).getDeviceProfile().iconSizePx;
-
final Bitmap b = Bitmap.createBitmap(
size + blurSizeOutline,
size + blurSizeOutline,
- config);
+ Bitmap.Config.ARGB_8888);
- canvas.setBitmap(b);
+ Canvas canvas = new Canvas(b);
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.translate(blurSizeOutline / 2, blurSizeOutline / 2);
canvas.scale(((float) size) / bounds.width(), ((float) size) / bounds.height(), 0, 0);
diff --git a/src/com/android/launcher3/testing/DummyWidget.java b/src/com/android/launcher3/testing/DummyWidget.java
deleted file mode 100644
index df887ac1f..000000000
--- a/src/com/android/launcher3/testing/DummyWidget.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.android.launcher3.testing;
-
-import android.appwidget.AppWidgetProviderInfo;
-
-import com.android.launcher3.CustomAppWidget;
-import com.android.launcher3.R;
-
-public class DummyWidget implements CustomAppWidget {
- @Override
- public String getLabel() {
- return "Dumb Launcher Widget";
- }
-
- @Override
- public int getPreviewImage() {
- return 0;
- }
-
- @Override
- public int getIcon() {
- return 0;
- }
-
- @Override
- public int getWidgetLayout() {
- return R.layout.zzz_dummy_widget;
- }
-
- @Override
- public int getSpanX() {
- return 2;
- }
-
- @Override
- public int getSpanY() {
- return 2;
- }
-
- @Override
- public int getMinSpanX() {
- return 1;
- }
-
- @Override
- public int getMinSpanY() {
- return 1;
- }
-
- @Override
- public int getResizeMode() {
- return AppWidgetProviderInfo.RESIZE_BOTH;
- }
-}
diff --git a/src/com/android/launcher3/testing/LauncherExtension.java b/src/com/android/launcher3/testing/LauncherExtension.java
index 355963bfe..a1a4d7555 100644
--- a/src/com/android/launcher3/testing/LauncherExtension.java
+++ b/src/com/android/launcher3/testing/LauncherExtension.java
@@ -7,13 +7,10 @@ import android.view.Menu;
import com.android.launcher3.AppInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherCallbacks;
-import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.ComponentKeyMapper;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.List;
/**
* This class represents a very trivial LauncherExtension. It primarily serves as a simple
@@ -150,12 +147,6 @@ public class LauncherExtension extends Launcher {
}
@Override
- public List<ComponentKeyMapper<AppInfo>> getPredictedApps() {
- // To debug app predictions, enable AlphabeticalAppsList#DEBUG_PREDICTIONS
- return new ArrayList<>();
- }
-
- @Override
public void onAttachedToWindow() {
}
diff --git a/src/com/android/launcher3/util/ManagedProfileHeuristic.java b/src/com/android/launcher3/util/ManagedProfileHeuristic.java
index 091dd84bc..009aee775 100644
--- a/src/com/android/launcher3/util/ManagedProfileHeuristic.java
+++ b/src/com/android/launcher3/util/ManagedProfileHeuristic.java
@@ -67,7 +67,7 @@ public class ManagedProfileHeuristic {
return;
}
- if (Utilities.isAtLeastO() && !SessionCommitReceiver.isEnabled(context)) {
+ if (Utilities.ATLEAST_OREO && !SessionCommitReceiver.isEnabled(context)) {
// Just mark the folder id preference to avoid new folder creation later.
ufi.prefs.edit().putLong(ufi.folderIdKey, ItemInfo.NO_ID).apply();
return;
diff --git a/src/com/android/launcher3/util/SystemUiController.java b/src/com/android/launcher3/util/SystemUiController.java
index d7a2625e9..edbf05a7c 100644
--- a/src/com/android/launcher3/util/SystemUiController.java
+++ b/src/com/android/launcher3/util/SystemUiController.java
@@ -59,7 +59,7 @@ public class SystemUiController {
// Apply the state flags in priority order
int newFlags = oldFlags;
for (int stateFlag : mStates) {
- if (Utilities.isAtLeastO()) {
+ if (Utilities.ATLEAST_OREO) {
if ((stateFlag & FLAG_LIGHT_NAV) != 0) {
newFlags |= View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
} else if ((stateFlag & FLAG_DARK_NAV) != 0) {
diff --git a/src/com/android/launcher3/util/TestingUtils.java b/src/com/android/launcher3/util/TestingUtils.java
index a7cc42b5f..d927dc335 100644
--- a/src/com/android/launcher3/util/TestingUtils.java
+++ b/src/com/android/launcher3/util/TestingUtils.java
@@ -3,18 +3,14 @@ package com.android.launcher3.util;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.FrameLayout;
-import com.android.launcher3.CustomAppWidget;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import java.util.HashMap;
-
public class TestingUtils {
public static final String MEMORY_TRACKER = "com.android.launcher3.testing.MemoryTracker";
@@ -23,9 +19,6 @@ public class TestingUtils {
public static final boolean MEMORY_DUMP_ENABLED = false;
public static final String SHOW_WEIGHT_WATCHER = "debug.show_mem";
- public static final boolean ENABLE_CUSTOM_WIDGET_TEST = false;
- public static final String DUMMY_WIDGET = "com.android.launcher3.testing.DummyWidget";
-
public static void startTrackingMemory(Context context) {
if (MEMORY_DUMP_ENABLED) {
context.startService(new Intent()
@@ -55,16 +48,4 @@ public class TestingUtils {
launcher.mWeightWatcher = watcher;
}
}
-
- public static void addDummyWidget(HashMap<String, CustomAppWidget> set) {
- if (ENABLE_CUSTOM_WIDGET_TEST) {
- try {
- Class<?> clazz = Class.forName(DUMMY_WIDGET);
- CustomAppWidget widget = (CustomAppWidget) clazz.newInstance();
- set.put(widget.getClass().getName(), widget);
- } catch (Exception e) {
- Log.e("TestingUtils", "Error adding dummy widget", e);
- }
- }
- }
}
diff --git a/src/com/android/launcher3/util/TraceHelper.java b/src/com/android/launcher3/util/TraceHelper.java
new file mode 100644
index 000000000..5b66fcda6
--- /dev/null
+++ b/src/com/android/launcher3/util/TraceHelper.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util;
+
+import android.os.SystemClock;
+import android.os.Trace;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.MutableLong;
+
+import com.android.launcher3.config.FeatureFlags;
+
+/**
+ * A wrapper around {@link Trace} to allow easier proguarding for production builds.
+ *
+ * To enable any tracing log, execute the following command:
+ * $ adb shell setprop log.tag.TAGNAME VERBOSE
+ */
+public class TraceHelper {
+
+ private static final boolean ENABLED = FeatureFlags.IS_DOGFOOD_BUILD;
+
+ private static final boolean SYSTEM_TRACE = true;
+ private static final ArrayMap<String, MutableLong> sUpTimes =
+ ENABLED ? new ArrayMap<String, MutableLong>() : null;
+
+ public static void beginSection(String sectionName) {
+ if (ENABLED) {
+ MutableLong time = sUpTimes.get(sectionName);
+ if (time == null) {
+ time = new MutableLong(Log.isLoggable(sectionName, Log.VERBOSE) ? 0 : -1);
+ sUpTimes.put(sectionName, time);
+ }
+ if (time.value >= 0) {
+ if (SYSTEM_TRACE) {
+ Trace.beginSection(sectionName);
+ }
+ time.value = SystemClock.uptimeMillis();
+ }
+ }
+ }
+
+ public static void partitionSection(String sectionName, String partition) {
+ if (ENABLED) {
+ MutableLong time = sUpTimes.get(sectionName);
+ if (time.value >= 0) {
+
+ if (SYSTEM_TRACE) {
+ Trace.endSection();
+ Trace.beginSection(sectionName);
+ }
+
+ long now = SystemClock.uptimeMillis();
+ Log.d(sectionName, partition + " : " + (now - time.value));
+ time.value = now;
+ }
+ }
+ }
+
+ public static void endSection(String sectionName) {
+ if (ENABLED) {
+ endSection(sectionName, "End");
+ }
+ }
+
+ public static void endSection(String sectionName, String msg) {
+ if (ENABLED) {
+ MutableLong time = sUpTimes.get(sectionName);
+ if (time.value >= 0) {
+ if (SYSTEM_TRACE) {
+ Trace.endSection();
+ }
+ Log.d(sectionName, msg + " : " + (SystemClock.uptimeMillis() - time.value));
+ }
+ }
+ }
+}
diff --git a/src/com/android/launcher3/util/UiThreadHelper.java b/src/com/android/launcher3/util/UiThreadHelper.java
new file mode 100644
index 000000000..27140a113
--- /dev/null
+++ b/src/com/android/launcher3/util/UiThreadHelper.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.util;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
+import android.view.inputmethod.InputMethodManager;
+
+/**
+ * Utility class for offloading some class from UI thread
+ */
+public class UiThreadHelper {
+
+ private static HandlerThread sHandlerThread;
+ private static Handler sHandler;
+
+ private static final int MSG_HIDE_KEYBOARD = 1;
+
+ public static Looper getBackgroundLooper() {
+ if (sHandlerThread == null) {
+ sHandlerThread =
+ new HandlerThread("UiThreadHelper", Process.THREAD_PRIORITY_FOREGROUND);
+ sHandlerThread.start();
+ }
+ return sHandlerThread.getLooper();
+ }
+
+ private static Handler getHandler(Context context) {
+ if (sHandler == null) {
+ sHandler = new Handler(getBackgroundLooper(),
+ new UiCallbacks(context.getApplicationContext()));
+ }
+ return sHandler;
+ }
+
+ public static void hideKeyboardAsync(Context context, IBinder token) {
+ Message.obtain(getHandler(context), MSG_HIDE_KEYBOARD, token).sendToTarget();
+ }
+
+ private static class UiCallbacks implements Handler.Callback {
+
+ private final InputMethodManager mIMM;
+
+ UiCallbacks(Context context) {
+ mIMM = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+ }
+
+ @Override
+ public boolean handleMessage(Message message) {
+ switch (message.what) {
+ case MSG_HIDE_KEYBOARD:
+ mIMM.hideSoftInputFromWindow((IBinder) message.obj, 0);
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java b/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java
index f99efcec9..ec494f181 100644
--- a/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java
+++ b/src/com/android/launcher3/util/WallpaperOffsetInterpolator.java
@@ -1,9 +1,15 @@
package com.android.launcher3.util;
import android.app.WallpaperManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Message;
+import android.os.SystemClock;
import android.util.Log;
-import android.view.Choreographer;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
@@ -13,60 +19,30 @@ import com.android.launcher3.Workspace;
/**
* Utility class to handle wallpaper scrolling along with workspace.
*/
-public class WallpaperOffsetInterpolator implements Choreographer.FrameCallback {
+public class WallpaperOffsetInterpolator extends BroadcastReceiver {
+
+ private static final int[] sTempInt = new int[2];
private static final String TAG = "WPOffsetInterpolator";
private static final int ANIMATION_DURATION = 250;
// Don't use all the wallpaper for parallax until you have at least this many pages
private static final int MIN_PARALLAX_PAGE_SPAN = 4;
- private final Choreographer mChoreographer;
- private final Interpolator mInterpolator;
- private final WallpaperManager mWallpaperManager;
private final Workspace mWorkspace;
private final boolean mIsRtl;
+ private final Handler mHandler;
+ private boolean mRegistered = false;
private IBinder mWindowToken;
private boolean mWallpaperIsLiveWallpaper;
- private float mLastSetWallpaperOffsetSteps = 0;
- private float mFinalOffset = 0.0f;
- private float mCurrentOffset = 0.5f; // to force an initial update
- private boolean mWaitingForUpdate;
private boolean mLockedToDefaultPage;
-
- private boolean mAnimating;
- private long mAnimationStartTime;
- private float mAnimationStartOffset;
- int mNumScreens;
- int mNumPagesForWallpaperParallax;
+ private int mNumScreens;
public WallpaperOffsetInterpolator(Workspace workspace) {
- mChoreographer = Choreographer.getInstance();
- mInterpolator = new DecelerateInterpolator(1.5f);
-
mWorkspace = workspace;
- mWallpaperManager = WallpaperManager.getInstance(workspace.getContext());
mIsRtl = Utilities.isRtl(workspace.getResources());
- }
-
- @Override
- public void doFrame(long frameTimeNanos) {
- updateOffset(false);
- }
-
- private void updateOffset(boolean force) {
- if (mWaitingForUpdate || force) {
- mWaitingForUpdate = false;
- if (computeScrollOffset() && mWindowToken != null) {
- try {
- mWallpaperManager.setWallpaperOffsets(mWindowToken, getCurrX(), 0.5f);
- setWallpaperOffsetSteps();
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Error updating wallpaper offset: " + e);
- }
- }
- }
+ mHandler = new OffsetHandler(workspace.getContext());
}
/**
@@ -80,46 +56,25 @@ public class WallpaperOffsetInterpolator implements Choreographer.FrameCallback
return mLockedToDefaultPage;
}
- public boolean computeScrollOffset() {
- final float oldOffset = mCurrentOffset;
- if (mAnimating) {
- long durationSinceAnimation = System.currentTimeMillis() - mAnimationStartTime;
- float t0 = durationSinceAnimation / (float) ANIMATION_DURATION;
- float t1 = mInterpolator.getInterpolation(t0);
- mCurrentOffset = mAnimationStartOffset +
- (mFinalOffset - mAnimationStartOffset) * t1;
- mAnimating = durationSinceAnimation < ANIMATION_DURATION;
- } else {
- mCurrentOffset = mFinalOffset;
- }
-
- if (Math.abs(mCurrentOffset - mFinalOffset) > 0.0000001f) {
- scheduleUpdate();
- }
- if (Math.abs(oldOffset - mCurrentOffset) > 0.0000001f) {
- return true;
- }
- return false;
- }
-
/**
+ * Computes the wallpaper offset as an int ratio (out[0] / out[1])
+ *
* TODO: do different behavior if it's a live wallpaper?
*/
- public float wallpaperOffsetForScroll(int scroll) {
+ private void wallpaperOffsetForScroll(int scroll, int numScrollingPages, final int[] out) {
+ out[1] = 1;
+
// To match the default wallpaper behavior in the system, we default to either the left
// or right edge on initialization
- int numScrollingPages = getNumScreensExcludingEmpty();
if (mLockedToDefaultPage || numScrollingPages <= 1) {
- return mIsRtl ? 1f : 0f;
+ out[0] = mIsRtl ? 1 : 0;
+ return;
}
// Distribute the wallpaper parallax over a minimum of MIN_PARALLAX_PAGE_SPAN workspace
// screens, not including the custom screen, and empty screens (if > MIN_PARALLAX_PAGE_SPAN)
- if (mWallpaperIsLiveWallpaper) {
- mNumPagesForWallpaperParallax = numScrollingPages;
- } else {
- mNumPagesForWallpaperParallax = Math.max(MIN_PARALLAX_PAGE_SPAN, numScrollingPages);
- }
+ int numPagesForWallpaperParallax = mWallpaperIsLiveWallpaper ? numScrollingPages :
+ Math.max(MIN_PARALLAX_PAGE_SPAN, numScrollingPages);
// Offset by the custom screen
int leftPageIndex;
@@ -136,106 +91,184 @@ public class WallpaperOffsetInterpolator implements Choreographer.FrameCallback
int leftPageScrollX = mWorkspace.getScrollForPage(leftPageIndex);
int rightPageScrollX = mWorkspace.getScrollForPage(rightPageIndex);
int scrollRange = rightPageScrollX - leftPageScrollX;
- if (scrollRange == 0) {
- return 0f;
+ if (scrollRange <= 0) {
+ out[0] = 0;
+ return;
}
// Sometimes the left parameter of the pages is animated during a layout transition;
// this parameter offsets it to keep the wallpaper from animating as well
int adjustedScroll = scroll - leftPageScrollX -
mWorkspace.getLayoutTransitionOffsetForPage(0);
- float offset = Utilities.boundToRange((float) adjustedScroll / scrollRange, 0f, 1f);
+ adjustedScroll = Utilities.boundToRange(adjustedScroll, 0, scrollRange);
+ out[1] = (numPagesForWallpaperParallax - 1) * scrollRange;
// The offset is now distributed 0..1 between the left and right pages that we care about,
// so we just map that between the pages that we are using for parallax
- float rtlOffset = 0;
+ int rtlOffset = 0;
if (mIsRtl) {
// In RTL, the pages are right aligned, so adjust the offset from the end
- rtlOffset = (float) ((mNumPagesForWallpaperParallax - 1) - (numScrollingPages - 1)) /
- (mNumPagesForWallpaperParallax - 1);
+ rtlOffset = out[1] - (numScrollingPages - 1) * scrollRange;
}
- return rtlOffset + offset *
- ((float) (numScrollingPages - 1) / (mNumPagesForWallpaperParallax - 1));
+ out[0] = rtlOffset + adjustedScroll * (numScrollingPages - 1);
}
- private float wallpaperOffsetForCurrentScroll() {
- return wallpaperOffsetForScroll(mWorkspace.getScrollX());
+ public float wallpaperOffsetForScroll(int scroll) {
+ wallpaperOffsetForScroll(scroll, getNumScreensExcludingEmpty(), sTempInt);
+ return ((float) sTempInt[0]) / sTempInt[1];
}
- private int numEmptyScreensToIgnore() {
+ private int getNumScreensExcludingEmpty() {
int numScrollingPages = mWorkspace.getChildCount();
if (numScrollingPages >= MIN_PARALLAX_PAGE_SPAN && mWorkspace.hasExtraEmptyScreen()) {
- return 1;
+ return numScrollingPages - 1;
} else {
- return 0;
+ return numScrollingPages;
}
}
- private int getNumScreensExcludingEmpty() {
- return mWorkspace.getChildCount() - numEmptyScreensToIgnore();
- }
-
public void syncWithScroll() {
- float offset = wallpaperOffsetForCurrentScroll();
- setFinalX(offset);
- updateOffset(true);
- }
-
- public float getCurrX() {
- return mCurrentOffset;
+ int numScreens = getNumScreensExcludingEmpty();
+ wallpaperOffsetForScroll(mWorkspace.getScrollX(), numScreens, sTempInt);
+ Message msg = Message.obtain(mHandler, MSG_UPDATE_OFFSET, sTempInt[0], sTempInt[1],
+ mWindowToken);
+ if (numScreens != mNumScreens) {
+ if (mNumScreens > 0) {
+ // Don't animate if we're going from 0 screens
+ msg.what = MSG_START_ANIMATION;
+ }
+ mNumScreens = numScreens;
+ updateOffset();
+ }
+ msg.sendToTarget();
}
- public float getFinalX() {
- return mFinalOffset;
+ private void updateOffset() {
+ int numPagesForWallpaperParallax;
+ if (mWallpaperIsLiveWallpaper) {
+ numPagesForWallpaperParallax = mNumScreens;
+ } else {
+ numPagesForWallpaperParallax = Math.max(MIN_PARALLAX_PAGE_SPAN, mNumScreens);
+ }
+ Message.obtain(mHandler, MSG_SET_NUM_PARALLAX, numPagesForWallpaperParallax, 0,
+ mWindowToken).sendToTarget();
}
- private void animateToFinal() {
- mAnimating = true;
- mAnimationStartOffset = mCurrentOffset;
- mAnimationStartTime = System.currentTimeMillis();
+ public void jumpToFinal() {
+ Message.obtain(mHandler, MSG_JUMP_TO_FINAL, mWindowToken).sendToTarget();
}
- private void setWallpaperOffsetSteps() {
- // Set wallpaper offset steps (1 / (number of screens - 1))
- float xOffset = 1.0f / (mNumPagesForWallpaperParallax - 1);
- if (xOffset != mLastSetWallpaperOffsetSteps) {
- mWallpaperManager.setWallpaperOffsetSteps(xOffset, 1.0f);
- mLastSetWallpaperOffsetSteps = xOffset;
+ public void setWindowToken(IBinder token) {
+ mWindowToken = token;
+ if (mWindowToken == null && mRegistered) {
+ mWorkspace.getContext().unregisterReceiver(this);
+ mRegistered = false;
+ } else if (mWindowToken != null && !mRegistered) {
+ mWorkspace.getContext()
+ .registerReceiver(this, new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED));
+ onReceive(mWorkspace.getContext(), null);
+ mRegistered = true;
}
}
- public void setFinalX(float x) {
- scheduleUpdate();
- mFinalOffset = Math.max(0f, Math.min(x, 1f));
- if (getNumScreensExcludingEmpty() != mNumScreens) {
- if (mNumScreens > 0 && Float.compare(mCurrentOffset, mFinalOffset) != 0) {
- // Don't animate if we're going from 0 screens, or if the final offset is the same
- // as the current offset
- animateToFinal();
- }
- mNumScreens = getNumScreensExcludingEmpty();
- }
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mWallpaperIsLiveWallpaper =
+ WallpaperManager.getInstance(mWorkspace.getContext()).getWallpaperInfo() != null;
+ updateOffset();
}
- private void scheduleUpdate() {
- if (!mWaitingForUpdate) {
- mChoreographer.postFrameCallback(this);
- mWaitingForUpdate = true;
+ private static final int MSG_START_ANIMATION = 1;
+ private static final int MSG_UPDATE_OFFSET = 2;
+ private static final int MSG_APPLY_OFFSET = 3;
+ private static final int MSG_SET_NUM_PARALLAX = 4;
+ private static final int MSG_JUMP_TO_FINAL = 5;
+
+ private static class OffsetHandler extends Handler {
+
+ private final Interpolator mInterpolator;
+ private final WallpaperManager mWM;
+
+ private float mCurrentOffset = 0.5f; // to force an initial update
+ private boolean mAnimating;
+ private long mAnimationStartTime;
+ private float mAnimationStartOffset;
+
+ private float mFinalOffset;
+ private float mOffsetX;
+
+ public OffsetHandler(Context context) {
+ super(UiThreadHelper.getBackgroundLooper());
+ mInterpolator = new DecelerateInterpolator(1.5f);
+ mWM = WallpaperManager.getInstance(context);
}
- }
- public void jumpToFinal() {
- mCurrentOffset = mFinalOffset;
- }
+ @Override
+ public void handleMessage(Message msg) {
+ final IBinder token = (IBinder) msg.obj;
+ if (token == null) {
+ return;
+ }
- public void onResume() {
- mWallpaperIsLiveWallpaper = mWallpaperManager.getWallpaperInfo() != null;
- // Force the wallpaper offset steps to be set again, because another app might have changed
- // them
- mLastSetWallpaperOffsetSteps = 0f;
- }
+ switch (msg.what) {
+ case MSG_START_ANIMATION: {
+ mAnimating = true;
+ mAnimationStartOffset = mCurrentOffset;
+ mAnimationStartTime = msg.getWhen();
+ // Follow through
+ }
+ case MSG_UPDATE_OFFSET:
+ mFinalOffset = ((float) msg.arg1) / msg.arg2;
+ // Follow through
+ case MSG_APPLY_OFFSET: {
+ float oldOffset = mCurrentOffset;
+ if (mAnimating) {
+ long durationSinceAnimation = SystemClock.uptimeMillis()
+ - mAnimationStartTime;
+ float t0 = durationSinceAnimation / (float) ANIMATION_DURATION;
+ float t1 = mInterpolator.getInterpolation(t0);
+ mCurrentOffset = mAnimationStartOffset +
+ (mFinalOffset - mAnimationStartOffset) * t1;
+ mAnimating = durationSinceAnimation < ANIMATION_DURATION;
+ } else {
+ mCurrentOffset = mFinalOffset;
+ }
+
+ if (Float.compare(mCurrentOffset, oldOffset) != 0) {
+ setOffsetSafely(token);
+ // Force the wallpaper offset steps to be set again, because another app
+ // might have changed them
+ mWM.setWallpaperOffsetSteps(mOffsetX, 1.0f);
+ }
+ if (mAnimating) {
+ // If we are animating, keep updating the offset
+ Message.obtain(this, MSG_APPLY_OFFSET, token).sendToTarget();
+ }
+ return;
+ }
+ case MSG_SET_NUM_PARALLAX: {
+ // Set wallpaper offset steps (1 / (number of screens - 1))
+ mOffsetX = 1.0f / (msg.arg1 - 1);
+ mWM.setWallpaperOffsetSteps(mOffsetX, 1.0f);
+ return;
+ }
+ case MSG_JUMP_TO_FINAL: {
+ if (Float.compare(mCurrentOffset, mFinalOffset) != 0) {
+ mCurrentOffset = mFinalOffset;
+ setOffsetSafely(token);
+ }
+ mAnimating = false;
+ return;
+ }
+ }
+ }
- public void setWindowToken(IBinder token) {
- mWindowToken = token;
+ private void setOffsetSafely(IBinder token) {
+ try {
+ mWM.setWallpaperOffsets(token, mCurrentOffset, 0.5f);
+ } catch (IllegalArgumentException e) {
+ Log.e(TAG, "Error updating wallpaper offset: " + e);
+ }
+ }
}
} \ No newline at end of file
diff --git a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
index ad05ce917..bc404842e 100644
--- a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
+++ b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java
@@ -35,13 +35,13 @@ public class PendingAddWidgetInfo extends PendingAddItemInfo {
public Bundle bindOptions = null;
public PendingAddWidgetInfo(LauncherAppWidgetProviderInfo i) {
- if (i.isCustomWidget) {
+ if (i.isCustomWidget()) {
itemType = LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
} else {
itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
}
this.info = i;
- user = i.getUser();
+ user = i.getProfile();
componentName = i.provider;
previewImage = i.previewImage;
icon = i.icon;
diff --git a/src/com/android/launcher3/widget/PendingItemDragHelper.java b/src/com/android/launcher3/widget/PendingItemDragHelper.java
index 19be28d83..c5cf5e23a 100644
--- a/src/com/android/launcher3/widget/PendingItemDragHelper.java
+++ b/src/com/android/launcher3/widget/PendingItemDragHelper.java
@@ -22,7 +22,6 @@ import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import android.view.View;
import android.widget.RemoteViews;
@@ -32,11 +31,9 @@ import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.PendingAddItemInfo;
import com.android.launcher3.R;
-import com.android.launcher3.Workspace;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.dragndrop.LivePreviewWidgetCell;
import com.android.launcher3.graphics.DragPreviewProvider;
-import com.android.launcher3.graphics.HolographicOutlineHelper;
import com.android.launcher3.graphics.LauncherIcons;
/**
@@ -48,8 +45,8 @@ public class PendingItemDragHelper extends DragPreviewProvider {
private static final float MAX_WIDGET_SCALE = 1.25f;
private final PendingAddItemInfo mAddInfo;
+ private int[] mEstimatedCellSize;
- private Bitmap mPreviewBitmap;
private RemoteViews mPreview;
public PendingItemDragHelper(View view) {
@@ -80,12 +77,12 @@ public class PendingItemDragHelper extends DragPreviewProvider {
final Point dragOffset;
final Rect dragRegion;
+ mEstimatedCellSize = launcher.getWorkspace().estimateItemSize(mAddInfo);
if (mAddInfo instanceof PendingAddWidgetInfo) {
PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) mAddInfo;
- int[] size = launcher.getWorkspace().estimateItemSize(createWidgetInfo, true, false);
- int maxWidth = Math.min((int) (previewBitmapWidth * MAX_WIDGET_SCALE), size[0]);
+ int maxWidth = Math.min((int) (previewBitmapWidth * MAX_WIDGET_SCALE), mEstimatedCellSize[0]);
int[] previewSizeBeforeScale = new int[1];
@@ -117,14 +114,12 @@ public class PendingItemDragHelper extends DragPreviewProvider {
PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) mAddInfo;
Drawable icon = createShortcutInfo.activityInfo.getFullResIcon(app.getIconCache());
preview = LauncherIcons.createScaledBitmapWithoutShadow(icon, launcher, 0);
- mAddInfo.spanX = mAddInfo.spanY = 1;
scale = ((float) launcher.getDeviceProfile().iconSizePx) / preview.getWidth();
dragOffset = new Point(previewPadding / 2, previewPadding / 2);
// Create a preview same as the workspace cell size and draw the icon at the
// appropriate position.
- int[] size = launcher.getWorkspace().estimateItemSize(mAddInfo, false, true);
DeviceProfile dp = launcher.getDeviceProfile();
int iconSize = dp.iconSizePx;
@@ -134,9 +129,10 @@ public class PendingItemDragHelper extends DragPreviewProvider {
previewBounds.top += padding;
dragRegion = new Rect();
- dragRegion.left = (size[0] - iconSize) / 2;
+ dragRegion.left = (mEstimatedCellSize[0] - iconSize) / 2;
dragRegion.right = dragRegion.left + iconSize;
- dragRegion.top = (size[1] - iconSize - dp.iconTextSizePx - dp.iconDrawablePaddingPx) / 2;
+ dragRegion.top = (mEstimatedCellSize[1]
+ - iconSize - dp.iconTextSizePx - dp.iconDrawablePaddingPx) / 2;
dragRegion.bottom = dragRegion.top + iconSize;
}
@@ -149,60 +145,31 @@ public class PendingItemDragHelper extends DragPreviewProvider {
int dragLayerY = screenPos.y + previewBounds.top
+ (int) ((scale * preview.getHeight() - preview.getHeight()) / 2);
- mPreviewBitmap = preview;
// Start the drag
launcher.getDragController().startDrag(preview, dragLayerX, dragLayerY, source, mAddInfo,
dragOffset, dragRegion, scale, options);
}
-
@Override
- public Bitmap createDragOutline(Canvas canvas) {
- if (mAddInfo instanceof PendingAddShortcutInfo) {
- int width = mPreviewBitmap.getWidth();
- int height = mPreviewBitmap.getHeight();
- Bitmap b = Bitmap.createBitmap(width + blurSizeOutline, height + blurSizeOutline,
- Bitmap.Config.ALPHA_8);
- canvas.setBitmap(b);
-
- Launcher launcher = Launcher.getLauncher(mView.getContext());
- int size = launcher.getDeviceProfile().iconSizePx;
-
- Rect src = new Rect(0, 0, mPreviewBitmap.getWidth(), mPreviewBitmap.getHeight());
- Rect dst = new Rect(0, 0, size, size);
- dst.offset(blurSizeOutline / 2, blurSizeOutline / 2);
- canvas.drawBitmap(mPreviewBitmap, src, dst, new Paint(Paint.FILTER_BITMAP_FLAG));
-
- HolographicOutlineHelper.getInstance(mView.getContext())
- .applyExpensiveOutlineWithBlur(b, canvas);
-
- canvas.setBitmap(null);
- return b;
+ protected Bitmap convertPreviewToAlphaBitmap(Bitmap preview) {
+ if (mAddInfo instanceof PendingAddShortcutInfo || mEstimatedCellSize == null) {
+ return super.convertPreviewToAlphaBitmap(preview);
}
- Workspace workspace = Launcher.getLauncher(mView.getContext()).getWorkspace();
- int[] size = workspace.estimateItemSize(mAddInfo, false, false);
-
- int w = size[0];
- int h = size[1];
+ int w = mEstimatedCellSize[0];
+ int h = mEstimatedCellSize[1];
final Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ALPHA_8);
- canvas.setBitmap(b);
+ Rect src = new Rect(0, 0, preview.getWidth(), preview.getHeight());
- Rect src = new Rect(0, 0, mPreviewBitmap.getWidth(), mPreviewBitmap.getHeight());
- float scaleFactor = Math.min((w - blurSizeOutline) / (float) mPreviewBitmap.getWidth(),
- (h - blurSizeOutline) / (float) mPreviewBitmap.getHeight());
- int scaledWidth = (int) (scaleFactor * mPreviewBitmap.getWidth());
- int scaledHeight = (int) (scaleFactor * mPreviewBitmap.getHeight());
+ float scaleFactor = Math.min((w - blurSizeOutline) / (float) preview.getWidth(),
+ (h - blurSizeOutline) / (float) preview.getHeight());
+ int scaledWidth = (int) (scaleFactor * preview.getWidth());
+ int scaledHeight = (int) (scaleFactor * preview.getHeight());
Rect dst = new Rect(0, 0, scaledWidth, scaledHeight);
// center the image
dst.offset((w - scaledWidth) / 2, (h - scaledHeight) / 2);
-
- canvas.drawBitmap(mPreviewBitmap, src, dst, null);
- HolographicOutlineHelper.getInstance(mView.getContext())
- .applyExpensiveOutlineWithBlur(b, canvas);
- canvas.setBitmap(null);
-
+ new Canvas(b).drawBitmap(preview, src, dst, new Paint(Paint.FILTER_BITMAP_FLAG));
return b;
}
}
diff --git a/src/com/android/launcher3/widget/WidgetHostViewLoader.java b/src/com/android/launcher3/widget/WidgetHostViewLoader.java
index 5eeea44b8..8dcdd4465 100644
--- a/src/com/android/launcher3/widget/WidgetHostViewLoader.java
+++ b/src/com/android/launcher3/widget/WidgetHostViewLoader.java
@@ -85,7 +85,7 @@ public class WidgetHostViewLoader implements DragController.DragListener {
private boolean preloadWidget() {
final LauncherAppWidgetProviderInfo pInfo = mInfo.info;
- if (pInfo.isCustomWidget) {
+ if (pInfo.isCustomWidget()) {
return false;
}
final Bundle options = getDefaultOptionsForWidget(mLauncher, mInfo);
@@ -129,7 +129,7 @@ public class WidgetHostViewLoader implements DragController.DragListener {
mWidgetLoadingId = -1;
hostView.setVisibility(View.INVISIBLE);
- int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(mInfo, false, true);
+ int[] unScaledSize = mLauncher.getWorkspace().estimateItemSize(mInfo);
// We want the first widget layout to be the correct size. This will be important
// for width size reporting to the AppWidgetManager.
DragLayer.LayoutParams lp = new DragLayer.LayoutParams(unScaledSize[0],
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index 01101ac74..7aa50a445 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -40,24 +40,23 @@ import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
-import com.android.launcher3.touch.SwipeDetector;
import com.android.launcher3.anim.PropertyListBuilder;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.graphics.GradientView;
import com.android.launcher3.model.WidgetItem;
-import com.android.launcher3.userevent.nano.LauncherLogProto;
+import com.android.launcher3.touch.SwipeDetector;
+import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.SystemUiController;
import com.android.launcher3.util.Themes;
-import com.android.launcher3.util.TouchController;
import java.util.List;
/**
* Bottom sheet for the "Widgets" system shortcut in the long-press popup.
*/
-public class WidgetsBottomSheet extends AbstractFloatingView implements Insettable, TouchController,
+public class WidgetsBottomSheet extends AbstractFloatingView implements Insettable,
SwipeDetector.Listener, View.OnClickListener, View.OnLongClickListener,
DragController.DragListener {
@@ -108,7 +107,6 @@ public class WidgetsBottomSheet extends AbstractFloatingView implements Insettab
onWidgetsBound();
mLauncher.getDragLayer().addView(mGradientBackground);
- mGradientBackground.setVisibility(VISIBLE);
mLauncher.getDragLayer().addView(this);
measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
setTranslationY(mTranslationYClosed);
@@ -242,18 +240,6 @@ public class WidgetsBottomSheet extends AbstractFloatingView implements Insettab
}
@Override
- public int getLogContainerType() {
- return LauncherLogProto.ContainerType.WIDGETS; // TODO: be more specific
- }
-
- /**
- * Returns a {@link WidgetsBottomSheet} which is already open or null
- */
- public static WidgetsBottomSheet getOpen(Launcher launcher) {
- return getOpenView(launcher, TYPE_WIDGETS_BOTTOM_SHEET);
- }
-
- @Override
public void setInsets(Rect insets) {
// Extend behind left, right, and bottom insets.
int leftInset = insets.left - mInsets.left;
@@ -302,12 +288,27 @@ public class WidgetsBottomSheet extends AbstractFloatingView implements Insettab
}
@Override
+ public void logActionCommand(int command) {
+ // TODO: be more specific
+ mLauncher.getUserEventDispatcher().logActionCommand(command, ContainerType.WIDGETS);
+ }
+
+ @Override
public boolean onControllerTouchEvent(MotionEvent ev) {
return mSwipeDetector.onTouchEvent(ev);
}
@Override
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_UP) {
+ // If we got ACTION_UP without ever returning true on intercept,
+ // the user never started dragging the bottom sheet.
+ if (!mLauncher.getDragLayer().isEventOverView(this, ev)) {
+ close(true);
+ return false;
+ }
+ }
+
int directionsToDetectScroll = mSwipeDetector.isIdleState() ?
SwipeDetector.DIRECTION_NEGATIVE : 0;
mSwipeDetector.setDetectableScrollConditions(
diff --git a/src/com/android/launcher3/widget/WidgetsContainerView.java b/src/com/android/launcher3/widget/WidgetsContainerView.java
index acec3dd3b..39dd0d498 100644
--- a/src/com/android/launcher3/widget/WidgetsContainerView.java
+++ b/src/com/android/launcher3/widget/WidgetsContainerView.java
@@ -197,25 +197,6 @@ public class WidgetsContainerView extends BaseContainerView
//
@Override
- public boolean supportsAppInfoDropTarget() {
- return true;
- }
-
- /*
- * Both this method and {@link #supportsFlingToDelete} has to return {@code false} for the
- * {@link DeleteDropTarget} to be invisible.)
- */
- @Override
- public boolean supportsDeleteDropTarget() {
- return false;
- }
-
- @Override
- public float getIntrinsicIconScaleFactor() {
- return 0;
- }
-
- @Override
public void onDropCompleted(View target, DragObject d, boolean isFlingToDelete,
boolean success) {
if (LOGD) {
diff --git a/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java b/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java
new file mode 100644
index 000000000..1086987f8
--- /dev/null
+++ b/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.widget.custom;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.Utilities;
+
+/**
+ * Custom app widget provider info that can be used as a widget, but provide extra functionality
+ * by allowing custom code and views.
+ */
+public class CustomAppWidgetProviderInfo extends LauncherAppWidgetProviderInfo
+ implements Parcelable {
+
+ public final int providerId;
+
+ protected CustomAppWidgetProviderInfo(Parcel parcel, boolean readSelf, int providerId) {
+ super(parcel);
+ if (readSelf) {
+ this.providerId = parcel.readInt();
+
+ provider = new ComponentName(parcel.readString(), CLS_CUSTOM_WIDGET_PREFIX + providerId);
+
+ label = parcel.readString();
+ initialLayout = parcel.readInt();
+ icon = parcel.readInt();
+ previewImage = parcel.readInt();
+
+ resizeMode = parcel.readInt();
+ spanX = parcel.readInt();
+ spanY = parcel.readInt();
+ minSpanX = parcel.readInt();
+ minSpanY = parcel.readInt();
+ } else {
+ this.providerId = providerId;
+ }
+ }
+
+ @Override
+ public void initSpans(Context context) { }
+
+ @Override
+ public String getLabel(PackageManager packageManager) {
+ return Utilities.trim(label);
+ }
+
+ @Override
+ public String toString() {
+ return "WidgetProviderInfo(" + provider + ")";
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ super.writeToParcel(out, flags);
+ out.writeInt(providerId);
+ out.writeString(provider.getPackageName());
+
+ out.writeString(label);
+ out.writeInt(initialLayout);
+ out.writeInt(icon);
+ out.writeInt(previewImage);
+
+ out.writeInt(resizeMode);
+ out.writeInt(spanX);
+ out.writeInt(spanY);
+ out.writeInt(minSpanX);
+ out.writeInt(minSpanY);
+ }
+
+ public static final Parcelable.Creator<CustomAppWidgetProviderInfo> CREATOR
+ = new Parcelable.Creator<CustomAppWidgetProviderInfo>() {
+
+ @Override
+ public CustomAppWidgetProviderInfo createFromParcel(Parcel parcel) {
+ return new CustomAppWidgetProviderInfo(parcel, true, 0);
+ }
+
+ @Override
+ public CustomAppWidgetProviderInfo[] newArray(int size) {
+ return new CustomAppWidgetProviderInfo[size];
+ }
+ };
+}
diff --git a/src/com/android/launcher3/widget/custom/CustomWidgetParser.java b/src/com/android/launcher3/widget/custom/CustomWidgetParser.java
new file mode 100644
index 000000000..00720c449
--- /dev/null
+++ b/src/com/android/launcher3/widget/custom/CustomWidgetParser.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.widget.custom;
+
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.Parcel;
+import android.os.Process;
+import android.util.SparseArray;
+import android.util.Xml;
+
+import com.android.launcher3.LauncherAppWidgetInfo;
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.android.launcher3.LauncherAppWidgetProviderInfo.CLS_CUSTOM_WIDGET_PREFIX;
+
+/**
+ * Utility class to parse {@ink CustomAppWidgetProviderInfo} definitions from xml
+ */
+public class CustomWidgetParser {
+
+ private static List<LauncherAppWidgetProviderInfo> sCustomWidgets;
+ private static SparseArray<ComponentName> sWidgetsIdMap;
+
+ public static List<LauncherAppWidgetProviderInfo> getCustomWidgets(Context context) {
+ if (sCustomWidgets == null) {
+ // Synchronization not needed as it it safe to load multiple times
+ parseCustomWidgets(context);
+ }
+
+ return sCustomWidgets;
+ }
+
+ public static int getWidgetIdForCustomProvider(Context context, ComponentName provider) {
+ if (sWidgetsIdMap == null) {
+ parseCustomWidgets(context);
+ }
+ int index = sWidgetsIdMap.indexOfValue(provider);
+ if (index >= 0) {
+ return LauncherAppWidgetInfo.CUSTOM_WIDGET_ID - sWidgetsIdMap.keyAt(index);
+ } else {
+ return AppWidgetManager.INVALID_APPWIDGET_ID;
+ }
+ }
+
+ public static LauncherAppWidgetProviderInfo getWidgetProvider(Context context, int widgetId) {
+ if (sWidgetsIdMap == null || sCustomWidgets == null) {
+ parseCustomWidgets(context);
+ }
+ ComponentName cn = sWidgetsIdMap.get(LauncherAppWidgetInfo.CUSTOM_WIDGET_ID - widgetId);
+ for (LauncherAppWidgetProviderInfo info : sCustomWidgets) {
+ if (info.provider.equals(cn)) {
+ return info;
+ }
+ }
+ return null;
+ }
+
+ private static void parseCustomWidgets(Context context) {
+ ArrayList<LauncherAppWidgetProviderInfo> widgets = new ArrayList<>();
+ SparseArray<ComponentName> idMap = new SparseArray<>();
+
+ List<AppWidgetProviderInfo> providers = AppWidgetManager.getInstance(context)
+ .getInstalledProvidersForProfile(Process.myUserHandle());
+ if (providers.isEmpty()) {
+ sCustomWidgets = widgets;
+ sWidgetsIdMap = idMap;
+ return;
+ }
+
+ Parcel parcel = Parcel.obtain();
+ providers.get(0).writeToParcel(parcel, 0);
+
+ try (XmlResourceParser parser = context.getResources().getXml(R.xml.custom_widgets)) {
+ final int depth = parser.getDepth();
+ int type;
+
+ while (((type = parser.next()) != XmlPullParser.END_TAG ||
+ parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
+ if ((type == XmlPullParser.START_TAG) && "widget".equals(parser.getName())) {
+ TypedArray a = context.obtainStyledAttributes(
+ Xml.asAttributeSet(parser), R.styleable.CustomAppWidgetProviderInfo);
+
+ parcel.setDataPosition(0);
+ CustomAppWidgetProviderInfo info = newInfo(a, parcel, context);
+ widgets.add(info);
+ a.recycle();
+
+ idMap.put(info.providerId, info.provider);
+ }
+ }
+ } catch (IOException | XmlPullParserException e) {
+ throw new RuntimeException(e);
+ }
+ parcel.recycle();
+ sCustomWidgets = widgets;
+ sWidgetsIdMap = idMap;
+ }
+
+ private static CustomAppWidgetProviderInfo newInfo(TypedArray a, Parcel parcel, Context context) {
+ int providerId = a.getInt(R.styleable.CustomAppWidgetProviderInfo_providerId, 0);
+ CustomAppWidgetProviderInfo info = new CustomAppWidgetProviderInfo(parcel, false, providerId);
+ info.provider = new ComponentName(context.getPackageName(), CLS_CUSTOM_WIDGET_PREFIX + providerId);
+
+ info.label = a.getString(R.styleable.CustomAppWidgetProviderInfo_android_label);
+ info.initialLayout = a.getResourceId(R.styleable.CustomAppWidgetProviderInfo_android_initialLayout, 0);
+ info.icon = a.getResourceId(R.styleable.CustomAppWidgetProviderInfo_android_icon, 0);
+ info.previewImage = a.getResourceId(R.styleable.CustomAppWidgetProviderInfo_android_previewImage, 0);
+ info.resizeMode = a.getInt(R.styleable.CustomAppWidgetProviderInfo_android_resizeMode, 0);
+
+ info.spanX = a.getInt(R.styleable.CustomAppWidgetProviderInfo_numColumns, 1);
+ info.spanY = a.getInt(R.styleable.CustomAppWidgetProviderInfo_numRows, 1);
+ info.minSpanX = a.getInt(R.styleable.CustomAppWidgetProviderInfo_numMinColumns, 1);
+ info.minSpanY = a.getInt(R.styleable.CustomAppWidgetProviderInfo_numMinRows, 1);
+ return info;
+ }
+}