Merge "Moving widget inflation logic to a separate class" into main
This commit is contained in:
@@ -39,7 +39,6 @@ import com.android.launcher3.util.DisplayController.DisplayInfoChangeListener;
|
||||
import com.android.launcher3.util.DisplayController.Info;
|
||||
import com.android.launcher3.util.OnColorHintListener;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.launcher3.util.WallpaperColorHints;
|
||||
import com.android.launcher3.util.WindowBounds;
|
||||
|
||||
@@ -55,16 +54,12 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
||||
public static final Object AUTO_CANCEL_ACTION_MODE = new Object();
|
||||
|
||||
private ActionMode mCurrentActionMode;
|
||||
protected boolean mIsSafeModeEnabled;
|
||||
|
||||
private int mThemeRes = R.style.AppTheme;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mIsSafeModeEnabled = TraceHelper.allowIpcs("isSafeMode",
|
||||
() -> getPackageManager().isSafeMode());
|
||||
DisplayController.INSTANCE.get(this).addChangeListener(this);
|
||||
|
||||
// Update theme
|
||||
@@ -183,6 +178,6 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
||||
|
||||
@Override
|
||||
public boolean isAppBlockedForSafeMode() {
|
||||
return mIsSafeModeEnabled;
|
||||
return LauncherAppState.getInstance(this).isSafeModeEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,6 @@ import static com.android.launcher3.logging.StatsLogManager.StatsLatencyLogger.L
|
||||
import static com.android.launcher3.logging.StatsLogManager.StatsLatencyLogger.LatencyType.WARM;
|
||||
import static com.android.launcher3.model.ItemInstallQueue.FLAG_ACTIVITY_PAUSED;
|
||||
import static com.android.launcher3.model.ItemInstallQueue.FLAG_DRAG_AND_DROP;
|
||||
import static com.android.launcher3.model.data.LauncherAppWidgetInfo.CUSTOM_WIDGET_ID;
|
||||
import static com.android.launcher3.popup.SystemShortcut.APP_INFO;
|
||||
import static com.android.launcher3.popup.SystemShortcut.INSTALL;
|
||||
import static com.android.launcher3.popup.SystemShortcut.WIDGETS;
|
||||
@@ -196,7 +195,6 @@ import com.android.launcher3.model.BgDataModel.Callbacks;
|
||||
import com.android.launcher3.model.ItemInstallQueue;
|
||||
import com.android.launcher3.model.ModelWriter;
|
||||
import com.android.launcher3.model.StringCache;
|
||||
import com.android.launcher3.model.WidgetsModel;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
@@ -208,7 +206,6 @@ import com.android.launcher3.pm.PinRequestHelper;
|
||||
import com.android.launcher3.popup.ArrowPopup;
|
||||
import com.android.launcher3.popup.PopupDataProvider;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
import com.android.launcher3.qsb.QsbContainerView;
|
||||
import com.android.launcher3.statemanager.StateManager;
|
||||
import com.android.launcher3.statemanager.StateManager.StateHandler;
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
@@ -252,6 +249,8 @@ import com.android.launcher3.widget.PendingAddShortcutInfo;
|
||||
import com.android.launcher3.widget.PendingAddWidgetInfo;
|
||||
import com.android.launcher3.widget.PendingAppWidgetHostView;
|
||||
import com.android.launcher3.widget.WidgetAddFlowHandler;
|
||||
import com.android.launcher3.widget.WidgetInflater;
|
||||
import com.android.launcher3.widget.WidgetInflater.InflationResult;
|
||||
import com.android.launcher3.widget.WidgetManagerHelper;
|
||||
import com.android.launcher3.widget.custom.CustomWidgetManager;
|
||||
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
|
||||
@@ -333,6 +332,7 @@ public class Launcher extends StatefulActivity<LauncherState>
|
||||
|
||||
private WidgetManagerHelper mAppWidgetManager;
|
||||
private LauncherWidgetHolder mAppWidgetHolder;
|
||||
private WidgetInflater mWidgetInflater;
|
||||
|
||||
private final int[] mTmpAddItemCellCoordinates = new int[2];
|
||||
|
||||
@@ -517,6 +517,7 @@ public class Launcher extends StatefulActivity<LauncherState>
|
||||
setupViews();
|
||||
|
||||
mAppWidgetManager = new WidgetManagerHelper(this);
|
||||
mWidgetInflater = new WidgetInflater(this);
|
||||
mAppWidgetHolder = createAppWidgetHolder();
|
||||
mAppWidgetHolder.startListening();
|
||||
mAppWidgetHolder.addProviderChangeListener(() -> refreshAndBindWidgetsForPackageUser(null));
|
||||
@@ -2309,157 +2310,30 @@ public class Launcher extends StatefulActivity<LauncherState>
|
||||
|
||||
private View inflateAppWidget(LauncherAppWidgetInfo item,
|
||||
@Nullable LauncherRestoreEventLogger restoreEventLogger) {
|
||||
if (item.hasOptionFlag(LauncherAppWidgetInfo.OPTION_SEARCH_WIDGET)) {
|
||||
item.providerName = QsbContainerView.getSearchComponentName(this);
|
||||
if (item.providerName == null) {
|
||||
getModelWriter().deleteItemFromDatabase(item,
|
||||
"search widget removed because search component cannot be found");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
final AppWidgetHostView view;
|
||||
if (mIsSafeModeEnabled) {
|
||||
view = new PendingAppWidgetHostView(this, item, null, true);
|
||||
prepareAppWidget(view, item);
|
||||
return view;
|
||||
}
|
||||
|
||||
TraceHelper.INSTANCE.beginSection("BIND_WIDGET_id=" + item.appWidgetId);
|
||||
try {
|
||||
final LauncherAppWidgetProviderInfo appWidgetInfo;
|
||||
String removalReason = "";
|
||||
if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)) {
|
||||
// If the provider is not ready, bind as a pending widget.
|
||||
appWidgetInfo = null;
|
||||
removalReason = "the provider isn't ready.";
|
||||
} else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) {
|
||||
// The widget id is not valid. Try to find the widget based on the provider info.
|
||||
appWidgetInfo = mAppWidgetManager.findProvider(item.providerName, item.user);
|
||||
if (appWidgetInfo == null) {
|
||||
if (WidgetsModel.GO_DISABLE_WIDGETS) {
|
||||
removalReason = "widgets are disabled on go device.";
|
||||
} else {
|
||||
removalReason =
|
||||
"WidgetManagerHelper cannot find a provider from provider info.";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
appWidgetInfo = mAppWidgetManager.getLauncherAppWidgetInfo(item.appWidgetId,
|
||||
item.getTargetComponent());
|
||||
if (appWidgetInfo == null) {
|
||||
if (item.appWidgetId <= CUSTOM_WIDGET_ID) {
|
||||
removalReason =
|
||||
"CustomWidgetManager cannot find provider from that widget id.";
|
||||
} else {
|
||||
removalReason = "AppWidgetManager cannot find provider for that widget id."
|
||||
+ " It could be because AppWidgetService is not available, or the"
|
||||
+ " appWidgetId has not been bound to a the provider yet, or you"
|
||||
+ " don't have access to that appWidgetId.";
|
||||
}
|
||||
InflationResult inflationResult = mWidgetInflater.inflateAppWidget(item);
|
||||
if (inflationResult.getType() == WidgetInflater.TYPE_DELETE) {
|
||||
getModelWriter().deleteItemFromDatabase(item, inflationResult.getReason());
|
||||
if (restoreEventLogger != null) {
|
||||
restoreEventLogger.logSingleFavoritesItemRestoreFailed(
|
||||
ITEM_TYPE_APPWIDGET, RESTORE_ERROR_BIND_FAILURE);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// If the provider is ready, but the width is not yet restored, try to restore it.
|
||||
if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)
|
||||
&& (item.restoreStatus != LauncherAppWidgetInfo.RESTORE_COMPLETED)) {
|
||||
if (appWidgetInfo == null) {
|
||||
getModelWriter().deleteItemFromDatabase(item,
|
||||
"Removing restored widget: id=" + item.appWidgetId
|
||||
+ " belongs to component " + item.providerName + " user " + item.user
|
||||
+ ", as the provider is null and " + removalReason);
|
||||
if (restoreEventLogger != null) {
|
||||
restoreEventLogger.logSingleFavoritesItemRestoreFailed(
|
||||
ITEM_TYPE_APPWIDGET, RESTORE_ERROR_BIND_FAILURE);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// If we do not have a valid id, try to bind an id.
|
||||
if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) {
|
||||
if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_ALLOCATED)) {
|
||||
// Id has not been allocated yet. Allocate a new id.
|
||||
item.appWidgetId = mAppWidgetHolder.allocateAppWidgetId();
|
||||
item.restoreStatus |= LauncherAppWidgetInfo.FLAG_ID_ALLOCATED;
|
||||
|
||||
// Also try to bind the widget. If the bind fails, the user will be shown
|
||||
// a click to setup UI, which will ask for the bind permission.
|
||||
PendingAddWidgetInfo pendingInfo =
|
||||
new PendingAddWidgetInfo(appWidgetInfo, item.sourceContainer);
|
||||
pendingInfo.spanX = item.spanX;
|
||||
pendingInfo.spanY = item.spanY;
|
||||
pendingInfo.minSpanX = item.minSpanX;
|
||||
pendingInfo.minSpanY = item.minSpanY;
|
||||
Bundle options = pendingInfo.getDefaultSizeOptions(this);
|
||||
|
||||
boolean isDirectConfig =
|
||||
item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG);
|
||||
if (isDirectConfig && item.bindOptions != null) {
|
||||
Bundle newOptions = item.bindOptions.getExtras();
|
||||
if (options != null) {
|
||||
newOptions.putAll(options);
|
||||
}
|
||||
options = newOptions;
|
||||
}
|
||||
boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed(
|
||||
item.appWidgetId, appWidgetInfo, options);
|
||||
|
||||
// We tried to bind once. If we were not able to bind, we would need to
|
||||
// go through the permission dialog, which means we cannot skip the config
|
||||
// activity.
|
||||
item.bindOptions = null;
|
||||
item.restoreStatus &= ~LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG;
|
||||
|
||||
// Bind succeeded
|
||||
if (success) {
|
||||
// If the widget has a configure activity, it is still needs to set it
|
||||
// up, otherwise the widget is ready to go.
|
||||
item.restoreStatus = (appWidgetInfo.configure == null) || isDirectConfig
|
||||
? LauncherAppWidgetInfo.RESTORE_COMPLETED
|
||||
: LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
|
||||
}
|
||||
|
||||
getModelWriter().updateItemInDatabase(item);
|
||||
}
|
||||
} else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_UI_NOT_READY)
|
||||
&& (appWidgetInfo.configure == null)) {
|
||||
// The widget was marked as UI not ready, but there is no configure activity to
|
||||
// update the UI.
|
||||
item.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED;
|
||||
getModelWriter().updateItemInDatabase(item);
|
||||
}
|
||||
else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_UI_NOT_READY)
|
||||
&& appWidgetInfo.configure != null) {
|
||||
if (mAppWidgetManager.isAppWidgetRestored(item.appWidgetId)) {
|
||||
item.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED;
|
||||
getModelWriter().updateItemInDatabase(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
|
||||
// Verify that we own the widget
|
||||
if (appWidgetInfo == null) {
|
||||
FileLog.e(TAG, "Removing invalid widget: id=" + item.appWidgetId);
|
||||
getModelWriter().deleteWidgetInfo(item, getAppWidgetHolder(), removalReason);
|
||||
if (restoreEventLogger != null) {
|
||||
restoreEventLogger.logSingleFavoritesItemRestoreFailed(
|
||||
ITEM_TYPE_APPWIDGET, RESTORE_ERROR_BIND_FAILURE);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
item.minSpanX = appWidgetInfo.minSpanX;
|
||||
item.minSpanY = appWidgetInfo.minSpanY;
|
||||
view = mAppWidgetHolder.createView(item.appWidgetId, appWidgetInfo);
|
||||
} else {
|
||||
view = new PendingAppWidgetHostView(this, item, appWidgetInfo, false);
|
||||
if (inflationResult.isUpdate()) {
|
||||
getModelWriter().updateItemInDatabase(item);
|
||||
}
|
||||
AppWidgetHostView view = inflationResult.getType() == WidgetInflater.TYPE_PENDING
|
||||
? new PendingAppWidgetHostView(this, item, inflationResult.getWidgetInfo())
|
||||
: mAppWidgetHolder.createView(
|
||||
item.appWidgetId, inflationResult.getWidgetInfo());
|
||||
prepareAppWidget(view, item);
|
||||
return view;
|
||||
} finally {
|
||||
TraceHelper.INSTANCE.endSection();
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -56,6 +56,7 @@ import com.android.launcher3.util.SafeCloseable;
|
||||
import com.android.launcher3.util.SettingsCache;
|
||||
import com.android.launcher3.util.SimpleBroadcastReceiver;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.launcher3.widget.custom.CustomWidgetManager;
|
||||
|
||||
public class LauncherAppState implements SafeCloseable {
|
||||
@@ -71,6 +72,8 @@ public class LauncherAppState implements SafeCloseable {
|
||||
private final LauncherIconProvider mIconProvider;
|
||||
private final IconCache mIconCache;
|
||||
private final InvariantDeviceProfile mInvariantDeviceProfile;
|
||||
private boolean mIsSafeModeEnabled;
|
||||
|
||||
private final RunnableList mOnTerminateCallback = new RunnableList();
|
||||
|
||||
public static LauncherAppState getInstance(final Context context) {
|
||||
@@ -90,6 +93,8 @@ public class LauncherAppState implements SafeCloseable {
|
||||
Log.v(Launcher.TAG, "LauncherAppState initiated");
|
||||
Preconditions.assertUIThread();
|
||||
|
||||
mIsSafeModeEnabled = TraceHelper.allowIpcs("isSafeMode",
|
||||
() -> context.getPackageManager().isSafeMode());
|
||||
mInvariantDeviceProfile.addOnChangeListener(modelPropertiesChanged -> {
|
||||
if (modelPropertiesChanged) {
|
||||
refreshAndReloadLauncher();
|
||||
@@ -224,6 +229,10 @@ public class LauncherAppState implements SafeCloseable {
|
||||
return mInvariantDeviceProfile;
|
||||
}
|
||||
|
||||
public boolean isSafeModeEnabled() {
|
||||
return mIsSafeModeEnabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shorthand for {@link #getInvariantDeviceProfile()}
|
||||
*/
|
||||
|
||||
@@ -88,8 +88,8 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView
|
||||
private Layout mSetupTextLayout;
|
||||
|
||||
public PendingAppWidgetHostView(Context context, LauncherAppWidgetInfo info,
|
||||
@Nullable LauncherAppWidgetProviderInfo appWidget, boolean disabledForSafeMode) {
|
||||
this(context, info, disabledForSafeMode, appWidget,
|
||||
@Nullable LauncherAppWidgetProviderInfo appWidget) {
|
||||
this(context, info, appWidget,
|
||||
context.getResources().getText(R.string.gadget_complete_setup_text));
|
||||
|
||||
super.updateAppWidget(null);
|
||||
@@ -107,7 +107,7 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView
|
||||
|
||||
public PendingAppWidgetHostView(
|
||||
Context context, int appWidgetId, @NonNull LauncherAppWidgetProviderInfo appWidget) {
|
||||
this(context, new LauncherAppWidgetInfo(appWidgetId, appWidget.provider), false,
|
||||
this(context, new LauncherAppWidgetInfo(appWidgetId, appWidget.provider),
|
||||
appWidget, appWidget.label);
|
||||
getBackground().mutate().setAlpha(DEFERRED_ALPHA);
|
||||
|
||||
@@ -117,14 +117,13 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView
|
||||
}
|
||||
|
||||
private PendingAppWidgetHostView(Context context, LauncherAppWidgetInfo info,
|
||||
boolean disabledForSafeMode, LauncherAppWidgetProviderInfo appwidget,
|
||||
CharSequence label) {
|
||||
LauncherAppWidgetProviderInfo appwidget, CharSequence label) {
|
||||
super(new ContextThemeWrapper(context, R.style.WidgetContainerTheme));
|
||||
|
||||
mAppwidget = appwidget;
|
||||
mInfo = info;
|
||||
mStartState = info.restoreStatus;
|
||||
mDisabledForSafeMode = disabledForSafeMode;
|
||||
mDisabledForSafeMode = LauncherAppState.getInstance(context).isSafeModeEnabled();
|
||||
mLabel = label;
|
||||
|
||||
mPaint = new TextPaint();
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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
|
||||
|
||||
import android.content.Context
|
||||
import com.android.launcher3.Launcher
|
||||
import com.android.launcher3.LauncherAppState
|
||||
import com.android.launcher3.logging.FileLog
|
||||
import com.android.launcher3.model.WidgetsModel
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo
|
||||
import com.android.launcher3.qsb.QsbContainerView
|
||||
|
||||
/** Utility class for handling widget inflation taking into account all the restore state updates */
|
||||
class WidgetInflater(private val context: Context) {
|
||||
|
||||
private val widgetHelper = WidgetManagerHelper(context)
|
||||
|
||||
fun inflateAppWidget(
|
||||
item: LauncherAppWidgetInfo,
|
||||
): InflationResult {
|
||||
if (item.hasOptionFlag(LauncherAppWidgetInfo.OPTION_SEARCH_WIDGET)) {
|
||||
item.providerName = QsbContainerView.getSearchComponentName(context)
|
||||
if (item.providerName == null) {
|
||||
return InflationResult(
|
||||
TYPE_DELETE,
|
||||
reason = "search widget removed because search component cannot be found"
|
||||
)
|
||||
}
|
||||
}
|
||||
if (LauncherAppState.INSTANCE.get(context).isSafeModeEnabled) {
|
||||
return InflationResult(TYPE_PENDING)
|
||||
}
|
||||
val appWidgetInfo: LauncherAppWidgetProviderInfo?
|
||||
var removalReason = ""
|
||||
if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)) {
|
||||
// If the provider is not ready, bind as a pending widget.
|
||||
appWidgetInfo = null
|
||||
removalReason = "the provider isn't ready."
|
||||
} else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) {
|
||||
// The widget id is not valid. Try to find the widget based on the provider info.
|
||||
appWidgetInfo = widgetHelper.findProvider(item.providerName, item.user)
|
||||
if (appWidgetInfo == null) {
|
||||
if (WidgetsModel.GO_DISABLE_WIDGETS) {
|
||||
removalReason = "widgets are disabled on go device."
|
||||
} else {
|
||||
removalReason = "WidgetManagerHelper cannot find a provider from provider info."
|
||||
}
|
||||
}
|
||||
} else {
|
||||
appWidgetInfo =
|
||||
widgetHelper.getLauncherAppWidgetInfo(item.appWidgetId, item.targetComponent)
|
||||
if (appWidgetInfo == null) {
|
||||
if (item.appWidgetId <= LauncherAppWidgetInfo.CUSTOM_WIDGET_ID) {
|
||||
removalReason = "CustomWidgetManager cannot find provider from that widget id."
|
||||
} else {
|
||||
removalReason =
|
||||
("AppWidgetManager cannot find provider for that widget id." +
|
||||
" It could be because AppWidgetService is not available, or the" +
|
||||
" appWidgetId has not been bound to a the provider yet, or you" +
|
||||
" don't have access to that appWidgetId.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var update = false
|
||||
|
||||
// If the provider is ready, but the width is not yet restored, try to restore it.
|
||||
if (
|
||||
!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) &&
|
||||
item.restoreStatus != LauncherAppWidgetInfo.RESTORE_COMPLETED
|
||||
) {
|
||||
if (appWidgetInfo == null) {
|
||||
return InflationResult(
|
||||
type = TYPE_DELETE,
|
||||
reason =
|
||||
"Removing restored widget: id=${item.appWidgetId} belongs to component" +
|
||||
" ${item.providerName} user ${item.user}" +
|
||||
", as the provider is null and $removalReason"
|
||||
)
|
||||
}
|
||||
|
||||
// If we do not have a valid id, try to bind an id.
|
||||
if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) {
|
||||
if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_ALLOCATED)) {
|
||||
// Id has not been allocated yet. Allocate a new id.
|
||||
LauncherWidgetHolder.newInstance(context).let {
|
||||
item.appWidgetId = it.allocateAppWidgetId()
|
||||
it.destroy()
|
||||
}
|
||||
item.restoreStatus =
|
||||
item.restoreStatus or LauncherAppWidgetInfo.FLAG_ID_ALLOCATED
|
||||
|
||||
// Also try to bind the widget. If the bind fails, the user will be shown
|
||||
// a click to setup UI, which will ask for the bind permission.
|
||||
val pendingInfo = PendingAddWidgetInfo(appWidgetInfo, item.sourceContainer)
|
||||
pendingInfo.spanX = item.spanX
|
||||
pendingInfo.spanY = item.spanY
|
||||
pendingInfo.minSpanX = item.minSpanX
|
||||
pendingInfo.minSpanY = item.minSpanY
|
||||
var options = pendingInfo.getDefaultSizeOptions(context)
|
||||
val isDirectConfig =
|
||||
item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG)
|
||||
if (isDirectConfig && item.bindOptions != null) {
|
||||
val newOptions = item.bindOptions.extras
|
||||
if (options != null) {
|
||||
newOptions!!.putAll(options)
|
||||
}
|
||||
options = newOptions
|
||||
}
|
||||
val success =
|
||||
widgetHelper.bindAppWidgetIdIfAllowed(
|
||||
item.appWidgetId,
|
||||
appWidgetInfo,
|
||||
options
|
||||
)
|
||||
|
||||
// We tried to bind once. If we were not able to bind, we would need to
|
||||
// go through the permission dialog, which means we cannot skip the config
|
||||
// activity.
|
||||
item.bindOptions = null
|
||||
item.restoreStatus =
|
||||
item.restoreStatus and LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG.inv()
|
||||
|
||||
// Bind succeeded
|
||||
if (success) {
|
||||
// If the widget has a configure activity, it is still needs to set it
|
||||
// up, otherwise the widget is ready to go.
|
||||
item.restoreStatus =
|
||||
if ((appWidgetInfo.configure == null) || isDirectConfig)
|
||||
LauncherAppWidgetInfo.RESTORE_COMPLETED
|
||||
else LauncherAppWidgetInfo.FLAG_UI_NOT_READY
|
||||
}
|
||||
update = true
|
||||
}
|
||||
} else if (
|
||||
(item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_UI_NOT_READY) &&
|
||||
(appWidgetInfo.configure == null))
|
||||
) {
|
||||
// The widget was marked as UI not ready, but there is no configure activity to
|
||||
// update the UI.
|
||||
item.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED
|
||||
update = true
|
||||
} else if (
|
||||
(item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_UI_NOT_READY) &&
|
||||
appWidgetInfo.configure != null)
|
||||
) {
|
||||
if (widgetHelper.isAppWidgetRestored(item.appWidgetId)) {
|
||||
item.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED
|
||||
update = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
|
||||
// Verify that we own the widget
|
||||
if (appWidgetInfo == null) {
|
||||
FileLog.e(Launcher.TAG, "Removing invalid widget: id=" + item.appWidgetId)
|
||||
return InflationResult(TYPE_DELETE, reason = removalReason)
|
||||
}
|
||||
item.minSpanX = appWidgetInfo.minSpanX
|
||||
item.minSpanY = appWidgetInfo.minSpanY
|
||||
return InflationResult(TYPE_REAL, isUpdate = update, widgetInfo = appWidgetInfo)
|
||||
} else {
|
||||
return InflationResult(TYPE_PENDING, isUpdate = update, widgetInfo = appWidgetInfo)
|
||||
}
|
||||
}
|
||||
|
||||
data class InflationResult(
|
||||
val type: Int,
|
||||
val reason: String? = null,
|
||||
val isUpdate: Boolean = false,
|
||||
val widgetInfo: LauncherAppWidgetProviderInfo? = null
|
||||
)
|
||||
|
||||
companion object {
|
||||
const val TYPE_DELETE = 0
|
||||
|
||||
const val TYPE_PENDING = 1
|
||||
|
||||
const val TYPE_REAL = 2
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user