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.java20
-rw-r--r--src/com/android/launcher3/AppFilter.java6
-rw-r--r--src/com/android/launcher3/BaseActivity.java20
-rw-r--r--src/com/android/launcher3/BaseDraggingActivity.java16
-rw-r--r--src/com/android/launcher3/FastBitmapDrawable.java15
-rw-r--r--src/com/android/launcher3/IconCache.java19
-rw-r--r--src/com/android/launcher3/IconProvider.java6
-rw-r--r--src/com/android/launcher3/InstallShortcutReceiver.java12
-rw-r--r--src/com/android/launcher3/InvariantDeviceProfile.java12
-rw-r--r--src/com/android/launcher3/Launcher.java20
-rw-r--r--src/com/android/launcher3/LauncherAppState.java38
-rw-r--r--src/com/android/launcher3/LauncherAppTransitionManager.java6
-rw-r--r--src/com/android/launcher3/LauncherModel.java15
-rw-r--r--src/com/android/launcher3/LauncherScroller.java536
-rw-r--r--src/com/android/launcher3/MainProcessInitializer.java5
-rw-r--r--src/com/android/launcher3/OverviewButtonClickListener.java51
-rw-r--r--src/com/android/launcher3/SettingsActivity.java23
-rw-r--r--src/com/android/launcher3/Utilities.java24
-rw-r--r--src/com/android/launcher3/Workspace.java12
-rw-r--r--src/com/android/launcher3/allapps/DiscoveryBounce.java12
-rw-r--r--src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java2
-rw-r--r--src/com/android/launcher3/compat/AccessibilityManagerCompat.java18
-rw-r--r--src/com/android/launcher3/compat/UserManagerCompat.java2
-rw-r--r--src/com/android/launcher3/compat/UserManagerCompatVL.java10
-rw-r--r--src/com/android/launcher3/dragndrop/BaseItemDragListener.java8
-rw-r--r--src/com/android/launcher3/dragndrop/DragController.java3
-rw-r--r--src/com/android/launcher3/folder/Folder.java19
-rw-r--r--src/com/android/launcher3/folder/FolderIcon.java7
-rw-r--r--src/com/android/launcher3/graphics/BitmapRenderer.java54
-rw-r--r--src/com/android/launcher3/graphics/DrawableFactory.java5
-rw-r--r--src/com/android/launcher3/logging/LoggerUtils.java2
-rw-r--r--src/com/android/launcher3/logging/UserEventDispatcher.java20
-rw-r--r--src/com/android/launcher3/model/LoaderTask.java14
-rw-r--r--src/com/android/launcher3/notification/NotificationListener.java2
-rw-r--r--src/com/android/launcher3/popup/ArrowPopup.java28
-rw-r--r--src/com/android/launcher3/popup/PopupContainerWithArrow.java13
-rw-r--r--src/com/android/launcher3/shortcuts/DeepShortcutView.java2
-rw-r--r--src/com/android/launcher3/touch/AbstractStateChangeTouchController.java3
-rw-r--r--src/com/android/launcher3/touch/ItemClickHandler.java2
-rw-r--r--src/com/android/launcher3/util/FloatRange.java39
-rw-r--r--src/com/android/launcher3/util/InstantAppResolver.java5
-rw-r--r--src/com/android/launcher3/util/ItemInfoMatcher.java84
-rw-r--r--src/com/android/launcher3/util/MainThreadInitializedObject.java60
-rw-r--r--src/com/android/launcher3/util/Provider.java13
-rw-r--r--src/com/android/launcher3/util/ResourceBasedOverride.java54
-rw-r--r--src/com/android/launcher3/views/ActivityContext.java43
-rw-r--r--src/com/android/launcher3/views/BaseDragLayer.java7
-rw-r--r--src/com/android/launcher3/views/OptionsPopupView.java8
-rw-r--r--src/com/android/launcher3/widget/WidgetsFullSheet.java6
49 files changed, 470 insertions, 931 deletions
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index daf20323d..322383778 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -34,6 +34,7 @@ import android.widget.LinearLayout;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
import com.android.launcher3.util.TouchController;
+import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
import java.lang.annotation.Retention;
@@ -84,7 +85,8 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
// Usually we show the back button when a floating view is open. Instead, hide for these types.
public static final int TYPE_HIDE_BACK_BUTTON = TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE;
- public static final int TYPE_ACCESSIBLE = TYPE_ALL & ~TYPE_DISCOVERY_BOUNCE;
+ public static final int TYPE_ACCESSIBLE = TYPE_ALL
+ & ~TYPE_DISCOVERY_BOUNCE & ~TYPE_QUICKSTEP_PREVIEW;
protected boolean mIsOpen;
@@ -151,7 +153,7 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
if (mIsOpen) {
sendAccessibilityEvent(TYPE_VIEW_FOCUSED);
}
- BaseDraggingActivity.fromContext(getContext()).getDragLayer()
+ ActivityContext.lookupContext(getContext()).getDragLayer()
.sendAccessibilityEvent(TYPE_WINDOW_CONTENT_CHANGED);
}
@@ -160,7 +162,7 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
}
protected static <T extends AbstractFloatingView> T getOpenView(
- BaseDraggingActivity activity, @FloatingViewType int type) {
+ ActivityContext activity, @FloatingViewType int type) {
BaseDragLayer dragLayer = activity.getDragLayer();
// Iterate in reverse order. AbstractFloatingView is added later to the dragLayer,
// and will be one of the last views.
@@ -176,7 +178,7 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
return null;
}
- public static void closeOpenContainer(BaseDraggingActivity activity,
+ public static void closeOpenContainer(ActivityContext activity,
@FloatingViewType int type) {
AbstractFloatingView view = getOpenView(activity, type);
if (view != null) {
@@ -184,7 +186,7 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
}
}
- public static void closeOpenViews(BaseDraggingActivity activity, boolean animate,
+ public static void closeOpenViews(ActivityContext activity, boolean animate,
@FloatingViewType int type) {
BaseDragLayer dragLayer = activity.getDragLayer();
// Iterate in reverse order. AbstractFloatingView is added later to the dragLayer,
@@ -200,20 +202,20 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
}
}
- public static void closeAllOpenViews(BaseDraggingActivity activity, boolean animate) {
+ public static void closeAllOpenViews(ActivityContext activity, boolean animate) {
closeOpenViews(activity, animate, TYPE_ALL);
activity.finishAutoCancelActionMode();
}
- public static void closeAllOpenViews(BaseDraggingActivity activity) {
+ public static void closeAllOpenViews(ActivityContext activity) {
closeAllOpenViews(activity, true);
}
- public static AbstractFloatingView getTopOpenView(BaseDraggingActivity activity) {
+ public static AbstractFloatingView getTopOpenView(ActivityContext activity) {
return getTopOpenViewWithType(activity, TYPE_ALL);
}
- public static AbstractFloatingView getTopOpenViewWithType(BaseDraggingActivity activity,
+ public static AbstractFloatingView getTopOpenViewWithType(ActivityContext activity,
@FloatingViewType int type) {
return getOpenView(activity, type);
}
diff --git a/src/com/android/launcher3/AppFilter.java b/src/com/android/launcher3/AppFilter.java
index 923835a67..9b6166ffc 100644
--- a/src/com/android/launcher3/AppFilter.java
+++ b/src/com/android/launcher3/AppFilter.java
@@ -3,10 +3,12 @@ package com.android.launcher3;
import android.content.ComponentName;
import android.content.Context;
-public class AppFilter {
+import com.android.launcher3.util.ResourceBasedOverride;
+
+public class AppFilter implements ResourceBasedOverride {
public static AppFilter newInstance(Context context) {
- return Utilities.getOverrideObject(AppFilter.class, context, R.string.app_filter_class);
+ return Overrides.getObject(AppFilter.class, context, R.string.app_filter_class);
}
public boolean shouldShowApp(ComponentName app) {
diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java
index a4b6f5b05..6c82e6385 100644
--- a/src/com/android/launcher3/BaseActivity.java
+++ b/src/com/android/launcher3/BaseActivity.java
@@ -26,6 +26,7 @@ import android.content.ContextWrapper;
import android.content.Intent;
import android.content.res.Configuration;
import android.support.annotation.IntDef;
+import android.view.ContextThemeWrapper;
import android.view.View.AccessibilityDelegate;
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
@@ -107,7 +108,7 @@ public abstract class BaseActivity extends Activity implements UserEventDelegate
public final UserEventDispatcher getUserEventDispatcher() {
if (mUserEventDispatcher == null) {
- mUserEventDispatcher = UserEventDispatcher.newInstance(this, mDeviceProfile, this);
+ mUserEventDispatcher = UserEventDispatcher.newInstance(this, this);
}
return mUserEventDispatcher;
}
@@ -116,13 +117,6 @@ public abstract class BaseActivity extends Activity implements UserEventDelegate
return Utilities.ATLEAST_NOUGAT && isInMultiWindowMode();
}
- public static BaseActivity fromContext(Context context) {
- if (context instanceof BaseActivity) {
- return (BaseActivity) context;
- }
- return ((BaseActivity) ((ContextWrapper) context).getBaseContext());
- }
-
public SystemUiController getSystemUiController() {
if (mSystemUiController == null) {
mSystemUiController = new SystemUiController(getWindow());
@@ -259,4 +253,14 @@ public abstract class BaseActivity extends Activity implements UserEventDelegate
writer.println(" mActivityFlags: " + mActivityFlags);
writer.println(" mForceInvisible: " + mForceInvisible);
}
+
+ public static <T extends BaseActivity> T fromContext(Context context) {
+ if (context instanceof BaseActivity) {
+ return (T) context;
+ } else if (context instanceof ContextThemeWrapper) {
+ return fromContext(((ContextWrapper) context).getBaseContext());
+ } else {
+ throw new IllegalArgumentException("Cannot find BaseActivity in parent tree");
+ }
+ }
}
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index eec196e1e..d6635dc13 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -18,8 +18,6 @@ package com.android.launcher3;
import android.app.ActivityOptions;
import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.ContextWrapper;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
@@ -28,23 +26,23 @@ import android.os.StrictMode;
import android.os.UserHandle;
import android.util.Log;
import android.view.ActionMode;
-import android.view.Surface;
import android.view.View;
import android.widget.Toast;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.badge.BadgeInfo;
import com.android.launcher3.compat.LauncherAppsCompat;
+import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.uioverrides.DisplayRotationListener;
import com.android.launcher3.uioverrides.WallpaperColorInfo;
-import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.views.BaseDragLayer;
+import com.android.launcher3.views.ActivityContext;
/**
* Extension of BaseActivity allowing support for drag-n-drop
*/
public abstract class BaseDraggingActivity extends BaseActivity
- implements WallpaperColorInfo.OnChangeListener {
+ implements WallpaperColorInfo.OnChangeListener, ActivityContext {
private static final String TAG = "BaseDraggingActivity";
@@ -110,6 +108,7 @@ public abstract class BaseDraggingActivity extends BaseActivity
mCurrentActionMode = null;
}
+ @Override
public boolean finishAutoCancelActionMode() {
if (mCurrentActionMode != null && AUTO_CANCEL_ACTION_MODE == mCurrentActionMode.getTag()) {
mCurrentActionMode.finish();
@@ -128,13 +127,6 @@ public abstract class BaseDraggingActivity extends BaseActivity
public abstract void invalidateParent(ItemInfo info);
- public static BaseDraggingActivity fromContext(Context context) {
- if (context instanceof BaseDraggingActivity) {
- return (BaseDraggingActivity) context;
- }
- return ((BaseDraggingActivity) ((ContextWrapper) context).getBaseContext());
- }
-
public Rect getViewBounds(View v) {
int[] pos = new int[2];
v.getLocationOnScreen(pos);
diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java
index 9217ca987..7efb6ec94 100644
--- a/src/com/android/launcher3/FastBitmapDrawable.java
+++ b/src/com/android/launcher3/FastBitmapDrawable.java
@@ -109,7 +109,7 @@ public class FastBitmapDrawable extends Drawable {
@Override
public final void draw(Canvas canvas) {
- if (mScaleAnimation != null) {
+ if (mScale != 1f) {
int count = canvas.save();
Rect bounds = getBounds();
canvas.scale(mScale, mScale, bounds.exactCenterX(), bounds.exactCenterY());
@@ -150,10 +150,23 @@ public class FastBitmapDrawable extends Drawable {
return mAlpha;
}
+ public void setScale(float scale) {
+ if (mScaleAnimation != null) {
+ mScaleAnimation.cancel();
+ mScaleAnimation = null;
+ }
+ mScale = scale;
+ invalidateSelf();
+ }
+
public float getAnimatedScale() {
return mScaleAnimation == null ? 1 : mScale;
}
+ public float getScale() {
+ return mScale;
+ }
+
@Override
public int getIntrinsicWidth() {
return mBitmap.getWidth();
diff --git a/src/com/android/launcher3/IconCache.java b/src/com/android/launcher3/IconCache.java
index c5ca183f7..f496600c7 100644
--- a/src/com/android/launcher3/IconCache.java
+++ b/src/com/android/launcher3/IconCache.java
@@ -478,7 +478,8 @@ public class IconCache {
info.contentDescription = "";
info.usingLowResIcon = false;
} else {
- getTitleAndIcon(info, new ActivityInfoProvider(info.getIntent(), info.user),
+ Intent intent = info.getIntent();
+ getTitleAndIcon(info, () -> mLauncherApps.resolveActivity(intent, info.user),
true, useLowResIcon);
}
}
@@ -869,22 +870,6 @@ public class IconCache {
}
}
- private class ActivityInfoProvider extends Provider<LauncherActivityInfo> {
-
- private final Intent mIntent;
- private final UserHandle mUser;
-
- public ActivityInfoProvider(Intent intent, UserHandle user) {
- mIntent = intent;
- mUser = user;
- }
-
- @Override
- public LauncherActivityInfo get() {
- return mLauncherApps.resolveActivity(mIntent, mUser);
- }
- }
-
/**
* Interface for receiving itemInfo with high-res icon.
*/
diff --git a/src/com/android/launcher3/IconProvider.java b/src/com/android/launcher3/IconProvider.java
index b469a8f45..ed8d03c47 100644
--- a/src/com/android/launcher3/IconProvider.java
+++ b/src/com/android/launcher3/IconProvider.java
@@ -5,14 +5,16 @@ import android.content.pm.LauncherActivityInfo;
import android.graphics.drawable.Drawable;
import android.os.Build;
+import com.android.launcher3.util.ResourceBasedOverride;
+
import java.util.Locale;
-public class IconProvider {
+public class IconProvider implements ResourceBasedOverride {
protected String mSystemState;
public static IconProvider newInstance(Context context) {
- IconProvider provider = Utilities.getOverrideObject(
+ IconProvider provider = Overrides.getObject(
IconProvider.class, context, R.string.icon_provider_class);
provider.updateSystemStateString(context);
return provider;
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index fe8a841be..b9d45fb02 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -47,7 +47,6 @@ import com.android.launcher3.shortcuts.ShortcutInfoCompat;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Preconditions;
-import com.android.launcher3.util.Provider;
import com.android.launcher3.util.Thunk;
import org.json.JSONException;
@@ -486,13 +485,10 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
if (Looper.myLooper() == LauncherModel.getWorkerLooper()) {
app.getIconCache().getTitleAndIcon(si, activityInfo, false /* useLowResIcon */);
} else {
- app.getModel().updateAndBindShortcutInfo(new Provider<ShortcutInfo>() {
- @Override
- public ShortcutInfo get() {
- app.getIconCache().getTitleAndIcon(
- si, activityInfo, false /* useLowResIcon */);
- return si;
- }
+ app.getModel().updateAndBindShortcutInfo(() -> {
+ app.getIconCache().getTitleAndIcon(
+ si, activityInfo, false /* useLowResIcon */);
+ return si;
});
}
return Pair.create((ItemInfo) si, (Object) activityInfo);
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index f63cce58d..22bc162b6 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -29,6 +29,8 @@ import android.view.Display;
import android.view.WindowManager;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.util.ConfigMonitor;
+import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.Thunk;
import org.xmlpull.v1.XmlPullParser;
@@ -41,8 +43,12 @@ import java.util.Comparator;
public class InvariantDeviceProfile {
- // This is a static that we use for the default icon size on a 4/5-inch phone
- private static float DEFAULT_ICON_SIZE_DP = 60;
+ // We do not need any synchronization for this variable as its only written on UI thread.
+ public static final MainThreadInitializedObject<InvariantDeviceProfile> INSTANCE =
+ new MainThreadInitializedObject<>((c) -> {
+ new ConfigMonitor(c).register();
+ return new InvariantDeviceProfile(c);
+ });
private static final float ICON_SIZE_DEFINED_IN_APP_DP = 48;
@@ -118,7 +124,7 @@ public class InvariantDeviceProfile {
}
@TargetApi(23)
- public InvariantDeviceProfile(Context context) {
+ private InvariantDeviceProfile(Context context) {
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
DisplayMetrics dm = new DisplayMetrics();
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 4fe35033b..44d3d5373 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -16,6 +16,7 @@
package com.android.launcher3;
+import static android.content.pm.ActivityInfo.CONFIG_LOCALE;
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
@@ -74,7 +75,6 @@ import android.view.animation.OvershootInterpolator;
import android.widget.Toast;
import com.android.launcher3.DropTarget.DragObject;
-import com.android.launcher3.Workspace.ItemOperator;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.allapps.AllAppsTransitionController;
@@ -86,6 +86,7 @@ import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragView;
+import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.folder.FolderIconPreviewVerifier;
import com.android.launcher3.keyboard.CustomActionsPopup;
@@ -356,6 +357,11 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
@Override
public void onConfigurationChanged(Configuration newConfig) {
int diff = newConfig.diff(mOldConfig);
+
+ if ((diff & CONFIG_LOCALE) != 0) {
+ Folder.setLocaleDependentFields(getResources(), true /* force */);
+ }
+
if ((diff & (CONFIG_ORIENTATION | CONFIG_SCREEN_SIZE)) != 0) {
mUserEventDispatcher = null;
initDeviceProfile(mDeviceProfile.inv);
@@ -1058,12 +1064,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
}
public FolderIcon findFolderIcon(final long folderIconId) {
- return (FolderIcon) mWorkspace.getFirstMatch(new ItemOperator() {
- @Override
- public boolean evaluate(ItemInfo info, View view) {
- return info != null && info.id == folderIconId;
- }
- });
+ return (FolderIcon) mWorkspace.getHomescreenIconByItemId(folderIconId);
}
/**
@@ -2417,10 +2418,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
}
public static Launcher getLauncher(Context context) {
- if (context instanceof Launcher) {
- return (Launcher) context;
- }
- return ((Launcher) ((ContextWrapper) context).getBaseContext());
+ return (Launcher) fromContext(context);
}
/**
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index a46692b0b..5159de17a 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -16,12 +16,13 @@
package com.android.launcher3;
+import static com.android.launcher3.SettingsActivity.NOTIFICATION_BADGING;
+
import android.content.ComponentName;
import android.content.ContentProviderClient;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.os.Looper;
import android.util.Log;
import com.android.launcher3.compat.LauncherAppsCompat;
@@ -29,21 +30,17 @@ import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.notification.NotificationListener;
-import com.android.launcher3.util.ConfigMonitor;
+import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.SettingsObserver;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-
-import static com.android.launcher3.SettingsActivity.NOTIFICATION_BADGING;
-
public class LauncherAppState {
public static final String ACTION_FORCE_ROLOAD = "force-reload-launcher";
// We do not need any synchronization for this variable as its only written on UI thread.
- private static LauncherAppState INSTANCE;
+ private static final MainThreadInitializedObject<LauncherAppState> INSTANCE =
+ new MainThreadInitializedObject<>((c) -> new LauncherAppState(c));
private final Context mContext;
private final LauncherModel mModel;
@@ -53,27 +50,11 @@ public class LauncherAppState {
private final SettingsObserver mNotificationBadgingObserver;
public static LauncherAppState getInstance(final Context context) {
- if (INSTANCE == null) {
- if (Looper.myLooper() == Looper.getMainLooper()) {
- INSTANCE = new LauncherAppState(context.getApplicationContext());
- } else {
- try {
- return new MainThreadExecutor().submit(new Callable<LauncherAppState>() {
- @Override
- public LauncherAppState call() throws Exception {
- return LauncherAppState.getInstance(context);
- }
- }).get();
- } catch (InterruptedException|ExecutionException e) {
- throw new RuntimeException(e);
- }
- }
- }
- return INSTANCE;
+ return INSTANCE.get(context);
}
public static LauncherAppState getInstanceNoCreate() {
- return INSTANCE;
+ return INSTANCE.getNoCreate();
}
public Context getContext() {
@@ -89,7 +70,7 @@ public class LauncherAppState {
Preconditions.assertUIThread();
mContext = context;
- mInvariantDeviceProfile = new InvariantDeviceProfile(mContext);
+ mInvariantDeviceProfile = InvariantDeviceProfile.INSTANCE.get(mContext);
mIconCache = new IconCache(mContext, mInvariantDeviceProfile);
mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache);
mModel = new LauncherModel(this, mIconCache, AppFilter.newInstance(mContext));
@@ -112,7 +93,6 @@ public class LauncherAppState {
mContext.registerReceiver(mModel, filter);
UserManagerCompat.getInstance(mContext).enableAndResetCache();
- new ConfigMonitor(mContext).register();
if (!mContext.getResources().getBoolean(R.bool.notification_badging_enabled)) {
mNotificationBadgingObserver = null;
@@ -171,7 +151,7 @@ public class LauncherAppState {
* Shorthand for {@link #getInvariantDeviceProfile()}
*/
public static InvariantDeviceProfile getIDP(Context context) {
- return LauncherAppState.getInstance(context).getInvariantDeviceProfile();
+ return InvariantDeviceProfile.INSTANCE.get(context);
}
private static LauncherProvider getLocalProvider(Context context) {
diff --git a/src/com/android/launcher3/LauncherAppTransitionManager.java b/src/com/android/launcher3/LauncherAppTransitionManager.java
index 4037a23ff..970e55878 100644
--- a/src/com/android/launcher3/LauncherAppTransitionManager.java
+++ b/src/com/android/launcher3/LauncherAppTransitionManager.java
@@ -23,13 +23,15 @@ import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.view.View;
+import com.android.launcher3.util.ResourceBasedOverride;
+
/**
* Manages the opening and closing app transitions from Launcher.
*/
-public class LauncherAppTransitionManager {
+public class LauncherAppTransitionManager implements ResourceBasedOverride {
public static LauncherAppTransitionManager newInstance(Context context) {
- return Utilities.getOverrideObject(LauncherAppTransitionManager.class,
+ return Overrides.getObject(LauncherAppTransitionManager.class,
context, R.string.app_transition_manager_class);
}
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 37538ae0d..19aa795fe 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -620,15 +620,12 @@ public class LauncherModel extends BroadcastReceiver
}
public void updateAndBindShortcutInfo(final ShortcutInfo si, final ShortcutInfoCompat info) {
- updateAndBindShortcutInfo(new Provider<ShortcutInfo>() {
- @Override
- public ShortcutInfo get() {
- si.updateFromDeepShortcutInfo(info, mApp.getContext());
- LauncherIcons li = LauncherIcons.obtain(mApp.getContext());
- li.createShortcutIcon(info).applyTo(si);
- li.recycle();
- return si;
- }
+ updateAndBindShortcutInfo(() -> {
+ si.updateFromDeepShortcutInfo(info, mApp.getContext());
+ LauncherIcons li = LauncherIcons.obtain(mApp.getContext());
+ li.createShortcutIcon(info).applyTo(si);
+ li.recycle();
+ return si;
});
}
diff --git a/src/com/android/launcher3/LauncherScroller.java b/src/com/android/launcher3/LauncherScroller.java
index a9b49556b..e5042c4e2 100644
--- a/src/com/android/launcher3/LauncherScroller.java
+++ b/src/com/android/launcher3/LauncherScroller.java
@@ -18,541 +18,37 @@ package com.android.launcher3;
import android.animation.TimeInterpolator;
import android.content.Context;
-import android.hardware.SensorManager;
-import android.os.Build;
-import android.view.ViewConfiguration;
-import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
+import android.widget.Scroller;
/**
- * This class differs from the framework {@link android.widget.Scroller} in that
- * you can modify the Interpolator post-construction.
+ * Extension of {@link android.widget.Scroller} with the ability to modify the
+ * Interpolator post-construction.
*/
-public class LauncherScroller {
- private int mMode;
+public class LauncherScroller extends Scroller {
- private int mStartX;
- private int mStartY;
- private int mFinalX;
- private int mFinalY;
+ private final InterpolatorWrapper mInterpolatorWrapper;
- private int mMinX;
- private int mMaxX;
- private int mMinY;
- private int mMaxY;
-
- private int mCurrX;
- private int mCurrY;
- private long mStartTime;
- private int mDuration;
- private float mDurationReciprocal;
- private float mDeltaX;
- private float mDeltaY;
- private boolean mFinished;
- private TimeInterpolator mInterpolator;
- private boolean mFlywheel;
-
- private float mVelocity;
- private float mCurrVelocity;
- private int mDistance;
-
- private float mFlingFriction = ViewConfiguration.getScrollFriction();
-
- private static final int DEFAULT_DURATION = 250;
- private static final int SCROLL_MODE = 0;
- private static final int FLING_MODE = 1;
-
- private static float DECELERATION_RATE = (float) (Math.log(0.78) / Math.log(0.9));
- private static final float INFLEXION = 0.35f; // Tension lines cross at (INFLEXION, 1)
- private static final float START_TENSION = 0.5f;
- private static final float END_TENSION = 1.0f;
- private static final float P1 = START_TENSION * INFLEXION;
- private static final float P2 = 1.0f - END_TENSION * (1.0f - INFLEXION);
-
- private static final int NB_SAMPLES = 100;
- private static final float[] SPLINE_POSITION = new float[NB_SAMPLES + 1];
- private static final float[] SPLINE_TIME = new float[NB_SAMPLES + 1];
-
- private float mDeceleration;
- private final float mPpi;
-
- // A context-specific coefficient adjusted to physical values.
- private float mPhysicalCoeff;
-
- static {
- float x_min = 0.0f;
- float y_min = 0.0f;
- for (int i = 0; i < NB_SAMPLES; i++) {
- final float alpha = (float) i / NB_SAMPLES;
-
- float x_max = 1.0f;
- float x, tx, coef;
- while (true) {
- x = x_min + (x_max - x_min) / 2.0f;
- coef = 3.0f * x * (1.0f - x);
- tx = coef * ((1.0f - x) * P1 + x * P2) + x * x * x;
- if (Math.abs(tx - alpha) < 1E-5) break;
- if (tx > alpha) x_max = x;
- else x_min = x;
- }
- SPLINE_POSITION[i] = coef * ((1.0f - x) * START_TENSION + x) + x * x * x;
-
- float y_max = 1.0f;
- float y, dy;
- while (true) {
- y = y_min + (y_max - y_min) / 2.0f;
- coef = 3.0f * y * (1.0f - y);
- dy = coef * ((1.0f - y) * START_TENSION + y) + y * y * y;
- if (Math.abs(dy - alpha) < 1E-5) break;
- if (dy > alpha) y_max = y;
- else y_min = y;
- }
- SPLINE_TIME[i] = coef * ((1.0f - y) * P1 + y * P2) + y * y * y;
- }
- SPLINE_POSITION[NB_SAMPLES] = SPLINE_TIME[NB_SAMPLES] = 1.0f;
-
- // This controls the viscous fluid effect (how much of it)
- sViscousFluidScale = 8.0f;
- // must be set to 1.0 (used in viscousFluid())
- sViscousFluidNormalize = 1.0f;
- sViscousFluidNormalize = 1.0f / viscousFluid(1.0f);
-
- }
-
- private static float sViscousFluidScale;
- private static float sViscousFluidNormalize;
-
- public void setInterpolator(TimeInterpolator interpolator) {
- mInterpolator = interpolator;
- }
-
- /**
- * Create a Scroller with the default duration and interpolator.
- */
public LauncherScroller(Context context) {
- this(context, null);
- }
-
- /**
- * Create a Scroller with the specified interpolator. If the interpolator is
- * null, the default (viscous) interpolator will be used. "Flywheel" behavior will
- * be in effect for apps targeting Honeycomb or newer.
- */
- public LauncherScroller(Context context, Interpolator interpolator) {
- this(context, interpolator,
- context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB);
- }
-
- /**
- * Create a Scroller with the specified interpolator. If the interpolator is
- * null, the default (viscous) interpolator will be used. Specify whether or
- * not to support progressive "flywheel" behavior in flinging.
- */
- public LauncherScroller(Context context, Interpolator interpolator, boolean flywheel) {
- mFinished = true;
- mInterpolator = interpolator;
- mPpi = context.getResources().getDisplayMetrics().density * 160.0f;
- mDeceleration = computeDeceleration(ViewConfiguration.getScrollFriction());
- mFlywheel = flywheel;
-
- mPhysicalCoeff = computeDeceleration(0.84f); // look and feel tuning
- }
-
- /**
- * The amount of friction applied to flings. The default value
- * is {@link ViewConfiguration#getScrollFriction}.
- *
- * @param friction A scalar dimension-less value representing the coefficient of
- * friction.
- */
- public final void setFriction(float friction) {
- mDeceleration = computeDeceleration(friction);
- mFlingFriction = friction;
- }
-
- private float computeDeceleration(float friction) {
- return SensorManager.GRAVITY_EARTH // g (m/s^2)
- * 39.37f // inch/meter
- * mPpi // pixels per inch
- * friction;
- }
-
- /**
- *
- * Returns whether the scroller has finished scrolling.
- *
- * @return True if the scroller has finished scrolling, false otherwise.
- */
- public final boolean isFinished() {
- return mFinished;
- }
-
- /**
- * Force the finished field to a particular value.
- *
- * @param finished The new finished value.
- */
- public final void forceFinished(boolean finished) {
- mFinished = finished;
- }
-
- /**
- * Returns how long the scroll event will take, in milliseconds.
- *
- * @return The duration of the scroll in milliseconds.
- */
- public final int getDuration() {
- return mDuration;
- }
-
- /**
- * Returns the current X offset in the scroll.
- *
- * @return The new X offset as an absolute distance from the origin.
- */
- public final int getCurrX() {
- return mCurrX;
- }
-
- /**
- * Returns the current Y offset in the scroll.
- *
- * @return The new Y offset as an absolute distance from the origin.
- */
- public final int getCurrY() {
- return mCurrY;
- }
-
- /**
- * Returns the current velocity.
- *
- * @return The original velocity less the deceleration. Result may be
- * negative.
- */
- public float getCurrVelocity() {
- return mMode == FLING_MODE ?
- mCurrVelocity : mVelocity - mDeceleration * timePassed() / 2000.0f;
- }
-
- /**
- * Returns the start X offset in the scroll.
- *
- * @return The start X offset as an absolute distance from the origin.
- */
- public final int getStartX() {
- return mStartX;
- }
-
- /**
- * Returns the start Y offset in the scroll.
- *
- * @return The start Y offset as an absolute distance from the origin.
- */
- public final int getStartY() {
- return mStartY;
- }
-
- /**
- * Returns where the scroll will end. Valid only for "fling" scrolls.
- *
- * @return The final X offset as an absolute distance from the origin.
- */
- public final int getFinalX() {
- return mFinalX;
+ this(context, new InterpolatorWrapper());
}
- /**
- * Returns where the scroll will end. Valid only for "fling" scrolls.
- *
- * @return The final Y offset as an absolute distance from the origin.
- */
- public final int getFinalY() {
- return mFinalY;
+ private LauncherScroller(Context context, InterpolatorWrapper interpolatorWrapper) {
+ super(context, interpolatorWrapper);
+ mInterpolatorWrapper = interpolatorWrapper;
}
- /**
- * Call this when you want to know the new location. If it returns true,
- * the animation is not yet finished.
- */
- public boolean computeScrollOffset() {
- if (mFinished) {
- return false;
- }
-
- int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
-
- if (timePassed < mDuration) {
- switch (mMode) {
- case SCROLL_MODE:
- float x = timePassed * mDurationReciprocal;
-
- if (mInterpolator == null)
- x = viscousFluid(x);
- else
- x = mInterpolator.getInterpolation(x);
-
- mCurrX = mStartX + Math.round(x * mDeltaX);
- mCurrY = mStartY + Math.round(x * mDeltaY);
- break;
- case FLING_MODE:
- final float t = (float) timePassed / mDuration;
- final int index = (int) (NB_SAMPLES * t);
- float distanceCoef = 1.f;
- float velocityCoef = 0.f;
- if (index < NB_SAMPLES) {
- final float t_inf = (float) index / NB_SAMPLES;
- final float t_sup = (float) (index + 1) / NB_SAMPLES;
- final float d_inf = SPLINE_POSITION[index];
- final float d_sup = SPLINE_POSITION[index + 1];
- velocityCoef = (d_sup - d_inf) / (t_sup - t_inf);
- distanceCoef = d_inf + (t - t_inf) * velocityCoef;
- }
-
- mCurrVelocity = velocityCoef * mDistance / mDuration * 1000.0f;
-
- mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX));
- // Pin to mMinX <= mCurrX <= mMaxX
- mCurrX = Math.min(mCurrX, mMaxX);
- mCurrX = Math.max(mCurrX, mMinX);
-
- mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY));
- // Pin to mMinY <= mCurrY <= mMaxY
- mCurrY = Math.min(mCurrY, mMaxY);
- mCurrY = Math.max(mCurrY, mMinY);
-
- if (mCurrX == mFinalX && mCurrY == mFinalY) {
- mFinished = true;
- }
-
- break;
- }
- }
- else {
- mCurrX = mFinalX;
- mCurrY = mFinalY;
- mFinished = true;
- }
- return true;
- }
-
- /**
- * Start scrolling by providing a starting point and the distance to travel.
- * The scroll will use the default value of 250 milliseconds for the
- * duration.
- *
- * @param startX Starting horizontal scroll offset in pixels. Positive
- * numbers will scroll the content to the left.
- * @param startY Starting vertical scroll offset in pixels. Positive numbers
- * will scroll the content up.
- * @param dx Horizontal distance to travel. Positive numbers will scroll the
- * content to the left.
- * @param dy Vertical distance to travel. Positive numbers will scroll the
- * content up.
- */
- public void startScroll(int startX, int startY, int dx, int dy) {
- startScroll(startX, startY, dx, dy, DEFAULT_DURATION);
- }
-
- /**
- * Start scrolling by providing a starting point, the distance to travel,
- * and the duration of the scroll.
- *
- * @param startX Starting horizontal scroll offset in pixels. Positive
- * numbers will scroll the content to the left.
- * @param startY Starting vertical scroll offset in pixels. Positive numbers
- * will scroll the content up.
- * @param dx Horizontal distance to travel. Positive numbers will scroll the
- * content to the left.
- * @param dy Vertical distance to travel. Positive numbers will scroll the
- * content up.
- * @param duration Duration of the scroll in milliseconds.
- */
- public void startScroll(int startX, int startY, int dx, int dy, int duration) {
- mMode = SCROLL_MODE;
- mFinished = false;
- mDuration = duration;
- mStartTime = AnimationUtils.currentAnimationTimeMillis();
- mStartX = startX;
- mStartY = startY;
- mFinalX = startX + dx;
- mFinalY = startY + dy;
- mDeltaX = dx;
- mDeltaY = dy;
- mDurationReciprocal = 1.0f / (float) mDuration;
- }
-
- /**
- * Start scrolling based on a fling gesture. The distance travelled will
- * depend on the initial velocity of the fling.
- *
- * @param startX Starting point of the scroll (X)
- * @param startY Starting point of the scroll (Y)
- * @param velocityX Initial velocity of the fling (X) measured in pixels per
- * second.
- * @param velocityY Initial velocity of the fling (Y) measured in pixels per
- * second
- * @param minX Minimum X value. The scroller will not scroll past this
- * point.
- * @param maxX Maximum X value. The scroller will not scroll past this
- * point.
- * @param minY Minimum Y value. The scroller will not scroll past this
- * point.
- * @param maxY Maximum Y value. The scroller will not scroll past this
- * point.
- */
- public void fling(int startX, int startY, int velocityX, int velocityY,
- int minX, int maxX, int minY, int maxY) {
- // Continue a scroll or fling in progress
- if (mFlywheel && !mFinished) {
- float oldVel = getCurrVelocity();
-
- float dx = (float) (mFinalX - mStartX);
- float dy = (float) (mFinalY - mStartY);
- float hyp = (float) Math.hypot(dx, dy);
-
- float ndx = dx / hyp;
- float ndy = dy / hyp;
-
- float oldVelocityX = ndx * oldVel;
- float oldVelocityY = ndy * oldVel;
- if (Math.signum(velocityX) == Math.signum(oldVelocityX) &&
- Math.signum(velocityY) == Math.signum(oldVelocityY)) {
- velocityX += oldVelocityX;
- velocityY += oldVelocityY;
- }
- }
-
- mMode = FLING_MODE;
- mFinished = false;
-
- float velocity = (float) Math.hypot(velocityX, velocityY);
-
- mVelocity = velocity;
- mDuration = getSplineFlingDuration(velocity);
- mStartTime = AnimationUtils.currentAnimationTimeMillis();
- mStartX = startX;
- mStartY = startY;
-
- float coeffX = velocity == 0 ? 1.0f : velocityX / velocity;
- float coeffY = velocity == 0 ? 1.0f : velocityY / velocity;
-
- double totalDistance = getSplineFlingDistance(velocity);
- mDistance = (int) (totalDistance * Math.signum(velocity));
-
- mMinX = minX;
- mMaxX = maxX;
- mMinY = minY;
- mMaxY = maxY;
-
- mFinalX = startX + (int) Math.round(totalDistance * coeffX);
- // Pin to mMinX <= mFinalX <= mMaxX
- mFinalX = Math.min(mFinalX, mMaxX);
- mFinalX = Math.max(mFinalX, mMinX);
-
- mFinalY = startY + (int) Math.round(totalDistance * coeffY);
- // Pin to mMinY <= mFinalY <= mMaxY
- mFinalY = Math.min(mFinalY, mMaxY);
- mFinalY = Math.max(mFinalY, mMinY);
- }
-
- private double getSplineDeceleration(float velocity) {
- return Math.log(INFLEXION * Math.abs(velocity) / (mFlingFriction * mPhysicalCoeff));
+ public void setInterpolator(TimeInterpolator interpolator) {
+ mInterpolatorWrapper.interpolator = interpolator;
}
- private int getSplineFlingDuration(float velocity) {
- final double l = getSplineDeceleration(velocity);
- final double decelMinusOne = DECELERATION_RATE - 1.0;
- return (int) (1000.0 * Math.exp(l / decelMinusOne));
- }
+ private static class InterpolatorWrapper implements Interpolator {
- private double getSplineFlingDistance(float velocity) {
- final double l = getSplineDeceleration(velocity);
- final double decelMinusOne = DECELERATION_RATE - 1.0;
- return mFlingFriction * mPhysicalCoeff * Math.exp(DECELERATION_RATE / decelMinusOne * l);
- }
+ public TimeInterpolator interpolator;
- static float viscousFluid(float x)
- {
- x *= sViscousFluidScale;
- if (x < 1.0f) {
- x -= (1.0f - (float)Math.exp(-x));
- } else {
- float start = 0.36787944117f; // 1/e == exp(-1)
- x = 1.0f - (float)Math.exp(1.0f - x);
- x = start + x * (1.0f - start);
+ @Override
+ public float getInterpolation(float v) {
+ return interpolator == null ? v : interpolator.getInterpolation(v);
}
- x *= sViscousFluidNormalize;
- return x;
- }
-
- /**
- * Stops the animation. Contrary to {@link #forceFinished(boolean)},
- * aborting the animating cause the scroller to move to the final x and y
- * position
- *
- * @see #forceFinished(boolean)
- */
- public void abortAnimation() {
- mCurrX = mFinalX;
- mCurrY = mFinalY;
- mFinished = true;
- }
-
- /**
- * Extend the scroll animation. This allows a running animation to scroll
- * further and longer, when used with {@link #setFinalX(int)} or {@link #setFinalY(int)}.
- *
- * @param extend Additional time to scroll in milliseconds.
- * @see #setFinalX(int)
- * @see #setFinalY(int)
- */
- public void extendDuration(int extend) {
- int passed = timePassed();
- mDuration = passed + extend;
- mDurationReciprocal = 1.0f / mDuration;
- mFinished = false;
- }
-
- /**
- * Returns the time elapsed since the beginning of the scrolling.
- *
- * @return The elapsed time in milliseconds.
- */
- public int timePassed() {
- return (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
- }
-
- /**
- * Sets the final position (X) for this scroller.
- *
- * @param newX The new X offset as an absolute distance from the origin.
- * @see #extendDuration(int)
- * @see #setFinalY(int)
- */
- public void setFinalX(int newX) {
- mFinalX = newX;
- mDeltaX = mFinalX - mStartX;
- mFinished = false;
- }
-
- /**
- * Sets the final position (Y) for this scroller.
- *
- * @param newY The new Y offset as an absolute distance from the origin.
- * @see #extendDuration(int)
- * @see #setFinalX(int)
- */
- public void setFinalY(int newY) {
- mFinalY = newY;
- mDeltaY = mFinalY - mStartY;
- mFinished = false;
- }
-
- /**
- * @hide
- */
- public boolean isScrollingInDirection(float xvel, float yvel) {
- return !mFinished && Math.signum(xvel) == Math.signum(mFinalX - mStartX) &&
- Math.signum(yvel) == Math.signum(mFinalY - mStartY);
}
}
diff --git a/src/com/android/launcher3/MainProcessInitializer.java b/src/com/android/launcher3/MainProcessInitializer.java
index 462eadb34..0028f97cd 100644
--- a/src/com/android/launcher3/MainProcessInitializer.java
+++ b/src/com/android/launcher3/MainProcessInitializer.java
@@ -20,14 +20,15 @@ import android.content.Context;
import com.android.launcher3.graphics.IconShapeOverride;
import com.android.launcher3.logging.FileLog;
+import com.android.launcher3.util.ResourceBasedOverride;
/**
* Utility class to handle one time initializations of the main process
*/
-public class MainProcessInitializer {
+public class MainProcessInitializer implements ResourceBasedOverride {
public static void initialize(Context context) {
- Utilities.getOverrideObject(
+ Overrides.getObject(
MainProcessInitializer.class, context, R.string.main_process_initializer_class)
.init(context);
}
diff --git a/src/com/android/launcher3/OverviewButtonClickListener.java b/src/com/android/launcher3/OverviewButtonClickListener.java
deleted file mode 100644
index dd670d2a7..000000000
--- a/src/com/android/launcher3/OverviewButtonClickListener.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.android.launcher3;
-
-import android.view.View;
-
-import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
-
-/**
- * A specialized listener for Overview buttons where both clicks and long clicks are logged
- * handled the same via {@link #handleViewClick(View)}.
- */
-public abstract class OverviewButtonClickListener implements View.OnClickListener,
- View.OnLongClickListener {
-
- private int mControlType; /** ControlType enum as defined in {@link Action.Touch} */
-
- public OverviewButtonClickListener(int controlType) {
- mControlType = controlType;
- }
-
- public void attachTo(View v) {
- v.setOnClickListener(this);
- v.setOnLongClickListener(this);
- }
-
- @Override
- public void onClick(View view) {
- if (shouldPerformClick(view)) {
- handleViewClick(view, Action.Touch.TAP);
- }
- }
-
- @Override
- public boolean onLongClick(View view) {
- if (shouldPerformClick(view)) {
- handleViewClick(view, Action.Touch.LONGPRESS);
- }
- return true;
- }
-
- private boolean shouldPerformClick(View view) {
- return !Launcher.getLauncher(view.getContext()).getWorkspace().isSwitchingState();
- }
-
- private void handleViewClick(View view, int action) {
- handleViewClick(view);
- Launcher.getLauncher(view.getContext()).getUserEventDispatcher()
- .logActionOnControl(action, mControlType);
- }
-
- public abstract void handleViewClick(View view);
-} \ No newline at end of file
diff --git a/src/com/android/launcher3/SettingsActivity.java b/src/com/android/launcher3/SettingsActivity.java
index 32c198ab0..8589b7ee6 100644
--- a/src/com/android/launcher3/SettingsActivity.java
+++ b/src/com/android/launcher3/SettingsActivity.java
@@ -24,6 +24,7 @@ import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
+import android.app.Fragment;
import android.app.FragmentManager;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -53,7 +54,8 @@ import java.util.Objects;
/**
* Settings activity for Launcher. Currently implements the following setting: Allow rotation
*/
-public class SettingsActivity extends Activity {
+public class SettingsActivity extends Activity
+ implements PreferenceFragment.OnPreferenceStartFragmentCallback {
private static final String ICON_BADGING_PREFERENCE_KEY = "pref_icon_badging";
/** Hidden field Settings.Secure.NOTIFICATION_BADGING */
@@ -71,9 +73,10 @@ public class SettingsActivity extends Activity {
super.onCreate(savedInstanceState);
if (savedInstanceState == null) {
+ Fragment f = Fragment.instantiate(this, getString(R.string.settings_fragment_name));
// Display the fragment as the main content.
getFragmentManager().beginTransaction()
- .replace(android.R.id.content, getNewFragment())
+ .replace(android.R.id.content, f)
.commit();
}
}
@@ -82,6 +85,22 @@ public class SettingsActivity extends Activity {
return new LauncherSettingsFragment();
}
+ @Override
+ public boolean onPreferenceStartFragment(
+ PreferenceFragment preferenceFragment, Preference pref) {
+ Fragment f = Fragment.instantiate(this, pref.getFragment(), pref.getExtras());
+ if (f instanceof DialogFragment) {
+ ((DialogFragment) f).show(getFragmentManager(), pref.getKey());
+ } else {
+ getFragmentManager()
+ .beginTransaction()
+ .replace(android.R.id.content, f)
+ .addToBackStack(pref.getKey())
+ .commit();
+ }
+ return true;
+ }
+
/**
* This fragment shows the launcher preferences.
*/
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 7fe8d35cb..7c5bb1af8 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -16,6 +16,7 @@
package com.android.launcher3;
+import android.app.ActivityManager;
import android.app.WallpaperManager;
import android.content.ComponentName;
import android.content.Context;
@@ -55,7 +56,6 @@ import com.android.launcher3.config.FeatureFlags;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashSet;
@@ -131,6 +131,9 @@ public final class Utilities {
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
+ public static final boolean IS_RUNNING_IN_TEST_HARNESS =
+ ActivityManager.isRunningInTestHarness();
+
public static boolean isPropertyEnabled(String propertyName) {
return Log.isLoggable(propertyName, Log.VERBOSE);
}
@@ -581,25 +584,6 @@ public final class Utilities {
|| e.getCause() instanceof DeadObjectException;
}
- public static <T> T getOverrideObject(Class<T> clazz, Context context, int resId) {
- String className = context.getString(resId);
- if (!TextUtils.isEmpty(className)) {
- try {
- Class<?> cls = Class.forName(className);
- return (T) cls.getDeclaredConstructor(Context.class).newInstance(context);
- } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
- | ClassCastException | NoSuchMethodException | InvocationTargetException e) {
- Log.e(TAG, "Bad overriden class", e);
- }
- }
-
- try {
- return clazz.newInstance();
- } catch (InstantiationException|IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
-
/**
* Returns a HashSet with a single element. We use this instead of Collections.singleton()
* because HashSet ensures all operations, such as remove, are supported.
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 54d29c115..a344a7b13 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1036,7 +1036,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
}
protected void onScrollInteractionBegin() {
- super.onScrollInteractionEnd();
+ super.onScrollInteractionBegin();
mScrollInteractionBegan = true;
}
@@ -3036,16 +3036,6 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
});
}
- public View getViewForTag(final Object tag) {
- return getFirstMatch(new ItemOperator() {
-
- @Override
- public boolean evaluate(ItemInfo info, View v) {
- return info == tag;
- }
- });
- }
-
public LauncherAppWidgetHostView getWidgetForAppWidgetId(final int appWidgetId) {
return (LauncherAppWidgetHostView) getFirstMatch(new ItemOperator() {
diff --git a/src/com/android/launcher3/allapps/DiscoveryBounce.java b/src/com/android/launcher3/allapps/DiscoveryBounce.java
index 3c3c4066d..76b25655c 100644
--- a/src/com/android/launcher3/allapps/DiscoveryBounce.java
+++ b/src/com/android/launcher3/allapps/DiscoveryBounce.java
@@ -125,7 +125,8 @@ public class DiscoveryBounce extends AbstractFloatingView {
private static void showForHomeIfNeeded(Launcher launcher, boolean withDelay) {
if (!launcher.isInState(NORMAL)
- || launcher.getSharedPrefs().getBoolean(HOME_BOUNCE_SEEN, false)
+ || (launcher.getSharedPrefs().getBoolean(HOME_BOUNCE_SEEN, false)
+ && !shouldShowForWorkProfile(launcher))
|| AbstractFloatingView.getTopOpenView(launcher) != null
|| UserManagerCompat.getInstance(launcher).isDemoUser()
|| ActivityManager.isRunningInTestHarness()) {
@@ -149,7 +150,8 @@ public class DiscoveryBounce extends AbstractFloatingView {
|| !launcher.hasBeenResumed()
|| launcher.isForceInvisible()
|| launcher.getDeviceProfile().isVerticalBarLayout()
- || launcher.getSharedPrefs().getBoolean(SHELF_BOUNCE_SEEN, false)
+ || (launcher.getSharedPrefs().getBoolean(SHELF_BOUNCE_SEEN, false)
+ && !shouldShowForWorkProfile(launcher))
|| UserManagerCompat.getInstance(launcher).isDemoUser()
|| ActivityManager.isRunningInTestHarness()) {
return;
@@ -189,4 +191,10 @@ public class DiscoveryBounce extends AbstractFloatingView {
mController.setProgress(progress - mDelta);
}
}
+
+ private static boolean shouldShowForWorkProfile(Launcher launcher) {
+ return !launcher.getSharedPrefs().getBoolean(
+ PersonalWorkSlidingTabStrip.KEY_SHOWED_PEEK_WORK_TAB, false)
+ && UserManagerCompat.getInstance(launcher).hasWorkProfile();
+ }
}
diff --git a/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java b/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java
index a916697bf..31c5914b8 100644
--- a/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java
+++ b/src/com/android/launcher3/allapps/PersonalWorkSlidingTabStrip.java
@@ -39,7 +39,7 @@ public class PersonalWorkSlidingTabStrip extends LinearLayout implements PageInd
private static final int POSITION_PERSONAL = 0;
private static final int POSITION_WORK = 1;
- private static final String KEY_SHOWED_PEEK_WORK_TAB = "showed_peek_work_tab";
+ public static final String KEY_SHOWED_PEEK_WORK_TAB = "showed_peek_work_tab";
private final Paint mSelectedIndicatorPaint;
private final Paint mDividerPaint;
diff --git a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
index 0c78381ea..29fc2bc60 100644
--- a/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
+++ b/src/com/android/launcher3/compat/AccessibilityManagerCompat.java
@@ -16,11 +16,14 @@
package com.android.launcher3.compat;
+import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.Context;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
+import com.android.launcher3.Utilities;
+
public class AccessibilityManagerCompat {
public static boolean isAccessibilityEnabled(Context context) {
@@ -44,4 +47,19 @@ public class AccessibilityManagerCompat {
private static AccessibilityManager getManager(Context context) {
return (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
}
+
+ public static void sendEventToTest(Context context, String eventTag) {
+ if (!Utilities.IS_RUNNING_IN_TEST_HARNESS) return;
+
+ final AccessibilityManager accessibilityManager = getManager(context);
+ if (accessibilityManager.isEnabled() &&
+ accessibilityManager.getEnabledAccessibilityServiceList(
+ AccessibilityServiceInfo.FEEDBACK_ALL_MASK).size() == 0) {
+
+ final AccessibilityEvent e = AccessibilityEvent.obtain(
+ AccessibilityEvent.TYPE_ANNOUNCEMENT);
+ e.setClassName(eventTag);
+ accessibilityManager.sendAccessibilityEvent(e);
+ }
+ }
}
diff --git a/src/com/android/launcher3/compat/UserManagerCompat.java b/src/com/android/launcher3/compat/UserManagerCompat.java
index 03e3861ea..ad5147734 100644
--- a/src/com/android/launcher3/compat/UserManagerCompat.java
+++ b/src/com/android/launcher3/compat/UserManagerCompat.java
@@ -64,4 +64,6 @@ public abstract class UserManagerCompat {
public abstract boolean isDemoUser();
public abstract boolean requestQuietModeEnabled(boolean enableQuietMode, UserHandle user);
public abstract boolean isAnyProfileQuietModeEnabled();
+
+ public abstract boolean hasWorkProfile();
}
diff --git a/src/com/android/launcher3/compat/UserManagerCompatVL.java b/src/com/android/launcher3/compat/UserManagerCompatVL.java
index 1ff69818a..eec343849 100644
--- a/src/com/android/launcher3/compat/UserManagerCompatVL.java
+++ b/src/com/android/launcher3/compat/UserManagerCompatVL.java
@@ -120,6 +120,16 @@ public class UserManagerCompatVL extends UserManagerCompat {
}
@Override
+ public boolean hasWorkProfile() {
+ synchronized (this) {
+ if (mUsers != null) {
+ return mUsers.size() > 1;
+ }
+ }
+ return getUserProfiles().size() > 1;
+ }
+
+ @Override
public CharSequence getBadgedLabelForUser(CharSequence label, UserHandle user) {
if (user == null) {
return label;
diff --git a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
index 1e84b416b..e204c6301 100644
--- a/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
+++ b/src/com/android/launcher3/dragndrop/BaseItemDragListener.java
@@ -106,6 +106,10 @@ public abstract class BaseItemDragListener extends InternalStateHandler implemen
}
protected boolean onDragStart(DragEvent event) {
+ return onDragStart(event, this);
+ }
+
+ protected boolean onDragStart(DragEvent event, DragOptions.PreDragCondition preDragCondition) {
ClipDescription desc = event.getClipDescription();
if (desc == null || !desc.hasMimeType(getMimeType())) {
Log.e(TAG, "Someone started a dragAndDrop before us.");
@@ -115,7 +119,7 @@ public abstract class BaseItemDragListener extends InternalStateHandler implemen
Point downPos = new Point((int) event.getX(), (int) event.getY());
DragOptions options = new DragOptions();
options.systemDndStartPoint = downPos;
- options.preDragCondition = this;
+ options.preDragCondition = preDragCondition;
// We use drag event position as the screenPos for the preview image. Since mPreviewRect
// already includes the view position relative to the drag event on the source window,
@@ -123,7 +127,7 @@ public abstract class BaseItemDragListener extends InternalStateHandler implemen
// across windows, using drag position here give a good estimate for relative position
// to source window.
createDragHelper().startDrag(new Rect(mPreviewRect),
- mPreviewBitmapWidth, mPreviewViewWidth, downPos, this, options);
+ mPreviewBitmapWidth, mPreviewViewWidth, downPos, this, options);
mDragStartTime = SystemClock.uptimeMillis();
return true;
}
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index 8a216fc17..47bbbcb0d 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -16,6 +16,7 @@
package com.android.launcher3.dragndrop;
+import static com.android.launcher3.AbstractFloatingView.TYPE_DISCOVERY_BOUNCE;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
import static com.android.launcher3.LauncherState.NORMAL;
@@ -31,6 +32,7 @@ import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
+import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget;
import com.android.launcher3.ItemInfo;
@@ -145,6 +147,7 @@ public class DragController implements DragDriver.EventListener, TouchController
// Hide soft keyboard, if visible
UiThreadHelper.hideKeyboardAsync(mLauncher, mWindowToken);
+ AbstractFloatingView.closeOpenViews(mLauncher, false, TYPE_DISCOVERY_BOUNCE);
mOptions = options;
if (mOptions.systemDndStartPoint != null) {
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 6b13da70c..6a3ebcfb0 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -25,6 +25,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.annotation.SuppressLint;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
import android.text.InputType;
@@ -191,14 +192,9 @@ public class Folder extends AbstractFloatingView implements DragSource,
public Folder(Context context, AttributeSet attrs) {
super(context, attrs);
setAlwaysDrawnWithCacheEnabled(false);
- Resources res = getResources();
- if (sDefaultFolderName == null) {
- sDefaultFolderName = res.getString(R.string.folder_name);
- }
- if (sHintText == null) {
- sHintText = res.getString(R.string.folder_hint_text);
- }
+ setLocaleDependentFields(getResources(), false /* force */);
+
mLauncher = Launcher.getLauncher(context);
// We need this view to be focusable in touch mode so that when text editing of the folder
// name is complete, we have something to focus on, thus hiding the cursor and giving
@@ -1473,4 +1469,13 @@ public class Folder extends AbstractFloatingView implements DragSource,
}
return false;
}
+
+ public static void setLocaleDependentFields(Resources res, boolean force) {
+ if (sDefaultFolderName == null || force) {
+ sDefaultFolderName = res.getString(R.string.folder_name);
+ }
+ if (sHintText == null || force) {
+ sHintText = res.getString(R.string.folder_hint_text);
+ }
+ }
}
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index cb5d872ab..95a6bbd20 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -77,7 +77,6 @@ public class FolderIcon extends FrameLayout implements FolderListener {
@Thunk Launcher mLauncher;
@Thunk Folder mFolder;
private FolderInfo mInfo;
- @Thunk static boolean sStaticValuesDirty = true;
private CheckLongPressHelper mLongPressHelper;
private StylusEventHelper mStylusEventHelper;
@@ -185,12 +184,6 @@ public class FolderIcon extends FrameLayout implements FolderListener {
return icon;
}
- @Override
- protected Parcelable onSaveInstanceState() {
- sStaticValuesDirty = true;
- return super.onSaveInstanceState();
- }
-
public Folder getFolder() {
return mFolder;
}
diff --git a/src/com/android/launcher3/graphics/BitmapRenderer.java b/src/com/android/launcher3/graphics/BitmapRenderer.java
index 3d11c448a..2a7f20ea3 100644
--- a/src/com/android/launcher3/graphics/BitmapRenderer.java
+++ b/src/com/android/launcher3/graphics/BitmapRenderer.java
@@ -23,32 +23,30 @@ import android.os.Build;
import com.android.launcher3.Utilities;
-public class BitmapRenderer {
-
- public static final boolean USE_HARDWARE_BITMAP = Utilities.ATLEAST_P;
-
- public static Bitmap createSoftwareBitmap(int width, int height, Renderer renderer) {
- Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- renderer.draw(new Canvas(result));
- return result;
- }
-
- @TargetApi(Build.VERSION_CODES.P)
- public static Bitmap createHardwareBitmap(int width, int height, Renderer renderer) {
- if (!USE_HARDWARE_BITMAP) {
- return createSoftwareBitmap(width, height, renderer);
- }
-
- Picture picture = new Picture();
- renderer.draw(picture.beginRecording(width, height));
- picture.endRecording();
- return Bitmap.createBitmap(picture);
- }
-
- /**
- * Interface representing a bitmap draw operation.
- */
- public interface Renderer {
- void draw(Canvas out);
- }
+/**
+ * Interface representing a bitmap draw operation.
+ */
+public interface BitmapRenderer {
+
+ boolean USE_HARDWARE_BITMAP = Utilities.ATLEAST_P;
+
+ static Bitmap createSoftwareBitmap(int width, int height, BitmapRenderer renderer) {
+ Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ renderer.draw(new Canvas(result));
+ return result;
+ }
+
+ @TargetApi(Build.VERSION_CODES.P)
+ static Bitmap createHardwareBitmap(int width, int height, BitmapRenderer renderer) {
+ if (!USE_HARDWARE_BITMAP) {
+ return createSoftwareBitmap(width, height, renderer);
+ }
+
+ Picture picture = new Picture();
+ renderer.draw(picture.beginRecording(width, height));
+ picture.endRecording();
+ return Bitmap.createBitmap(picture);
+ }
+
+ void draw(Canvas out);
}
diff --git a/src/com/android/launcher3/graphics/DrawableFactory.java b/src/com/android/launcher3/graphics/DrawableFactory.java
index 34a4e2d77..bbc013d50 100644
--- a/src/com/android/launcher3/graphics/DrawableFactory.java
+++ b/src/com/android/launcher3/graphics/DrawableFactory.java
@@ -36,11 +36,12 @@ import com.android.launcher3.ItemInfoWithIcon;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.AllAppsBackgroundDrawable;
+import com.android.launcher3.util.ResourceBasedOverride;
/**
* Factory for creating new drawables.
*/
-public class DrawableFactory {
+public class DrawableFactory implements ResourceBasedOverride {
private static final String TAG = "DrawableFactory";
@@ -52,7 +53,7 @@ public class DrawableFactory {
public static DrawableFactory get(Context context) {
synchronized (LOCK) {
if (sInstance == null) {
- sInstance = Utilities.getOverrideObject(DrawableFactory.class,
+ sInstance = Overrides.getObject(DrawableFactory.class,
context.getApplicationContext(), R.string.drawable_factory_class);
}
return sInstance;
diff --git a/src/com/android/launcher3/logging/LoggerUtils.java b/src/com/android/launcher3/logging/LoggerUtils.java
index 83593aaa0..1c4327c49 100644
--- a/src/com/android/launcher3/logging/LoggerUtils.java
+++ b/src/com/android/launcher3/logging/LoggerUtils.java
@@ -144,7 +144,7 @@ public class LoggerUtils {
}
public static Target newItemTarget(View v, InstantAppResolver instantAppResolver) {
- return (v.getTag() instanceof ItemInfo)
+ return (v != null) && (v.getTag() instanceof ItemInfo)
? newItemTarget((ItemInfo) v.getTag(), instantAppResolver)
: newTarget(Target.Type.ITEM);
}
diff --git a/src/com/android/launcher3/logging/UserEventDispatcher.java b/src/com/android/launcher3/logging/UserEventDispatcher.java
index d1e1051ee..7087fdb78 100644
--- a/src/com/android/launcher3/logging/UserEventDispatcher.java
+++ b/src/com/android/launcher3/logging/UserEventDispatcher.java
@@ -37,7 +37,6 @@ import android.util.Log;
import android.view.View;
import android.view.ViewParent;
-import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DropTarget;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.R;
@@ -51,6 +50,7 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.InstantAppResolver;
import com.android.launcher3.util.LogConfig;
+import com.android.launcher3.util.ResourceBasedOverride;
import java.util.Locale;
import java.util.UUID;
@@ -61,7 +61,7 @@ import java.util.UUID;
*
* $ adb shell setprop log.tag.UserEvent VERBOSE
*/
-public class UserEventDispatcher {
+public class UserEventDispatcher implements ResourceBasedOverride {
private final static int MAXIMUM_VIEW_HIERARCHY_LEVEL = 5;
@@ -70,7 +70,7 @@ public class UserEventDispatcher {
FeatureFlags.IS_DOGFOOD_BUILD && Utilities.isPropertyEnabled(LogConfig.USEREVENT);
private static final String UUID_STORAGE = "uuid";
- public static UserEventDispatcher newInstance(Context context, DeviceProfile dp,
+ public static UserEventDispatcher newInstance(Context context,
UserEventDelegate delegate) {
SharedPreferences sharedPrefs = Utilities.getDevicePrefs(context);
String uuidStr = sharedPrefs.getString(UUID_STORAGE, null);
@@ -78,18 +78,16 @@ public class UserEventDispatcher {
uuidStr = UUID.randomUUID().toString();
sharedPrefs.edit().putString(UUID_STORAGE, uuidStr).apply();
}
- UserEventDispatcher ued = Utilities.getOverrideObject(UserEventDispatcher.class,
+ UserEventDispatcher ued = Overrides.getObject(UserEventDispatcher.class,
context.getApplicationContext(), R.string.user_event_dispatcher_class);
ued.mDelegate = delegate;
- ued.mIsInLandscapeMode = dp.isVerticalBarLayout();
- ued.mIsInMultiWindowMode = dp.isMultiWindowMode;
ued.mUuidStr = uuidStr;
ued.mInstantAppResolver = InstantAppResolver.newInstance(context);
return ued;
}
- public static UserEventDispatcher newInstance(Context context, DeviceProfile dp) {
- return newInstance(context, dp, null);
+ public static UserEventDispatcher newInstance(Context context) {
+ return newInstance(context, null);
}
public interface UserEventDelegate {
@@ -139,8 +137,6 @@ public class UserEventDispatcher {
private long mElapsedContainerMillis;
private long mElapsedSessionMillis;
private long mActionDurationMillis;
- private boolean mIsInMultiWindowMode;
- private boolean mIsInLandscapeMode;
private String mUuidStr;
protected InstantAppResolver mInstantAppResolver;
private boolean mAppOrTaskLaunch;
@@ -434,8 +430,6 @@ public class UserEventDispatcher {
public void dispatchUserEvent(LauncherEvent ev, Intent intent) {
mAppOrTaskLaunch = false;
- ev.isInLandscapeMode = mIsInLandscapeMode;
- ev.isInMultiWindowMode = mIsInMultiWindowMode;
ev.elapsedContainerMillis = SystemClock.uptimeMillis() - mElapsedContainerMillis;
ev.elapsedSessionMillis = SystemClock.uptimeMillis() - mElapsedSessionMillis;
@@ -455,8 +449,6 @@ public class UserEventDispatcher {
ev.elapsedContainerMillis,
ev.elapsedSessionMillis,
ev.actionDurationMillis);
- log += "\n isInLandscapeMode " + ev.isInLandscapeMode;
- log += "\n isInMultiWindowMode " + ev.isInMultiWindowMode;
log += "\n\n";
Log.d(TAG, log);
}
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 06da843f7..e82c8f100 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -478,15 +478,11 @@ public class LoaderTask implements Runnable {
}
info = new ShortcutInfo(pinnedShortcut, context);
final ShortcutInfo finalInfo = info;
- Provider<Bitmap> fallbackIconProvider = new Provider<Bitmap>() {
- @Override
- public Bitmap get() {
- // If the pinned deep shortcut is no longer published,
- // use the last saved icon instead of the default.
- return c.loadIcon(finalInfo)
- ? finalInfo.iconBitmap : null;
- }
- };
+ // If the pinned deep shortcut is no longer published,
+ // use the last saved icon instead of the default.
+ Provider<Bitmap> fallbackIconProvider = () ->
+ c.loadIcon(finalInfo) ? finalInfo.iconBitmap : null;
+
LauncherIcons li = LauncherIcons.obtain(context);
li.createShortcutIcon(pinnedShortcut,
true /* badged */, fallbackIconProvider).applyTo(info);
diff --git a/src/com/android/launcher3/notification/NotificationListener.java b/src/com/android/launcher3/notification/NotificationListener.java
index b527b6a8d..ac5aaf853 100644
--- a/src/com/android/launcher3/notification/NotificationListener.java
+++ b/src/com/android/launcher3/notification/NotificationListener.java
@@ -197,7 +197,7 @@ public class NotificationListener extends NotificationListenerService {
mNotificationBadgingObserver = new SettingsObserver.Secure(getContentResolver()) {
@Override
public void onSettingChanged(boolean isNotificationBadgingEnabled) {
- if (!isNotificationBadgingEnabled) {
+ if (!isNotificationBadgingEnabled && sIsConnected) {
requestUnbind();
}
}
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index be666a6e2..e157482c6 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -36,8 +36,10 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.animation.AccelerateDecelerateInterpolator;
+import android.widget.FrameLayout;
import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.R;
@@ -47,6 +49,7 @@ import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.graphics.TriangleShape;
import com.android.launcher3.util.Themes;
+import com.android.launcher3.views.BaseDragLayer;
import java.util.ArrayList;
import java.util.Collections;
@@ -134,7 +137,7 @@ public abstract class ArrowPopup extends AbstractFloatingView {
protected void reorderAndShow(int viewsToFlip) {
setVisibility(View.INVISIBLE);
mIsOpen = true;
- mLauncher.getDragLayer().addView(this);
+ getPopupContainer().addView(this);
orientAboutObject();
boolean reverseOrder = mIsAboveIcon;
@@ -163,7 +166,7 @@ public abstract class ArrowPopup extends AbstractFloatingView {
? R.dimen.popup_arrow_horizontal_center_start
: R.dimen.popup_arrow_horizontal_center_end);
final int halfArrowWidth = res.getDimensionPixelSize(R.dimen.popup_arrow_width) / 2;
- mLauncher.getDragLayer().addView(mArrow);
+ getPopupContainer().addView(mArrow);
DragLayer.LayoutParams arrowLp = (DragLayer.LayoutParams) mArrow.getLayoutParams();
if (mIsLeftAligned) {
mArrow.setX(getX() + arrowCenterOffset - halfArrowWidth);
@@ -179,7 +182,7 @@ public abstract class ArrowPopup extends AbstractFloatingView {
ShapeDrawable arrowDrawable = new ShapeDrawable(TriangleShape.create(
arrowLp.width, arrowLp.height, !mIsAboveIcon));
Paint arrowPaint = arrowDrawable.getPaint();
- arrowPaint.setColor(Themes.getAttrColor(mLauncher, R.attr.popupColorPrimary));
+ arrowPaint.setColor(Themes.getAttrColor(getContext(), R.attr.popupColorPrimary));
// The corner path effect won't be reflected in the shadow, but shouldn't be noticeable.
int radius = getResources().getDimensionPixelSize(R.dimen.popup_arrow_corner_radius);
arrowPaint.setPathEffect(new CornerPathEffect(radius));
@@ -222,7 +225,7 @@ public abstract class ArrowPopup extends AbstractFloatingView {
int height = getMeasuredHeight() + extraVerticalSpace;
getTargetObjectLocation(mTempRect);
- DragLayer dragLayer = mLauncher.getDragLayer();
+ InsettableFrameLayout dragLayer = getPopupContainer();
Rect insets = dragLayer.getInsets();
// Align left (right in RTL) if there is room.
@@ -301,12 +304,11 @@ public abstract class ArrowPopup extends AbstractFloatingView {
return;
}
- DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
- DragLayer.LayoutParams arrowLp = (DragLayer.LayoutParams) mArrow.getLayoutParams();
+ FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
+ FrameLayout.LayoutParams arrowLp = (FrameLayout.LayoutParams) mArrow.getLayoutParams();
if (mIsAboveIcon) {
arrowLp.gravity = lp.gravity = Gravity.BOTTOM;
- lp.bottomMargin =
- mLauncher.getDragLayer().getHeight() - y - getMeasuredHeight() - insets.top;
+ lp.bottomMargin = getPopupContainer().getHeight() - y - getMeasuredHeight() - insets.top;
arrowLp.bottomMargin = lp.bottomMargin - arrowLp.height - mArrayOffset - insets.bottom;
} else {
arrowLp.gravity = lp.gravity = Gravity.TOP;
@@ -320,7 +322,7 @@ public abstract class ArrowPopup extends AbstractFloatingView {
super.onLayout(changed, l, t, r, b);
// enforce contained is within screen
- DragLayer dragLayer = mLauncher.getDragLayer();
+ ViewGroup dragLayer = getPopupContainer();
if (getTranslationX() + l < 0 || getTranslationX() + r > dragLayer.getWidth()) {
// If we are still off screen, center horizontally too.
mGravity |= Gravity.CENTER_HORIZONTAL;
@@ -454,7 +456,11 @@ public abstract class ArrowPopup extends AbstractFloatingView {
}
mIsOpen = false;
mDeferContainerRemoval = false;
- mLauncher.getDragLayer().removeView(this);
- mLauncher.getDragLayer().removeView(mArrow);
+ getPopupContainer().removeView(this);
+ getPopupContainer().removeView(mArrow);
+ }
+
+ protected BaseDragLayer getPopupContainer() {
+ return mLauncher.getDragLayer();
}
}
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 172cf41e0..635e04371 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -55,7 +55,6 @@ import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.accessibility.ShortcutMenuAccessibilityDelegate;
import com.android.launcher3.badge.BadgeInfo;
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.logging.LoggerUtils;
@@ -65,8 +64,10 @@ import com.android.launcher3.notification.NotificationKeyData;
import com.android.launcher3.shortcuts.DeepShortcutManager;
import com.android.launcher3.shortcuts.DeepShortcutView;
import com.android.launcher3.shortcuts.ShortcutDragPreviewProvider;
+import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.touch.ItemLongClickListener;
import com.android.launcher3.util.PackageUserKey;
+import com.android.launcher3.views.BaseDragLayer;
import java.util.ArrayList;
import java.util.List;
@@ -146,10 +147,14 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource,
command, mOriginalIcon, ContainerType.DEEPSHORTCUTS);
}
+ public OnClickListener getItemClickListener() {
+ return ItemClickHandler.INSTANCE;
+ }
+
@Override
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- DragLayer dl = mLauncher.getDragLayer();
+ BaseDragLayer dl = getPopupContainer();
if (!dl.isEventOverView(this, ev)) {
mLauncher.getUserEventDispatcher().logActionTapOutside(
LoggerUtils.newContainerTarget(ContainerType.DEEPSHORTCUTS));
@@ -215,7 +220,7 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource,
}
@TargetApi(Build.VERSION_CODES.P)
- private void populateAndShow(final BubbleTextView originalIcon, final List<String> shortcutIds,
+ protected void populateAndShow(final BubbleTextView originalIcon, final List<String> shortcutIds,
final List<NotificationKeyData> notificationKeys, List<SystemShortcut> systemShortcuts) {
mNumNotifications = notificationKeys.size();
mOriginalIcon = originalIcon;
@@ -293,7 +298,7 @@ public class PopupContainerWithArrow extends ArrowPopup implements DragSource,
@Override
protected void getTargetObjectLocation(Rect outPos) {
- mLauncher.getDragLayer().getDescendantRectRelativeToSelf(mOriginalIcon, outPos);
+ getPopupContainer().getDescendantRectRelativeToSelf(mOriginalIcon, outPos);
outPos.top += mOriginalIcon.getPaddingTop();
outPos.left += mOriginalIcon.getPaddingLeft();
outPos.right -= mOriginalIcon.getPaddingRight();
diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutView.java b/src/com/android/launcher3/shortcuts/DeepShortcutView.java
index 9ad266bbc..7d0ea7bb9 100644
--- a/src/com/android/launcher3/shortcuts/DeepShortcutView.java
+++ b/src/com/android/launcher3/shortcuts/DeepShortcutView.java
@@ -121,7 +121,7 @@ public class DeepShortcutView extends FrameLayout {
mBubbleText.setText(usingLongLabel ? longLabel : mDetail.getShortLabel());
// TODO: Add the click handler to this view directly and not the child view.
- mBubbleText.setOnClickListener(ItemClickHandler.INSTANCE);
+ mBubbleText.setOnClickListener(container.getItemClickListener());
mBubbleText.setOnLongClickListener(container);
mBubbleText.setOnTouchListener(container);
}
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 55f850c8d..0e277eabc 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -43,6 +43,7 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.AnimatorSetBuilder;
+import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
@@ -515,6 +516,8 @@ public abstract class AbstractStateChangeTouchController
logReachedState(logAction, targetState);
}
mLauncher.getStateManager().goToState(targetState, false /* animated */);
+
+ AccessibilityManagerCompat.sendEventToTest(mLauncher, "TAPL_WENT_TO_STATE");
}
}
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index f2f5592e5..97f836f4d 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -162,7 +162,7 @@ public class ItemClickHandler {
*
* @param v The view that was clicked. Must be a tagged with a {@link ShortcutInfo}.
*/
- private static void onClickAppShortcut(View v, ShortcutInfo shortcut, Launcher launcher) {
+ public static void onClickAppShortcut(View v, ShortcutInfo shortcut, Launcher launcher) {
if (shortcut.isDisabled()) {
final int disabledFlags = shortcut.runtimeStatusFlags & ShortcutInfo.FLAG_DISABLED_MASK;
if ((disabledFlags &
diff --git a/src/com/android/launcher3/util/FloatRange.java b/src/com/android/launcher3/util/FloatRange.java
deleted file mode 100644
index 12772f365..000000000
--- a/src/com/android/launcher3/util/FloatRange.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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;
-
-/**
- * A mutable class for describing the range of two int values.
- */
-public class FloatRange {
-
- public float start, end;
-
- public FloatRange() { }
-
- public FloatRange(float s, float e) {
- set(s, e);
- }
-
- public void set(float s, float e) {
- start = s;
- end = e;
- }
-
- public boolean contains(float value) {
- return value >= start && value <= end;
- }
-}
diff --git a/src/com/android/launcher3/util/InstantAppResolver.java b/src/com/android/launcher3/util/InstantAppResolver.java
index 4485427f5..5dc7af855 100644
--- a/src/com/android/launcher3/util/InstantAppResolver.java
+++ b/src/com/android/launcher3/util/InstantAppResolver.java
@@ -23,7 +23,6 @@ import android.util.Log;
import com.android.launcher3.AppInfo;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import java.util.Collections;
import java.util.List;
@@ -31,10 +30,10 @@ import java.util.List;
/**
* A wrapper class to access instant app related APIs.
*/
-public class InstantAppResolver {
+public class InstantAppResolver implements ResourceBasedOverride {
public static InstantAppResolver newInstance(Context context) {
- return Utilities.getOverrideObject(
+ return Overrides.getObject(
InstantAppResolver.class, context, R.string.instant_app_resolver_class);
}
diff --git a/src/com/android/launcher3/util/ItemInfoMatcher.java b/src/com/android/launcher3/util/ItemInfoMatcher.java
index daedaef91..19cf6c1e5 100644
--- a/src/com/android/launcher3/util/ItemInfoMatcher.java
+++ b/src/com/android/launcher3/util/ItemInfoMatcher.java
@@ -18,7 +18,6 @@ package com.android.launcher3.util;
import android.content.ComponentName;
import android.os.UserHandle;
-import android.util.SparseLongArray;
import com.android.launcher3.FolderInfo;
import com.android.launcher3.ItemInfo;
@@ -32,14 +31,14 @@ import java.util.HashSet;
/**
* A utility class to check for {@link ItemInfo}
*/
-public abstract class ItemInfoMatcher {
+public interface ItemInfoMatcher {
- public abstract boolean matches(ItemInfo info, ComponentName cn);
+ boolean matches(ItemInfo info, ComponentName cn);
/**
* Filters {@param infos} to those satisfying the {@link #matches(ItemInfo, ComponentName)}.
*/
- public final HashSet<ItemInfo> filterItemInfos(Iterable<ItemInfo> infos) {
+ default HashSet<ItemInfo> filterItemInfos(Iterable<ItemInfo> infos) {
HashSet<ItemInfo> filtered = new HashSet<>();
for (ItemInfo i : infos) {
if (i instanceof ShortcutInfo) {
@@ -70,88 +69,43 @@ public abstract class ItemInfoMatcher {
/**
* Returns a new matcher with returns true if either this or {@param matcher} returns true.
*/
- public ItemInfoMatcher or(final ItemInfoMatcher matcher) {
- final ItemInfoMatcher that = this;
- return new ItemInfoMatcher() {
- @Override
- public boolean matches(ItemInfo info, ComponentName cn) {
- return that.matches(info, cn) || matcher.matches(info, cn);
- }
- };
+ default ItemInfoMatcher or(ItemInfoMatcher matcher) {
+ return (info, cn) -> matches(info, cn) || matcher.matches(info, cn);
}
/**
* Returns a new matcher with returns true if both this and {@param matcher} returns true.
*/
- public ItemInfoMatcher and(final ItemInfoMatcher matcher) {
- final ItemInfoMatcher that = this;
- return new ItemInfoMatcher() {
- @Override
- public boolean matches(ItemInfo info, ComponentName cn) {
- return that.matches(info, cn) && matcher.matches(info, cn);
- }
- };
+ default ItemInfoMatcher and(ItemInfoMatcher matcher) {
+ return (info, cn) -> matches(info, cn) && matcher.matches(info, cn);
}
/**
* Returns a new matcher which returns the opposite boolean value of the provided
* {@param matcher}.
*/
- public static ItemInfoMatcher not(final ItemInfoMatcher matcher) {
- return new ItemInfoMatcher() {
- @Override
- public boolean matches(ItemInfo info, ComponentName cn) {
- return !matcher.matches(info, cn);
- }
- };
+ static ItemInfoMatcher not(ItemInfoMatcher matcher) {
+ return (info, cn) -> !matcher.matches(info, cn);
}
- public static ItemInfoMatcher ofUser(final UserHandle user) {
- return new ItemInfoMatcher() {
- @Override
- public boolean matches(ItemInfo info, ComponentName cn) {
- return info.user.equals(user);
- }
- };
+ static ItemInfoMatcher ofUser(UserHandle user) {
+ return (info, cn) -> info.user.equals(user);
}
- public static ItemInfoMatcher ofComponents(
- final HashSet<ComponentName> components, final UserHandle user) {
- return new ItemInfoMatcher() {
- @Override
- public boolean matches(ItemInfo info, ComponentName cn) {
- return components.contains(cn) && info.user.equals(user);
- }
- };
+ static ItemInfoMatcher ofComponents(HashSet<ComponentName> components, UserHandle user) {
+ return (info, cn) -> components.contains(cn) && info.user.equals(user);
}
- public static ItemInfoMatcher ofPackages(
- final HashSet<String> packageNames, final UserHandle user) {
- return new ItemInfoMatcher() {
- @Override
- public boolean matches(ItemInfo info, ComponentName cn) {
- return packageNames.contains(cn.getPackageName()) && info.user.equals(user);
- }
- };
+ static ItemInfoMatcher ofPackages(HashSet<String> packageNames, UserHandle user) {
+ return (info, cn) -> packageNames.contains(cn.getPackageName()) && info.user.equals(user);
}
- public static ItemInfoMatcher ofShortcutKeys(final HashSet<ShortcutKey> keys) {
- return new ItemInfoMatcher() {
- @Override
- public boolean matches(ItemInfo info, ComponentName cn) {
- return info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT &&
+ static ItemInfoMatcher ofShortcutKeys(HashSet<ShortcutKey> keys) {
+ return (info, cn) -> info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT &&
keys.contains(ShortcutKey.fromItemInfo(info));
- }
- };
}
- public static ItemInfoMatcher ofItemIds(
- final LongArrayMap<Boolean> ids, final Boolean matchDefault) {
- return new ItemInfoMatcher() {
- @Override
- public boolean matches(ItemInfo info, ComponentName cn) {
- return ids.get(info.id, matchDefault);
- }
- };
+ static ItemInfoMatcher ofItemIds(LongArrayMap<Boolean> ids, Boolean matchDefault) {
+ return (info, cn) -> ids.get(info.id, matchDefault);
}
}
diff --git a/src/com/android/launcher3/util/MainThreadInitializedObject.java b/src/com/android/launcher3/util/MainThreadInitializedObject.java
new file mode 100644
index 000000000..5747db1c1
--- /dev/null
+++ b/src/com/android/launcher3/util/MainThreadInitializedObject.java
@@ -0,0 +1,60 @@
+/*
+ * 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.util;
+
+import android.content.Context;
+import android.os.Looper;
+
+import com.android.launcher3.MainThreadExecutor;
+
+import java.util.concurrent.ExecutionException;
+
+/**
+ * Utility class for defining singletons which are initiated on main thread.
+ */
+public class MainThreadInitializedObject<T> {
+
+ private final ObjectProvider<T> mProvider;
+ private T mValue;
+
+ public MainThreadInitializedObject(ObjectProvider<T> provider) {
+ mProvider = provider;
+ }
+
+ public T get(Context context) {
+ if (mValue == null) {
+ if (Looper.myLooper() == Looper.getMainLooper()) {
+ mValue = mProvider.get(context.getApplicationContext());
+ } else {
+ try {
+ return new MainThreadExecutor().submit(() -> get(context)).get();
+ } catch (InterruptedException|ExecutionException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ return mValue;
+ }
+
+ public T getNoCreate() {
+ return mValue;
+ }
+
+ public interface ObjectProvider<T> {
+
+ T get(Context context);
+ }
+}
diff --git a/src/com/android/launcher3/util/Provider.java b/src/com/android/launcher3/util/Provider.java
index 1cdd8d6aa..4a54c0f05 100644
--- a/src/com/android/launcher3/util/Provider.java
+++ b/src/com/android/launcher3/util/Provider.java
@@ -19,20 +19,15 @@ package com.android.launcher3.util;
/**
* Utility class to allow lazy initialization of objects.
*/
-public abstract class Provider<T> {
+public interface Provider<T> {
/**
* Initializes and returns the object. This may contain expensive operations not suitable
* to UI thread.
*/
- public abstract T get();
+ T get();
- public static <T> Provider<T> of (final T value) {
- return new Provider<T>() {
- @Override
- public T get() {
- return value;
- }
- };
+ static <T> Provider<T> of (T value) {
+ return() -> value;
}
}
diff --git a/src/com/android/launcher3/util/ResourceBasedOverride.java b/src/com/android/launcher3/util/ResourceBasedOverride.java
new file mode 100644
index 000000000..e2c4992a4
--- /dev/null
+++ b/src/com/android/launcher3/util/ResourceBasedOverride.java
@@ -0,0 +1,54 @@
+/*
+ * 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.util;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * An interface to indicate that a class is dynamically loaded using resource overlay, hence its
+ * class name and constructor should be preserved by proguard
+ */
+public interface ResourceBasedOverride {
+
+ class Overrides {
+
+ private static final String TAG = "Overrides";
+
+ public static <T extends ResourceBasedOverride> T getObject(
+ Class<T> clazz, Context context, int resId) {
+ String className = context.getString(resId);
+ if (!TextUtils.isEmpty(className)) {
+ try {
+ Class<?> cls = Class.forName(className);
+ return (T) cls.getDeclaredConstructor(Context.class).newInstance(context);
+ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
+ | ClassCastException | NoSuchMethodException | InvocationTargetException e) {
+ Log.e(TAG, "Bad overriden class", e);
+ }
+ }
+
+ try {
+ return clazz.newInstance();
+ } catch (InstantiationException|IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+}
diff --git a/src/com/android/launcher3/views/ActivityContext.java b/src/com/android/launcher3/views/ActivityContext.java
new file mode 100644
index 000000000..04100af7f
--- /dev/null
+++ b/src/com/android/launcher3/views/ActivityContext.java
@@ -0,0 +1,43 @@
+/*
+ * 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.views;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.view.ContextThemeWrapper;
+
+/**
+ * An interface to be used along with a context. This allows a generic class to depend on Context
+ * subclass instead of an Activity.
+ */
+public interface ActivityContext {
+
+ default boolean finishAutoCancelActionMode() {
+ return false;
+ }
+
+ BaseDragLayer getDragLayer();
+
+ static ActivityContext lookupContext(Context context) {
+ if (context instanceof ActivityContext) {
+ return (ActivityContext) context;
+ } else if (context instanceof ContextThemeWrapper) {
+ return lookupContext(((ContextWrapper) context).getBaseContext());
+ } else {
+ throw new IllegalArgumentException("Cannot find ActivityContext in parent tree");
+ }
+ }
+}
diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java
index 8457b2bcd..e8a879fcc 100644
--- a/src/com/android/launcher3/views/BaseDragLayer.java
+++ b/src/com/android/launcher3/views/BaseDragLayer.java
@@ -28,8 +28,6 @@ import android.view.accessibility.AccessibilityEvent;
import android.widget.FrameLayout;
import com.android.launcher3.AbstractFloatingView;
-import com.android.launcher3.BaseActivity;
-import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.MultiValueAlpha;
@@ -41,7 +39,8 @@ import java.util.ArrayList;
/**
* A viewgroup with utility methods for drag-n-drop and touch interception
*/
-public abstract class BaseDragLayer<T extends BaseDraggingActivity> extends InsettableFrameLayout {
+public abstract class BaseDragLayer<T extends Context & ActivityContext>
+ extends InsettableFrameLayout {
protected final int[] mTmpXY = new int[2];
protected final Rect mHitRect = new Rect();
@@ -55,7 +54,7 @@ public abstract class BaseDragLayer<T extends BaseDraggingActivity> extends Inse
public BaseDragLayer(Context context, AttributeSet attrs, int alphaChannelCount) {
super(context, attrs);
- mActivity = (T) BaseActivity.fromContext(context);
+ mActivity = (T) ActivityContext.lookupContext(context);
mMultiValueAlpha = new MultiValueAlpha(this, alphaChannelCount);
}
diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java
index db4c49226..dc6d2ff09 100644
--- a/src/com/android/launcher3/views/OptionsPopupView.java
+++ b/src/com/android/launcher3/views/OptionsPopupView.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.AttributeSet;
@@ -94,7 +95,7 @@ public class OptionsPopupView extends ArrowPopup
if (ev.getAction() != MotionEvent.ACTION_DOWN) {
return false;
}
- if (mLauncher.getDragLayer().isEventOverView(this, ev)) {
+ if (getPopupContainer().isEventOverView(this, ev)) {
return false;
}
close(true);
@@ -133,6 +134,11 @@ public class OptionsPopupView extends ArrowPopup
popup.reorderAndShow(popup.getChildCount());
}
+ @VisibleForTesting
+ public static OptionsPopupView getOptionsPopup(Launcher launcher) {
+ return launcher.findViewById(R.id.deep_shortcuts_container);
+ }
+
public static void showDefaultOptions(Launcher launcher, float x, float y) {
float halfSize = launcher.getResources().getDimension(R.dimen.options_menu_thumb_size) / 2;
if (x < 0 || y < 0) {
diff --git a/src/com/android/launcher3/widget/WidgetsFullSheet.java b/src/com/android/launcher3/widget/WidgetsFullSheet.java
index e94d81d75..b49322832 100644
--- a/src/com/android/launcher3/widget/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsFullSheet.java
@@ -20,6 +20,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.graphics.Rect;
+import android.support.annotation.VisibleForTesting;
import android.util.AttributeSet;
import android.util.Pair;
import android.view.LayoutInflater;
@@ -224,6 +225,11 @@ public class WidgetsFullSheet extends BaseWidgetSheet
return sheet;
}
+ @VisibleForTesting
+ public static WidgetsRecyclerView getWidgetsView(Launcher launcher) {
+ return launcher.findViewById(R.id.widgets_list_view);
+ }
+
@Override
protected int getElementsRowCount() {
return mAdapter.getItemCount();