Log widget features.
Design doc: go/widgets-logging
Note that this doesn't log dynamic colors yet. I'll work on that in a
follow-up CL.
Bug: 185778648
Test: manual
Change-Id: I04249ef267907b4112c220fb206e077d1bee783a
diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto
index fb47b0a..475b5be 100644
--- a/protos/launcher_atom.proto
+++ b/protos/launcher_atom.proto
@@ -162,6 +162,7 @@
optional int32 app_widget_id = 3;
optional string package_name = 4; // only populated during snapshot if from workspace
optional string component_name = 5; // only populated during snapshot if from workspace
+ optional int32 widget_features = 6;
}
// Tasks handled by PackageManager
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index 3b26108..719cb0a 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -354,6 +354,10 @@
}
private static int getCardinality(LauncherAtom.ItemInfo info) {
+ // TODO(b/187734511): Implement a unified solution for 1x1 widgets in folders/hotseat.
+ if (info.getItemCase().equals(LauncherAtom.ItemInfo.ItemCase.WIDGET)) {
+ return info.getWidget().getWidgetFeatures();
+ }
switch (info.getContainerInfo().getContainerCase()) {
case PREDICTED_HOTSEAT_CONTAINER:
return info.getContainerInfo().getPredictedHotseatContainer().getCardinality();
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 5896f5a..c9700ad 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1315,8 +1315,15 @@
appWidgetInfo = mAppWidgetManager.getLauncherAppWidgetInfo(appWidgetId);
}
+ if (hostView == null) {
+ // Perform actual inflation because we're live
+ hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
+ }
+
LauncherAppWidgetInfo launcherInfo;
- launcherInfo = new LauncherAppWidgetInfo(appWidgetId, appWidgetInfo.provider);
+ launcherInfo =
+ new LauncherAppWidgetInfo(
+ appWidgetId, appWidgetInfo.provider, appWidgetInfo, hostView);
launcherInfo.spanX = itemInfo.spanX;
launcherInfo.spanY = itemInfo.spanY;
launcherInfo.minSpanX = itemInfo.minSpanX;
@@ -1326,10 +1333,6 @@
getModelWriter().addItemToDatabase(launcherInfo,
itemInfo.container, itemInfo.screenId, itemInfo.cellX, itemInfo.cellY);
- if (hostView == null) {
- // Perform actual inflation because we're live
- hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
- }
hostView.setVisibility(View.VISIBLE);
prepareAppWidget(hostView, launcherInfo);
mWorkspace.addInScreen(hostView, launcherInfo);
diff --git a/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java b/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java
index c04b7f0..003b3bd 100644
--- a/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java
+++ b/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java
@@ -16,9 +16,12 @@
package com.android.launcher3.model.data;
+import static com.android.launcher3.Utilities.ATLEAST_S;
+
import android.appwidget.AppWidgetHostView;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.res.Resources;
import android.os.Process;
import androidx.annotation.Nullable;
@@ -26,7 +29,10 @@
import com.android.launcher3.AppWidgetResizeFrame;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.util.ContentWriter;
+import com.android.launcher3.widget.LauncherAppWidgetHostView;
+import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
/**
* Represents a widget (either instantiated or about to be) in the Launcher.
@@ -81,6 +87,18 @@
public static final int CUSTOM_WIDGET_ID = -100;
/**
+ * Flags for recording all the features that a widget has enabled.
+ * @see widgetFeatures
+ */
+ public static final int FEATURE_RECONFIGURABLE = 1;
+ public static final int FEATURE_OPTIONAL_CONFIGURATION = 1 << 1;
+ public static final int FEATURE_PREVIEW_LAYOUT = 1 << 2;
+ public static final int FEATURE_TARGET_CELL_SIZE = 1 << 3;
+ public static final int FEATURE_MIN_SIZE = 1 << 4;
+ public static final int FEATURE_MAX_SIZE = 1 << 5;
+ public static final int FEATURE_ROUNDED_CORNERS = 1 << 6;
+
+ /**
* Identifier for this widget when talking with
* {@link android.appwidget.AppWidgetManager} for updates.
*/
@@ -113,6 +131,12 @@
*/
public PackageItemInfo pendingItemInfo;
+ /**
+ * Contains a binary representation indicating which widget features are enabled. This value is
+ * -1 if widget features could not be identified.
+ */
+ private int widgetFeatures;
+
private boolean mHasNotifiedInitialWidgetSizeChanged;
public LauncherAppWidgetInfo(int appWidgetId, ComponentName providerName) {
@@ -129,11 +153,18 @@
// to indicate that they should be calculated based on the layout and minWidth/minHeight
spanX = -1;
spanY = -1;
+ widgetFeatures = -1;
// We only support app widgets on current user.
user = Process.myUserHandle();
restoreStatus = RESTORE_COMPLETED;
}
+ public LauncherAppWidgetInfo(int appWidgetId, ComponentName providerName,
+ LauncherAppWidgetProviderInfo providerInfo, AppWidgetHostView hostView) {
+ this(appWidgetId, providerName);
+ widgetFeatures = computeWidgetFeatures(providerInfo, hostView);
+ }
+
/** Used for testing **/
public LauncherAppWidgetInfo() {
itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
@@ -194,4 +225,41 @@
public final boolean hasOptionFlag(int option) {
return (options & option) != 0;
}
+
+ @SuppressWarnings("NewApi")
+ private static int computeWidgetFeatures(
+ LauncherAppWidgetProviderInfo providerInfo, AppWidgetHostView hostView) {
+ int widgetFeatures = 0;
+ if (providerInfo.isReconfigurable()) {
+ widgetFeatures |= FEATURE_RECONFIGURABLE;
+ }
+ if (providerInfo.isConfigurationOptional()) {
+ widgetFeatures |= FEATURE_OPTIONAL_CONFIGURATION;
+ }
+ if (ATLEAST_S && providerInfo.previewLayout != Resources.ID_NULL) {
+ widgetFeatures |= FEATURE_PREVIEW_LAYOUT;
+ }
+ if (ATLEAST_S && providerInfo.targetCellWidth > 0 || providerInfo.targetCellHeight > 0) {
+ widgetFeatures |= FEATURE_TARGET_CELL_SIZE;
+ }
+ if (providerInfo.minResizeWidth > 0 || providerInfo.minResizeHeight > 0) {
+ widgetFeatures |= FEATURE_MIN_SIZE;
+ }
+ if (ATLEAST_S && providerInfo.maxResizeWidth > 0 || providerInfo.maxResizeHeight > 0) {
+ widgetFeatures |= FEATURE_MAX_SIZE;
+ }
+ if (hostView instanceof LauncherAppWidgetHostView &&
+ ((LauncherAppWidgetHostView) hostView).hasEnforcedCornerRadius()) {
+ widgetFeatures |= FEATURE_ROUNDED_CORNERS;
+ }
+ return widgetFeatures;
+ }
+
+ @Override
+ public LauncherAtom.ItemInfo buildProto(FolderInfo folderInfo) {
+ LauncherAtom.ItemInfo info = super.buildProto(folderInfo);
+ return info.toBuilder()
+ .setWidget(info.getWidget().toBuilder().setWidgetFeatures(widgetFeatures))
+ .build();
+ }
}
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
index de511cd..53b5fec 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java
@@ -149,6 +149,12 @@
return configure != null && (getWidgetFeatures() & WIDGET_FEATURE_RECONFIGURABLE) != 0;
}
+ public boolean isConfigurationOptional() {
+ return ATLEAST_S
+ && isReconfigurable()
+ && (getWidgetFeatures() & WIDGET_FEATURE_CONFIGURATION_OPTIONAL) != 0;
+ }
+
@Override
public final ComponentName getComponent() {
return provider;