From 64a75aa305bdd1ca8f22d2b48dedc5cada8fabc5 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 3 Jul 2017 13:50:52 -0700 Subject: [PATCH] Adding A feature flag to disable widgets and a corresponding build target Launcher3Go without widgets support Bug: 62353159 Change-Id: Ia03d2235a9bcf75f9ef191924f81630e63a2c684 --- Android.mk | 53 ++++++++- build.gradle | 26 ++++- go/AndroidManifest.xml | 53 +++++++++ go/res/layout/widget_cell_content.xml | 66 +++++++++++ go/res/values/strings.xml | 33 ++++++ .../launcher3/config/FeatureFlags.java | 68 +++++++++++ .../launcher3/AppWidgetsRestoredReceiver.java | 18 +-- src/com/android/launcher3/BaseActivity.java | 6 + src/com/android/launcher3/Launcher.java | 9 +- .../launcher3/LauncherAppWidgetHost.java | 109 +++++++++++++++--- src/com/android/launcher3/LauncherModel.java | 3 +- .../android/launcher3/LauncherProvider.java | 2 +- src/com/android/launcher3/Workspace.java | 10 +- .../compat/AppWidgetManagerCompat.java | 6 - .../compat/AppWidgetManagerCompatVL.java | 33 +++--- .../compat/AppWidgetManagerCompatVO.java | 5 + .../launcher3/dragndrop/AddItemActivity.java | 28 ++--- .../android/launcher3/model/LoaderTask.java | 5 + .../launcher3/qsb/QsbContainerView.java | 9 +- .../widget/WidgetAddFlowHandler.java | 18 +-- .../launcher3/config/FeatureFlags.java | 7 +- .../launcher3/ui/widget/BindWidgetTest.java | 3 +- 22 files changed, 473 insertions(+), 97 deletions(-) create mode 100644 go/AndroidManifest.xml create mode 100644 go/res/layout/widget_cell_content.xml create mode 100644 go/res/values/strings.xml create mode 100644 go/src_flags/com/android/launcher3/config/FeatureFlags.java diff --git a/Android.mk b/Android.mk index 0543b42445..d41e184f0a 100644 --- a/Android.mk +++ b/Android.mk @@ -17,7 +17,7 @@ LOCAL_PATH := $(call my-dir) # -# Build app code. +# Build rule for Launcher3 app. # include $(CLEAR_VARS) @@ -62,6 +62,57 @@ LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.launcher3.* include $(BUILD_PACKAGE) +# +# Build rule for Launcher3 Go app for Android Go devices. +# +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_STATIC_JAVA_LIBRARIES := \ + android-support-v4 \ + android-support-v7-recyclerview \ + android-support-v7-palette \ + android-support-dynamic-animation + +LOCAL_SRC_FILES := \ + $(call all-java-files-under, src) \ + $(call all-java-files-under, src_config) \ + $(call all-java-files-under, go/src_flags) \ + $(call all-proto-files-under, protos) \ + $(call all-proto-files-under, proto_overrides) + +LOCAL_RESOURCE_DIR := \ + $(LOCAL_PATH)/go/res \ + $(LOCAL_PATH)/res \ + prebuilts/sdk/current/support/v7/recyclerview/res \ + +LOCAL_PROGUARD_FLAG_FILES := proguard.flags + +LOCAL_PROTOC_OPTIMIZE_TYPE := nano +LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/protos/ --proto_path=$(LOCAL_PATH)/proto_overrides/ +LOCAL_PROTO_JAVA_OUTPUT_PARAMS := enum_style=java + +LOCAL_AAPT_FLAGS := \ + --auto-add-overlay \ + --extra-packages android.support.v7.recyclerview \ + +LOCAL_SDK_VERSION := current +LOCAL_MIN_SDK_VERSION := 21 +LOCAL_PACKAGE_NAME := Launcher3Go +LOCAL_PRIVILEGED_MODULE := true +LOCAL_OVERRIDES_PACKAGES := Home Launcher2 Launcher3 + +LOCAL_FULL_LIBS_MANIFEST_FILES := \ + $(LOCAL_PATH)/AndroidManifest.xml \ + $(LOCAL_PATH)/AndroidManifest-common.xml + +LOCAL_MANIFEST_FILE := go/AndroidManifest.xml + +LOCAL_JACK_COVERAGE_INCLUDE_FILTER := com.android.launcher3.* + +include $(BUILD_PACKAGE) + # # Launcher proto buffer jar used for development # diff --git a/build.gradle b/build.gradle index 79ee111f5d..886ccace68 100644 --- a/build.gradle +++ b/build.gradle @@ -35,11 +35,16 @@ android { applicationId 'com.android.launcher3' testApplicationId 'com.android.launcher3.tests' } + + l3go { + applicationId 'com.android.launcher3' + testApplicationId 'com.android.launcher3.tests' + } } sourceSets { main { res.srcDirs = ['res'] - java.srcDirs = ['src', 'src_flags'] + java.srcDirs = ['src'] manifest.srcFile 'AndroidManifest-common.xml' proto { srcDir 'protos/' @@ -48,18 +53,31 @@ android { } androidTest { - java.srcDirs = ['tests/src'] res.srcDirs = ['tests/res'] + java.srcDirs = ['tests/src'] manifest.srcFile "tests/AndroidManifest-common.xml" } aosp { + java.srcDirs = ['src_flags'] manifest.srcFile "AndroidManifest.xml" } aospAndroidTest { manifest.srcFile "tests/AndroidManifest.xml" } + + l3go { + res.srcDirs = ['go/res'] + java.srcDirs = ['go/src_flags'] + // Note: we are using the Launcher3 manifest here because the gradle manifest-merger uses + // different attributes than the build system. + manifest.srcFile "AndroidManifest.xml" + } + + l3goAndroidTest { + manifest.srcFile "tests/AndroidManifest.xml" + } } } @@ -74,10 +92,10 @@ dependencies { compile "com.android.support:support-dynamic-animation:${SUPPORT_LIBS_VERSION}" compile "com.android.support:recyclerview-v7:${SUPPORT_LIBS_VERSION}" compile "com.android.support:palette-v7:${SUPPORT_LIBS_VERSION}" - compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-2' + compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-7' testCompile 'junit:junit:4.12' - androidTestCompile "org.mockito:mockito-core:1.+" + androidTestCompile "org.mockito:mockito-core:1.9.5" androidTestCompile 'com.google.dexmaker:dexmaker:1.2' androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2' androidTestCompile 'com.android.support.test:runner:0.5' diff --git a/go/AndroidManifest.xml b/go/AndroidManifest.xml new file mode 100644 index 0000000000..ed8e0ad3bc --- /dev/null +++ b/go/AndroidManifest.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + diff --git a/go/res/layout/widget_cell_content.xml b/go/res/layout/widget_cell_content.xml new file mode 100644 index 0000000000..49506d9bec --- /dev/null +++ b/go/res/layout/widget_cell_content.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/go/res/values/strings.xml b/go/res/values/strings.xml new file mode 100644 index 0000000000..8ef2e62430 --- /dev/null +++ b/go/res/values/strings.xml @@ -0,0 +1,33 @@ + + + + + + + Touch & hold to pick up a shortcut. + + Double-tap & hold to pick up a shortcut or use custom actions. + + Shortcuts + + + + %1$s shortcuts + + diff --git a/go/src_flags/com/android/launcher3/config/FeatureFlags.java b/go/src_flags/com/android/launcher3/config/FeatureFlags.java new file mode 100644 index 0000000000..a1b644c422 --- /dev/null +++ b/go/src_flags/com/android/launcher3/config/FeatureFlags.java @@ -0,0 +1,68 @@ +/* + * 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.config; + +/** + * Defines a set of flags used to control various launcher behaviors + */ +public final class FeatureFlags { + + public static final boolean IS_DOGFOOD_BUILD = false; + + private FeatureFlags() {} + + // Custom flags go below this + public static boolean LAUNCHER3_DISABLE_ICON_NORMALIZATION = false; + public static boolean LAUNCHER3_LEGACY_FOLDER_ICON = false; + public static boolean LAUNCHER3_DISABLE_PINCH_TO_OVERVIEW = false; + public static boolean LAUNCHER3_ALL_APPS_PULL_UP = true; + public static boolean LAUNCHER3_NEW_FOLDER_ANIMATION = true; + // When enabled allows to use any point on the fast scrollbar to start dragging. + public static boolean LAUNCHER3_DIRECT_SCROLL = true; + // When enabled while all-apps open, the soft input will be set to adjust resize . + public static boolean LAUNCHER3_UPDATE_SOFT_INPUT_MODE = true; + // When enabled the promise icon is visible in all apps while installation an app. + public static boolean LAUNCHER3_PROMISE_APPS_IN_ALL_APPS = false; + // When enabled uses the AllAppsRadialGradientAndScrimDrawable for all apps + public static boolean LAUNCHER3_GRADIENT_ALL_APPS = true; + // When enabled allows use of physics based motions in the Launcher. + public static boolean LAUNCHER3_PHYSICS = true; + // When enabled allows use of spring motions on the icons. + public static boolean LAUNCHER3_SPRING_ICONS = true; + + // Feature flag to enable moving the QSB on the 0th screen of the workspace. + 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 fling down gesture on the first workspace triggers search. + public static final boolean PULLDOWN_SEARCH = false; + // 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 are badged with the number of notifications associated with that app. + public static final boolean BADGE_ICONS = true; + // 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; + + // Features to control Launcher3Go behavior + public static final boolean GO_DISABLE_WIDGETS = true; +} diff --git a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java index 6e33d2a556..b249c95306 100644 --- a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java +++ b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java @@ -13,6 +13,7 @@ import android.support.annotation.WorkerThread; import android.util.Log; import com.android.launcher3.LauncherSettings.Favorites; +import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.LoaderTask; import com.android.launcher3.provider.RestoreDbTask; import com.android.launcher3.util.ContentWriter; @@ -26,7 +27,7 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver { if (AppWidgetManager.ACTION_APPWIDGET_HOST_RESTORED.equals(intent.getAction())) { int hostId = intent.getIntExtra(AppWidgetManager.EXTRA_HOST_ID, 0); Log.d(TAG, "Widget ID map received for host:" + hostId); - if (hostId != Launcher.APPWIDGET_HOST_ID) { + if (hostId != LauncherAppWidgetHost.APPWIDGET_HOST_ID) { return; } @@ -38,7 +39,8 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver { .postAtFrontOfQueue(new Runnable() { @Override public void run() { - restoreAppWidgetIds(context, asyncResult, oldIds, newIds); + restoreAppWidgetIds(context, oldIds, newIds); + asyncResult.finish(); } }); } else { @@ -51,9 +53,13 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver { * Updates the app widgets whose id has changed during the restore process. */ @WorkerThread - static void restoreAppWidgetIds(Context context, PendingResult asyncResult, - int[] oldWidgetIds, int[] newWidgetIds) { - AppWidgetHost appWidgetHost = new AppWidgetHost(context, Launcher.APPWIDGET_HOST_ID); + static void restoreAppWidgetIds(Context context, int[] oldWidgetIds, int[] newWidgetIds) { + AppWidgetHost appWidgetHost = new LauncherAppWidgetHost(context); + if (FeatureFlags.GO_DISABLE_WIDGETS) { + Log.e(TAG, "Skipping widget ID remap as widgets not supported"); + appWidgetHost.deleteHost(); + return; + } if (!RestoreDbTask.isPending(context)) { // Someone has already gone through our DB once, probably LoaderTask. Skip any further // modifications of the DB. @@ -62,7 +68,6 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver { Log.d(TAG, "Deleting widgetId: " + widgetId); appWidgetHost.deleteAppWidgetId(widgetId); } - asyncResult.finish(); return; } final ContentResolver cr = context.getContentResolver(); @@ -106,6 +111,5 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver { if (app != null) { app.getModel().forceReload(); } - asyncResult.finish(); } } diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java index 2b59ede476..e49649502d 100644 --- a/src/com/android/launcher3/BaseActivity.java +++ b/src/com/android/launcher3/BaseActivity.java @@ -19,6 +19,7 @@ package com.android.launcher3; import android.app.Activity; import android.content.Context; import android.content.ContextWrapper; +import android.content.Intent; import android.view.View.AccessibilityDelegate; import com.android.launcher3.logging.UserEventDispatcher; @@ -63,4 +64,9 @@ public abstract class BaseActivity extends Activity { } return mSystemUiController; } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + } } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 7b7177e54e..97f1ead86b 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -209,10 +209,8 @@ public class Launcher extends BaseActivity private boolean mIsSafeModeEnabled; - public static final int APPWIDGET_HOST_ID = 1024; public static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 500; private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500; - private static final int ACTIVITY_START_DELAY = 1000; // How long to wait before the new-shortcut animation automatically pans the workspace private static final int NEW_APPS_PAGE_MOVE_DELAY = 500; @@ -397,7 +395,10 @@ public class Launcher extends BaseActivity mAppWidgetManager = AppWidgetManagerCompat.getInstance(this); - mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID); + mAppWidgetHost = new LauncherAppWidgetHost(this); + if (Utilities.ATLEAST_MARSHMALLOW) { + mAppWidgetHost.addProviderChangeListener(this); + } mAppWidgetHost.startListening(); // If we are getting an onCreate, we can actually preempt onResume and unset mPaused here, @@ -788,7 +789,7 @@ public class Launcher extends BaseActivity } @Override - protected void onActivityResult( + public void onActivityResult( final int requestCode, final int resultCode, final Intent data) { handleActivityResult(requestCode, resultCode, data); if (mLauncherCallbacks != null) { diff --git a/src/com/android/launcher3/LauncherAppWidgetHost.java b/src/com/android/launcher3/LauncherAppWidgetHost.java index 6e8c59b66c..5573c5c151 100644 --- a/src/com/android/launcher3/LauncherAppWidgetHost.java +++ b/src/com/android/launcher3/LauncherAppWidgetHost.java @@ -16,12 +16,20 @@ package com.android.launcher3; +import android.app.Activity; import android.appwidget.AppWidgetHost; import android.appwidget.AppWidgetHostView; +import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; +import android.content.ActivityNotFoundException; import android.content.Context; +import android.content.Intent; +import android.os.Handler; import android.util.SparseArray; import android.view.LayoutInflater; +import android.widget.Toast; + +import com.android.launcher3.config.FeatureFlags; import java.util.ArrayList; @@ -33,14 +41,16 @@ import java.util.ArrayList; */ public class LauncherAppWidgetHost extends AppWidgetHost { - private final ArrayList mProviderChangeListeners = new ArrayList(); + public static final int APPWIDGET_HOST_ID = 1024; + + private final ArrayList mProviderChangeListeners = new ArrayList<>(); private final SparseArray mViews = new SparseArray<>(); - private Launcher mLauncher; + private final Context mContext; - public LauncherAppWidgetHost(Launcher launcher, int hostId) { - super(launcher, hostId); - mLauncher = launcher; + public LauncherAppWidgetHost(Context context) { + super(context, APPWIDGET_HOST_ID); + mContext = context; } @Override @@ -53,6 +63,10 @@ public class LauncherAppWidgetHost extends AppWidgetHost { @Override public void startListening() { + if (FeatureFlags.GO_DISABLE_WIDGETS) { + return; + } + try { super.startListening(); } catch (Exception e) { @@ -66,24 +80,38 @@ public class LauncherAppWidgetHost extends AppWidgetHost { } } - public void addProviderChangeListener(Runnable callback) { + @Override + public void stopListening() { + if (FeatureFlags.GO_DISABLE_WIDGETS) { + return; + } + + super.stopListening(); + } + + @Override + public int allocateAppWidgetId() { + if (FeatureFlags.GO_DISABLE_WIDGETS) { + return AppWidgetManager.INVALID_APPWIDGET_ID; + } + + return super.allocateAppWidgetId(); + } + + public void addProviderChangeListener(ProviderChangedListener callback) { mProviderChangeListeners.add(callback); } - public void removeProviderChangeListener(Runnable callback) { + public void removeProviderChangeListener(ProviderChangedListener callback) { mProviderChangeListeners.remove(callback); } protected void onProvidersChanged() { if (!mProviderChangeListeners.isEmpty()) { - for (Runnable callback : new ArrayList<>(mProviderChangeListeners)) { - callback.run(); + for (ProviderChangedListener callback : new ArrayList<>(mProviderChangeListeners)) { + callback.notifyWidgetProvidersChanged(); } } - - if (Utilities.ATLEAST_MARSHMALLOW) { - mLauncher.notifyWidgetProvidersChanged(); - } } public AppWidgetHostView createView(Context context, int appWidgetId, @@ -109,7 +137,7 @@ public class LauncherAppWidgetHost extends AppWidgetHost { // will update. LauncherAppWidgetHostView view = mViews.get(appWidgetId); if (view == null) { - view = onCreateView(mLauncher, appWidgetId, appWidget); + view = onCreateView(mContext, appWidgetId, appWidget); } view.setAppWidget(appWidgetId, appWidget); view.switchToErrorView(); @@ -124,11 +152,11 @@ public class LauncherAppWidgetHost extends AppWidgetHost { @Override protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidget) { LauncherAppWidgetProviderInfo info = LauncherAppWidgetProviderInfo.fromProviderInfo( - mLauncher, appWidget); + mContext, appWidget); super.onProviderChanged(appWidgetId, info); // The super method updates the dimensions of the providerInfo. Update the // launcher spans accordingly. - info.initSpans(mLauncher); + info.initSpans(mContext); } @Override @@ -142,4 +170,53 @@ public class LauncherAppWidgetHost extends AppWidgetHost { super.clearViews(); mViews.clear(); } + + public void startBindFlow(BaseActivity activity, + int appWidgetId, AppWidgetProviderInfo info, int requestCode) { + + if (FeatureFlags.GO_DISABLE_WIDGETS) { + sendActionCancelled(activity, requestCode); + return; + } + + Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND) + .putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) + .putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.provider) + .putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE, info.getProfile()); + // TODO: we need to make sure that this accounts for the options bundle. + // intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options); + activity.startActivityForResult(intent, requestCode); + } + + + public void startConfigActivity(BaseActivity activity, int widgetId, int requestCode) { + if (FeatureFlags.GO_DISABLE_WIDGETS) { + sendActionCancelled(activity, requestCode); + return; + } + + try { + startAppWidgetConfigureActivityForResult(activity, widgetId, 0, requestCode, null); + } catch (ActivityNotFoundException | SecurityException e) { + Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); + sendActionCancelled(activity, requestCode); + } + } + + private void sendActionCancelled(final BaseActivity activity, final int requestCode) { + new Handler().post(new Runnable() { + @Override + public void run() { + activity.onActivityResult(requestCode, Activity.RESULT_CANCELED, null); + } + }); + } + + /** + * Listener for getting notifications on provider changes. + */ + public interface ProviderChangedListener { + + void notifyWidgetProvidersChanged(); + } } diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 82bee0e4c6..f1638fda25 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -133,7 +133,7 @@ public class LauncherModel extends BroadcastReceiver } }; - public interface Callbacks { + public interface Callbacks extends LauncherAppWidgetHost.ProviderChangedListener { public boolean setLoadOnResume(); public int getCurrentWorkspaceScreen(); public void clearPendingBinds(); @@ -159,7 +159,6 @@ public class LauncherModel extends BroadcastReceiver HashSet packageNames, HashSet components, UserHandle user); public void bindAppInfosRemoved(ArrayList appInfos); - public void notifyWidgetProvidersChanged(); public void bindAllWidgets(MultiHashMap widgets); public void onPageBoundSynchronously(int page); public void executeOnNextDraw(ViewOnDrawExecutor executor); diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java index 4813571f54..dc83f36adf 100644 --- a/src/com/android/launcher3/LauncherProvider.java +++ b/src/com/android/launcher3/LauncherProvider.java @@ -1031,7 +1031,7 @@ public class LauncherProvider extends ContentProvider { } public AppWidgetHost newLauncherWidgetHost() { - return new AppWidgetHost(mContext, Launcher.APPWIDGET_HOST_ID); + return new LauncherAppWidgetHost(mContext); } @Override diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index f781a3d1de..a2270d6c57 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -52,8 +52,10 @@ import android.view.accessibility.AccessibilityManager; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import android.widget.Toast; + import com.android.launcher3.Launcher.CustomContentCallbacks; import com.android.launcher3.Launcher.LauncherOverlay; +import com.android.launcher3.LauncherAppWidgetHost.ProviderChangedListener; import com.android.launcher3.UninstallDropTarget.DropTargetSource; import com.android.launcher3.accessibility.AccessibleDragListenerAdapter; import com.android.launcher3.accessibility.OverviewAccessibilityDelegate; @@ -86,6 +88,7 @@ import com.android.launcher3.util.VerticalFlingDetector; import com.android.launcher3.util.WallpaperOffsetInterpolator; import com.android.launcher3.widget.PendingAddShortcutInfo; import com.android.launcher3.widget.PendingAddWidgetInfo; + import java.util.ArrayList; import java.util.HashSet; import java.util.Set; @@ -4079,7 +4082,7 @@ public class Workspace extends PagedView * Used as a workaround to ensure that the AppWidgetService receives the * PACKAGE_ADDED broadcast before updating widgets. */ - private class DeferredWidgetRefresh implements Runnable { + private class DeferredWidgetRefresh implements Runnable, ProviderChangedListener { private final ArrayList mInfos; private final LauncherAppWidgetHost mHost; private final Handler mHandler; @@ -4122,6 +4125,11 @@ public class Workspace extends PagedView } }); } + + @Override + public void notifyWidgetProvidersChanged() { + run(); + } } private class StateTransitionListener extends AnimatorListenerAdapter diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompat.java b/src/com/android/launcher3/compat/AppWidgetManagerCompat.java index 3efbbfba5d..4e00eae9d6 100644 --- a/src/com/android/launcher3/compat/AppWidgetManagerCompat.java +++ b/src/com/android/launcher3/compat/AppWidgetManagerCompat.java @@ -16,15 +16,12 @@ package com.android.launcher3.compat; -import android.app.Activity; -import android.appwidget.AppWidgetHost; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; import android.content.ComponentName; import android.content.Context; import android.os.Bundle; import android.os.UserHandle; -import android.support.annotation.NonNull; import android.support.annotation.Nullable; import com.android.launcher3.LauncherAppWidgetProviderInfo; @@ -76,9 +73,6 @@ public abstract class AppWidgetManagerCompat { public abstract boolean bindAppWidgetIdIfAllowed( int appWidgetId, AppWidgetProviderInfo info, Bundle options); - public abstract void startConfigActivity(AppWidgetProviderInfo info, int widgetId, - Activity activity, AppWidgetHost host, int requestCode); - public abstract LauncherAppWidgetProviderInfo findProvider( ComponentName provider, UserHandle user); diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java b/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java index f239f5c319..cb3bd6c7d6 100644 --- a/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java +++ b/src/com/android/launcher3/compat/AppWidgetManagerCompatVL.java @@ -16,24 +16,21 @@ package com.android.launcher3.compat; -import android.app.Activity; -import android.appwidget.AppWidgetHost; import android.appwidget.AppWidgetProviderInfo; -import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; import android.support.annotation.Nullable; -import android.widget.Toast; import com.android.launcher3.LauncherAppWidgetProviderInfo; -import com.android.launcher3.R; +import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.PackageUserKey; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -49,6 +46,9 @@ class AppWidgetManagerCompatVL extends AppWidgetManagerCompat { @Override public List getAllProviders(@Nullable PackageUserKey packageUser) { + if (FeatureFlags.GO_DISABLE_WIDGETS) { + return Collections.emptyList(); + } if (packageUser == null) { ArrayList providers = new ArrayList(); for (UserHandle user : mUserManager.getUserProfiles()) { @@ -71,24 +71,20 @@ class AppWidgetManagerCompatVL extends AppWidgetManagerCompat { @Override public boolean bindAppWidgetIdIfAllowed(int appWidgetId, AppWidgetProviderInfo info, Bundle options) { + if (FeatureFlags.GO_DISABLE_WIDGETS) { + return false; + } return mAppWidgetManager.bindAppWidgetIdIfAllowed( appWidgetId, info.getProfile(), info.provider, options); } - @Override - public void startConfigActivity(AppWidgetProviderInfo info, int widgetId, Activity activity, - AppWidgetHost host, int requestCode) { - try { - host.startAppWidgetConfigureActivityForResult(activity, widgetId, 0, requestCode, null); - } catch (ActivityNotFoundException | SecurityException e) { - Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show(); - } - } - @Override public LauncherAppWidgetProviderInfo findProvider(ComponentName provider, UserHandle user) { - for (AppWidgetProviderInfo info : mAppWidgetManager - .getInstalledProvidersForProfile(user)) { + if (FeatureFlags.GO_DISABLE_WIDGETS) { + return null; + } + for (AppWidgetProviderInfo info : + getAllProviders(new PackageUserKey(provider.getPackageName(), user))) { if (info.provider.equals(provider)) { return LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, info); } @@ -99,6 +95,9 @@ class AppWidgetManagerCompatVL extends AppWidgetManagerCompat { @Override public HashMap getAllProvidersMap() { HashMap result = new HashMap<>(); + if (FeatureFlags.GO_DISABLE_WIDGETS) { + return result; + } for (UserHandle user : mUserManager.getUserProfiles()) { for (AppWidgetProviderInfo info : mAppWidgetManager.getInstalledProvidersForProfile(user)) { diff --git a/src/com/android/launcher3/compat/AppWidgetManagerCompatVO.java b/src/com/android/launcher3/compat/AppWidgetManagerCompatVO.java index 1c48a13bda..44158edbf1 100644 --- a/src/com/android/launcher3/compat/AppWidgetManagerCompatVO.java +++ b/src/com/android/launcher3/compat/AppWidgetManagerCompatVO.java @@ -20,8 +20,10 @@ import android.appwidget.AppWidgetProviderInfo; import android.content.Context; import android.support.annotation.Nullable; +import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.util.PackageUserKey; +import java.util.Collections; import java.util.List; class AppWidgetManagerCompatVO extends AppWidgetManagerCompatVL { @@ -32,6 +34,9 @@ class AppWidgetManagerCompatVO extends AppWidgetManagerCompatVL { @Override public List getAllProviders(@Nullable PackageUserKey packageUser) { + if (FeatureFlags.GO_DISABLE_WIDGETS) { + return Collections.emptyList(); + } if (packageUser == null) { return super.getAllProviders(null); } diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java index 01893bdafa..c843e72665 100644 --- a/src/com/android/launcher3/dragndrop/AddItemActivity.java +++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java @@ -16,14 +16,8 @@ package com.android.launcher3.dragndrop; -import static com.android.launcher3.logging.LoggerUtils.newCommandAction; -import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; -import static com.android.launcher3.logging.LoggerUtils.newItemTarget; -import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent; - import android.annotation.TargetApi; import android.app.ActivityOptions; -import android.appwidget.AppWidgetHost; import android.appwidget.AppWidgetManager; import android.content.ClipData; import android.content.ClipDescription; @@ -45,8 +39,8 @@ import android.view.View.OnTouchListener; import com.android.launcher3.BaseActivity; import com.android.launcher3.InstallShortcutReceiver; import com.android.launcher3.InvariantDeviceProfile; -import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppState; +import com.android.launcher3.LauncherAppWidgetHost; import com.android.launcher3.LauncherAppWidgetProviderInfo; import com.android.launcher3.R; import com.android.launcher3.Utilities; @@ -61,6 +55,11 @@ import com.android.launcher3.widget.PendingAddWidgetInfo; import com.android.launcher3.widget.WidgetHostViewLoader; import com.android.launcher3.widget.WidgetImageView; +import static com.android.launcher3.logging.LoggerUtils.newCommandAction; +import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; +import static com.android.launcher3.logging.LoggerUtils.newItemTarget; +import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent; + @TargetApi(Build.VERSION_CODES.O) public class AddItemActivity extends BaseActivity implements OnLongClickListener, OnTouchListener { @@ -78,7 +77,7 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener private LivePreviewWidgetCell mWidgetCell; // Widget request specific options. - private AppWidgetHost mAppWidgetHost; + private LauncherAppWidgetHost mAppWidgetHost; private AppWidgetManagerCompat mAppWidgetManager; private PendingAddWidgetInfo mPendingWidgetInfo; private int mPendingBindWidgetId; @@ -212,7 +211,7 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener mWidgetCell.setPreview(PinItemDragListener.getPreview(mRequest)); mAppWidgetManager = AppWidgetManagerCompat.getInstance(this); - mAppWidgetHost = new AppWidgetHost(this, Launcher.APPWIDGET_HOST_ID); + mAppWidgetHost = new LauncherAppWidgetHost(this); mPendingWidgetInfo = new PendingAddWidgetInfo(widgetInfo); mPendingWidgetInfo.spanX = Math.min(mIdp.numColumns, widgetInfo.spanX); @@ -256,13 +255,8 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener } // request bind widget - Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND); - intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mPendingBindWidgetId); - intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, - mPendingWidgetInfo.componentName); - intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE, - mRequest.getAppWidgetProviderInfo(this).getProfile()); - startActivityForResult(intent, REQUEST_BIND_APPWIDGET); + mAppWidgetHost.startBindFlow(this, mPendingBindWidgetId, + mRequest.getAppWidgetProviderInfo(this), REQUEST_BIND_APPWIDGET); } private void acceptWidget(int widgetId) { @@ -280,7 +274,7 @@ public class AddItemActivity extends BaseActivity implements OnLongClickListener } @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { + public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_BIND_APPWIDGET) { int widgetId = data != null ? data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mPendingBindWidgetId) diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 5bad436f8d..c56325ad5b 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -548,6 +548,11 @@ public class LoaderTask implements Runnable { break; case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: + if (FeatureFlags.GO_DISABLE_WIDGETS) { + c.markDeleted("Only legacy shortcuts can have null package"); + continue; + } + // Follow through case LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET: // Read all Launcher-specific widget details boolean customWidget = c.itemType == diff --git a/src/com/android/launcher3/qsb/QsbContainerView.java b/src/com/android/launcher3/qsb/QsbContainerView.java index 4dc3c1c0da..d26f9f6463 100644 --- a/src/com/android/launcher3/qsb/QsbContainerView.java +++ b/src/com/android/launcher3/qsb/QsbContainerView.java @@ -39,12 +39,14 @@ import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; import com.android.launcher3.Utilities; -import com.android.launcher3.compat.AppWidgetManagerCompat; import com.android.launcher3.config.FeatureFlags; /** * A frame layout which contains a QSB. This internally uses fragment to bind the view, which * allows it to contain the logic for {@link Fragment#startActivityForResult(Intent, int)}. + * + * Note: AppWidgetManagerCompat can be disabled using FeatureFlags. In QSB, we should use + * AppWidgetManager directly, so that it keeps working in that case. */ public class QsbContainerView extends FrameLayout { @@ -106,7 +108,7 @@ public class QsbContainerView extends FrameLayout { return QsbWidgetHostView.getDefaultView(container); } - AppWidgetManagerCompat widgetManager = AppWidgetManagerCompat.getInstance(activity); + AppWidgetManager widgetManager = AppWidgetManager.getInstance(activity); InvariantDeviceProfile idp = LauncherAppState.getIDP(activity); Bundle opts = new Bundle(); @@ -129,7 +131,8 @@ public class QsbContainerView extends FrameLayout { } widgetId = mQsbWidgetHost.allocateAppWidgetId(); - isWidgetBound = widgetManager.bindAppWidgetIdIfAllowed(widgetId, mWidgetInfo, opts); + isWidgetBound = widgetManager.bindAppWidgetIdIfAllowed( + widgetId, mWidgetInfo.getProfile(), mWidgetInfo.provider, opts); if (!isWidgetBound) { mQsbWidgetHost.deleteAppWidgetId(widgetId); widgetId = -1; diff --git a/src/com/android/launcher3/widget/WidgetAddFlowHandler.java b/src/com/android/launcher3/widget/WidgetAddFlowHandler.java index 629f30c262..5387be8392 100644 --- a/src/com/android/launcher3/widget/WidgetAddFlowHandler.java +++ b/src/com/android/launcher3/widget/WidgetAddFlowHandler.java @@ -15,10 +15,8 @@ */ package com.android.launcher3.widget; -import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; import android.content.Context; -import android.content.Intent; import android.os.Parcel; import android.os.Parcelable; @@ -26,7 +24,6 @@ import com.android.launcher3.ItemInfo; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppWidgetInfo; import com.android.launcher3.LauncherAppWidgetProviderInfo; -import com.android.launcher3.compat.AppWidgetManagerCompat; import com.android.launcher3.util.PendingRequestArgs; /** @@ -56,15 +53,8 @@ public class WidgetAddFlowHandler implements Parcelable { public void startBindFlow(Launcher launcher, int appWidgetId, ItemInfo info, int requestCode) { launcher.setWaitingForResult(PendingRequestArgs.forWidgetInfo(appWidgetId, this, info)); - - Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND); - intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); - intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, mProviderInfo.provider); - intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE, - mProviderInfo.getProfile()); - // TODO: we need to make sure that this accounts for the options bundle. - // intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options); - launcher.startActivityForResult(intent, requestCode); + launcher.getAppWidgetHost() + .startBindFlow(launcher, appWidgetId, mProviderInfo, requestCode); } /** @@ -85,9 +75,7 @@ public class WidgetAddFlowHandler implements Parcelable { return false; } launcher.setWaitingForResult(PendingRequestArgs.forWidgetInfo(appWidgetId, this, info)); - - AppWidgetManagerCompat.getInstance(launcher).startConfigActivity( - mProviderInfo, appWidgetId, launcher, launcher.getAppWidgetHost(), requestCode); + launcher.getAppWidgetHost().startConfigActivity(launcher, appWidgetId, requestCode); return true; } diff --git a/src_flags/com/android/launcher3/config/FeatureFlags.java b/src_flags/com/android/launcher3/config/FeatureFlags.java index 42a110cfe0..69840edd5e 100644 --- a/src_flags/com/android/launcher3/config/FeatureFlags.java +++ b/src_flags/com/android/launcher3/config/FeatureFlags.java @@ -21,14 +21,13 @@ package com.android.launcher3.config; */ public final class FeatureFlags { - public static final boolean IS_DOGFOOD_BUILD = true; + public static final boolean IS_DOGFOOD_BUILD = false; private FeatureFlags() {} // Custom flags go below this public static boolean LAUNCHER3_DISABLE_ICON_NORMALIZATION = false; public static boolean LAUNCHER3_LEGACY_FOLDER_ICON = false; - public static boolean LAUNCHER3_USE_SYSTEM_DRAG_DRIVER = true; public static boolean LAUNCHER3_DISABLE_PINCH_TO_OVERVIEW = false; public static boolean LAUNCHER3_ALL_APPS_PULL_UP = true; public static boolean LAUNCHER3_NEW_FOLDER_ANIMATION = true; @@ -63,4 +62,8 @@ public final class FeatureFlags { 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; + + // Features to control Launcher3Go behavior + public static final boolean GO_DISABLE_WIDGETS = false; + } diff --git a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java index 97f7b505a1..221fed1fc5 100644 --- a/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java +++ b/tests/src/com/android/launcher3/ui/widget/BindWidgetTest.java @@ -28,6 +28,7 @@ import android.support.test.uiautomator.UiSelector; import android.test.suitebuilder.annotation.LargeTest; import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherAppWidgetHost; import com.android.launcher3.LauncherAppWidgetHostView; import com.android.launcher3.LauncherAppWidgetInfo; import com.android.launcher3.LauncherAppWidgetProviderInfo; @@ -285,7 +286,7 @@ public class BindWidgetTest extends LauncherInstrumentationTestCase { pendingInfo.minSpanY = item.minSpanY; Bundle options = WidgetHostViewLoader.getDefaultOptionsForWidget(mTargetContext, pendingInfo); - AppWidgetHost host = new AppWidgetHost(mTargetContext, Launcher.APPWIDGET_HOST_ID); + AppWidgetHost host = new LauncherAppWidgetHost(mTargetContext); int widgetId = host.allocateAppWidgetId(); if (!mWidgetManager.bindAppWidgetIdIfAllowed(widgetId, info, options)) { host.deleteAppWidgetId(widgetId);