最近遇到几个客户要求长按桌面要有添加微件这个功能按钮,我们知道项目是按照go版过的GMS,go版系统是不带这个功能的,微件小部件是normal版的功能,也就是ddr必须是3G及以上容量才能带这个功能的,但是客户就是要求有这个功能,所以还是老老实实的加上,没办法,谁叫客户就是上帝呢,具体方法如下:
1. frameworks/base
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
old mode 100644
new mode 100755
index fc27da1..38f31f7
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3363,7 +3363,7 @@
<!-- True if the device requires AppWidgetService even if it does not have
the PackageManager.FEATURE_APP_WIDGETS feature -->
- <bool name="config_enableAppWidgetService">false</bool>
+ <bool name="config_enableAppWidgetService">true</bool>
<!-- True if the device supports Sustained Performance Mode-->
<bool name="config_sustainedPerformanceModeSupported">false</bool>
2. frameworks/native
diff --git a/data/etc/go_handheld_core_hardware.xml b/data/etc/go_handheld_core_hardware.xml
old mode 100644
new mode 100755
index ec73a60..dba7fcd
--- a/data/etc/go_handheld_core_hardware.xml
+++ b/data/etc/go_handheld_core_hardware.xml
@@ -34,6 +34,7 @@
<feature name="android.hardware.screen.landscape" />
<!-- basic system services -->
+ <feature name="android.software.app_widgets" />
<feature name="android.software.connectionservice" />
<feature name="android.software.backup" />
<feature name="android.software.home_screen" />
3. packages/apps/Launcher3 这个目录下改动比较大,请仔细核对
diff --git a/go/src/com/android/launcher3/model/LoaderResults.java b/go/src/com/android/launcher3/model/LoaderResults.java
old mode 100644
new mode 100755
index 7130531..aa2f679
--- a/go/src/com/android/launcher3/model/LoaderResults.java
+++ b/go/src/com/android/launcher3/model/LoaderResults.java
@@ -20,7 +20,12 @@ import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.model.BgDataModel.Callbacks;
+import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.LooperExecutor;
+import com.android.launcher3.widget.WidgetListRowEntry;
+
+import java.util.ArrayList;
+import java.util.HashMap;
/**
* Helper class to handle results of {@link com.android.launcher3.model.LoaderTask}.
@@ -39,9 +44,17 @@ public class LoaderResults extends BaseLoaderResults {
@Override
public void bindDeepShortcuts() {
+ final HashMap<ComponentKey, Integer> shortcutMapCopy;
+ synchronized (mBgDataModel) {
+ shortcutMapCopy = new HashMap<>(mBgDataModel.deepShortcutMap);
+ }
+ executeCallbacksTask(c -> c.bindDeepShortcutMap(shortcutMapCopy), mUiExecutor);
}
@Override
public void bindWidgets() {
+ final ArrayList<WidgetListRowEntry> widgets =
+ mBgDataModel.widgetsModel.getWidgetsList(mApp.getContext());
+ executeCallbacksTask(c -> c.bindAllWidgets(widgets), mUiExecutor);
}
}
diff --git a/go/src/com/android/launcher3/model/WidgetsModel.java b/go/src/com/android/launcher3/model/WidgetsModel.java
old mode 100644
new mode 100755
index 3b3dc01..9d87788
--- a/go/src/com/android/launcher3/model/WidgetsModel.java
+++ b/go/src/com/android/launcher3/model/WidgetsModel.java
@@ -1,35 +1,45 @@
-/*
- * Copyright (C) 2018 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.model;
+import static android.appwidget.AppWidgetProviderInfo.WIDGET_FEATURE_HIDE_FROM_PICKER;
+
+import static com.android.launcher3.pm.ShortcutConfigActivityInfo.queryList;
+
+import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Process;
import android.os.UserHandle;
+import android.util.Log;
import androidx.annotation.Nullable;
+import com.android.launcher3.AppFilter;
+import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.compat.AlphabeticIndexCompat;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.ComponentWithLabelAndIcon;
+import com.android.launcher3.icons.IconCache;
+import com.android.launcher3.model.data.PackageItemInfo;
+import com.android.launcher3.pm.ShortcutConfigActivityInfo;
+import com.android.launcher3.util.MultiHashMap;
import com.android.launcher3.util.PackageUserKey;
+import com.android.launcher3.util.Preconditions;
+import com.android.launcher3.widget.WidgetItemComparator;
import com.android.launcher3.widget.WidgetListRowEntry;
+import com.android.launcher3.widget.WidgetManagerHelper;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
/**
@@ -40,9 +50,15 @@ import java.util.Set;
public class WidgetsModel {
// True is the widget support is disabled.
- public static final boolean GO_DISABLE_WIDGETS = true;
+ public static final boolean GO_DISABLE_WIDGETS = false;
+
+ private static final String TAG = "WidgetsModel";
+ private static final boolean DEBUG = false;
- private static final ArrayList<WidgetListRowEntry> EMPTY_WIDGET_LIST = new ArrayList<>();
+ /* Map of widgets and shortcuts that are tracked per package. */
+ private final MultiHashMap<PackageItemInfo, WidgetItem> mWidgetsList = new MultiHashMap<>();
+
+ private AppFilter mAppFilter;
/**
* Returns a list of {@link WidgetListRowEntry}. All {@link WidgetItem} in a single row
@@ -53,25 +69,196 @@ public class WidgetsModel {
* @see com.android.launcher3.widget.WidgetsListAdapter#setWidgets(ArrayList)
*/
public synchronized ArrayList<WidgetListRowEntry> getWidgetsList(Context context) {
- return EMPTY_WIDGET_LIST;
+ ArrayList<WidgetListRowEntry> result = new ArrayList<>();
+ AlphabeticIndexCompat indexer = new AlphabeticIndexCompat(context);
+
+ WidgetItemComparator widgetComparator = new WidgetItemComparator();
+ for (Map.Entry<PackageItemInfo, ArrayList<WidgetItem>> entry : mWidgetsList.entrySet()) {
+ WidgetListRowEntry row = new WidgetListRowEntry(entry.getKey(), entry.getValue());
+ row.titleSectionName = (row.pkgItem.title == null) ? "" :
+ indexer.computeSectionName(row.pkgItem.title);
+ Collections.sort(row.widgets, widgetComparator);
+ result.add(row);
+ }
+ return result;
}
/**
* @param packageUser If null, all widgets and shortcuts are updated and returned, otherwise
* only widgets and shortcuts associated with the package/user are.
*/
- public List<ComponentWithLabelAndIcon> update(LauncherAppState app,
- @Nullable PackageUserKey packageUser) {
- return Collections.emptyList();
+ public List<ComponentWithLabelAndIcon> update(
+ LauncherAppState app, @Nullable PackageUserKey packageUser) {
+ Preconditions.assertWorkerThread();
+
+ Context context = app.getContext();
+ final ArrayList<WidgetItem> widgetsAndShortcuts = new ArrayList<>();
+ List<ComponentWithLabelAndIcon> updatedItems = new ArrayList<>();
+ try {
+ InvariantDeviceProfile idp = app.getInvariantDeviceProfile();
+ PackageManager pm = app.getContext().getPackageManager();
+
+ // Widgets
+ WidgetManagerHelper widgetManager = new WidgetManagerHelper(context);
+ for (AppWidgetProviderInfo widgetInfo : widgetManager.getAllProviders(packageUser)) {
+ LauncherAppWidgetProviderInfo launcherWidgetInfo =
+ LauncherAppWidgetProviderInfo.fromProviderInfo(context, widgetInfo);
+
+ widgetsAndShortcuts.add(new WidgetItem(
+ launcherWidgetInfo, idp, app.getIconCache()));
+ updatedItems.add(launcherWidgetInfo);
+ }
+
+ // Shortcuts
+ for (ShortcutConfigActivityInfo info :
+ queryList(context, packageUser)) {
+ widgetsAndShortcuts.add(new WidgetItem(info, app.getIconCache(), pm));
+ updatedItems.add(info);
+ }
+ setWidgetsAndShortcuts(widgetsAndShortcuts, app, packageUser);
+ } catch (Exception e) {
+ if (!FeatureFlags.IS_STUDIO_BUILD && Utilities.isBinderSizeError(e)) {
+ // the returned value may be incomplete and will not be refreshed until the next
+ // time Launcher starts.
+ // TODO: after figuring out a repro step, introduce a dirty bit to check when
+ // onResume is called to refresh the widget provider list.
+ } else {
+ throw e;
+ }
+ }
+
+ app.getWidgetCache().removeObsoletePreviews(widgetsAndShortcuts, packageUser);
+ return updatedItems;
}
+ private synchronized void setWidgetsAndShortcuts(ArrayList<WidgetItem> rawWidgetsShortcuts,
+ LauncherAppState app, @Nullable PackageUserKey packageUser) {
+ if (DEBUG) {
+ Log.d(TAG, "addWidgetsAndShortcuts, widgetsShortcuts#=" + rawWidgetsShortcuts.size());
+ }
+
+ // Temporary list for {@link PackageItemInfos} to avoid having to go through
+ // {@link mPackageItemInfos} to locate the key to be used for {@link #mWidgetsList}
+ HashMap<String, PackageItemInfo> tmpPackageItemInfos = new HashMap<>();
+
+ // clear the lists.
+ if (packageUser == null) {
+ mWidgetsList.clear();
+ } else {
+ // Only clear the widgets for the given package/user.
+ PackageItemInfo packageItem = null;
+ for (PackageItemInfo item : mWidgetsList.keySet()) {
+ if (item.packageName.equals(packageUser.mPackageName)) {
+ packageItem = item;
+ break;
+ }
+ }
+ if (packageItem != null) {
+ // We want to preserve the user that was on the packageItem previously,
+ // so add it to tmpPackageItemInfos here to avoid creating a new entry.
+ tmpPackageItemInfos.put(packageItem.packageName, packageItem);
+
+ Iterator<WidgetItem> widgetItemIterator = mWidgetsList.get(packageItem).iterator();
+ while (widgetItemIterator.hasNext()) {
+ WidgetItem nextWidget = widgetItemIterator.next();
+ if (nextWidget.componentName.getPackageName().equals(packageUser.mPackageName)
+ && nextWidget.user.equals(packageUser.mUser)) {
+ widgetItemIterator.remove();
+ }
+ }
+ }
+ }
+
+ InvariantDeviceProfile idp = app.getInvariantDeviceProfile();
+ UserHandle myUser = Process.myUserHandle();
+
+ // add and update.
+ for (WidgetItem item : rawWidgetsShortcuts) {
+ if (item.widgetInfo != null) {
+ if ((item.widgetInfo.getWidgetFeatures() & WIDGET_FEATURE_HIDE_FROM_PICKER) != 0) {
+ // Widget is hidden from picker
+ continue;
+ }
+
+ // Ensure that all widgets we show can be added on a workspace of this size
+ int minSpanX = Math.min(item.widgetInfo.spanX, item.widgetInfo.minSpanX);
+ int minSpanY = Math.min(item.widgetInfo.spanY, item.widgetInfo.minSpanY);
+ if (minSpanX > idp.numColumns || minSpanY > idp.numRows) {
+ if (DEBUG) {
+ Log.d(TAG, String.format(
+ "Widget %s : (%d X %d) can't fit on this device",
+ item.componentName, minSpanX, minSpanY));
+ }
+ continue;
+ }
+ }
+
+ if (mAppFilter == null) {
+ mAppFilter = AppFilter.newInstance(app.getContext());
+ }
+ if (!mAppFilter.shouldShowApp(item.componentName)) {
+ if (DEBUG) {
+ Log.d(TAG, String.format("%s is filtered and not added to the widget tray.",
+ item.componentName));
+ }
+ continue;
+ }
+
+ String packageName = item.componentName.getPackageName();
+ PackageItemInfo pInfo = tmpPackageItemInfos.get(packageName);
+ if (pInfo == null) {
+ pInfo = new PackageItemInfo(packageName);
+ pInfo.user = item.user;
+ tmpPackageItemInfos.put(packageName, pInfo);
+ } else if (!myUser.equals(pInfo.user)) {
+ // Keep updating the user, until we get the primary user.
+ pInfo.user = item.user;
+ }
+ mWidgetsList.addToList(pInfo, item);
+ }
+
+ // Update each package entry
+ IconCache iconCache = app.getIconCache();
+ for (PackageItemInfo p : tmpPackageItemInfos.values()) {
+ iconCache.getTitleAndIconForApp(p, true /* userLowResIcon */);
+ }
+ }
public void onPackageIconsUpdated(Set<String> packageNames, UserHandle user,
LauncherAppState app) {
+ for (Entry<PackageItemInfo, ArrayList<WidgetItem>> entry : mWidgetsList.entrySet()) {
+ if (packageNames.contains(entry.getKey().packageName)) {
+ ArrayList<WidgetItem> items = entry.getValue();
+ int count = items.size();
+ for (int i = 0; i < count; i++) {
+ WidgetItem item = items.get(i);
+ if (item.user.equals(user)) {
+ if (item.activityInfo != null) {
+ items.set(i, new WidgetItem(item.activityInfo, app.getIconCache(),
+ app.getContext().getPackageManager()));
+ } else {
+ items.set(i, new WidgetItem(item.widgetInfo,
+ app.getInvariantDeviceProfile(), app.getIconCache()));
+ }
+ }
+ }
+ }
+ }
}
public WidgetItem getWidgetProviderInfoByProviderName(
ComponentName providerName) {
+ ArrayList<WidgetItem> widgetsList = mWidgetsList.get(
+ new PackageItemInfo(providerName.getPackageName()));
+ if (widgetsList == null) {
+ return null;
+ }
+
+ for (WidgetItem item : widgetsList) {
+ if (item.componentName.equals(providerName)) {
+ return item;
+ }
+ }
return null;
}
}
\ No newline at end of file