Merge "Merging from ub-launcher3-rvc-dev @ build 6396980" into rvc-dev am: ce6f43f0df am: 2e9cdc6e40
Change-Id: Idca218a429c4f9727ab47a1322b87465a1b28316
This commit is contained in:
@@ -63,14 +63,14 @@ message Target {
|
||||
|
||||
// Note: proto does not support duplicate enum values, even if they belong to different enum type.
|
||||
// Hence "FROM" and "TO" prefix added.
|
||||
enum FromFolderLabelState{
|
||||
enum FromFolderLabelState {
|
||||
FROM_FOLDER_LABEL_STATE_UNSPECIFIED = 0;
|
||||
FROM_EMPTY = 1;
|
||||
FROM_CUSTOM = 2;
|
||||
FROM_SUGGESTED = 3;
|
||||
}
|
||||
|
||||
enum ToFolderLabelState{
|
||||
enum ToFolderLabelState {
|
||||
TO_FOLDER_LABEL_STATE_UNSPECIFIED = 0;
|
||||
TO_SUGGESTION0_WITH_VALID_PRIMARY = 1;
|
||||
TO_SUGGESTION1_WITH_VALID_PRIMARY = 2;
|
||||
@@ -79,10 +79,14 @@ message Target {
|
||||
TO_SUGGESTION2_WITH_EMPTY_PRIMARY = 5;
|
||||
TO_SUGGESTION3_WITH_VALID_PRIMARY = 6;
|
||||
TO_SUGGESTION3_WITH_EMPTY_PRIMARY = 7;
|
||||
TO_EMPTY_WITH_VALID_SUGGESTIONS = 8;
|
||||
TO_EMPTY_WITH_VALID_SUGGESTIONS = 8 [deprecated = true];
|
||||
TO_EMPTY_WITH_VALID_PRIMARY = 15;
|
||||
TO_EMPTY_WITH_VALID_SUGGESTIONS_AND_EMPTY_PRIMARY = 16;
|
||||
TO_EMPTY_WITH_EMPTY_SUGGESTIONS = 9;
|
||||
TO_EMPTY_WITH_SUGGESTIONS_DISABLED = 10;
|
||||
TO_CUSTOM_WITH_VALID_SUGGESTIONS = 11;
|
||||
TO_CUSTOM_WITH_VALID_SUGGESTIONS = 11 [deprecated = true];
|
||||
TO_CUSTOM_WITH_VALID_PRIMARY = 17;
|
||||
TO_CUSTOM_WITH_VALID_SUGGESTIONS_AND_EMPTY_PRIMARY = 18;
|
||||
TO_CUSTOM_WITH_EMPTY_SUGGESTIONS = 12;
|
||||
TO_CUSTOM_WITH_SUGGESTIONS_DISABLED = 13;
|
||||
UNCHANGED = 14;
|
||||
|
||||
+4
-6
@@ -18,10 +18,9 @@ package com.android.launcher3.appprediction;
|
||||
|
||||
import static com.android.quickstep.InstantAppResolverImpl.COMPONENT_CLASS_MARKER;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.ItemInfoWithIcon;
|
||||
import com.android.launcher3.allapps.AllAppsStore;
|
||||
import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
|
||||
public class ComponentKeyMapper {
|
||||
@@ -57,9 +56,8 @@ public class ComponentKeyMapper {
|
||||
return item;
|
||||
} else if (getComponentClass().equals(COMPONENT_CLASS_MARKER)) {
|
||||
return mCache.getInstantApp(componentKey.componentName.getPackageName());
|
||||
} else if (componentKey instanceof ShortcutKey) {
|
||||
return mCache.getShortcutInfo((ShortcutKey) componentKey);
|
||||
} else {
|
||||
return mCache.getShortcutInfo(componentKey);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-4
@@ -38,13 +38,14 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.UiThread;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.allapps.AllAppsStore;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import com.android.launcher3.shortcuts.ShortcutRequest;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.launcher3.util.InstantAppResolver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -76,7 +77,7 @@ public class DynamicItemCache {
|
||||
private final Runnable mOnUpdateCallback;
|
||||
private final IconCache mIconCache;
|
||||
|
||||
private final Map<ShortcutKey, WorkspaceItemInfo> mShortcuts;
|
||||
private final Map<ComponentKey, WorkspaceItemInfo> mShortcuts;
|
||||
private final Map<String, InstantAppItemInfo> mInstantApps;
|
||||
|
||||
public DynamicItemCache(Context context, Runnable onUpdateCallback) {
|
||||
@@ -230,7 +231,7 @@ public class DynamicItemCache {
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public WorkspaceItemInfo getShortcutInfo(ShortcutKey key) {
|
||||
public WorkspaceItemInfo getShortcutInfo(ComponentKey key) {
|
||||
return mShortcuts.get(key);
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -21,9 +21,9 @@ import static com.android.quickstep.InstantAppResolverImpl.COMPONENT_CLASS_MARKE
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
|
||||
public class InstantAppItemInfo extends AppInfo {
|
||||
|
||||
@@ -44,7 +44,7 @@ public class InstantAppItemInfo extends AppInfo {
|
||||
workspaceItemInfo.status = WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON
|
||||
| WorkspaceItemInfo.FLAG_RESTORE_STARTED
|
||||
| WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI;
|
||||
workspaceItemInfo.intent.setPackage(componentName.getPackageName());
|
||||
workspaceItemInfo.getIntent().setPackage(componentName.getPackageName());
|
||||
return workspaceItemInfo;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -38,18 +38,14 @@ import android.widget.LinearLayout;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.ItemInfoWithIcon;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.allapps.AllAppsStore;
|
||||
import com.android.launcher3.allapps.FloatingHeaderRow;
|
||||
import com.android.launcher3.allapps.FloatingHeaderView;
|
||||
@@ -60,6 +56,10 @@ import com.android.launcher3.keyboard.FocusIndicatorHelper;
|
||||
import com.android.launcher3.keyboard.FocusIndicatorHelper.SimpleFocusIndicatorHelper;
|
||||
import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider;
|
||||
import com.android.launcher3.model.AppLaunchTracker;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.touch.ItemClickHandler;
|
||||
import com.android.launcher3.touch.ItemLongClickListener;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
|
||||
+2
-2
@@ -28,8 +28,6 @@ import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.InvariantDeviceProfile.OnIDPChangeListener;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.ItemInfoWithIcon;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
@@ -40,6 +38,8 @@ import com.android.launcher3.allapps.AllAppsContainerView;
|
||||
import com.android.launcher3.allapps.AllAppsStore.OnUpdateListener;
|
||||
import com.android.launcher3.hybridhotseat.HotseatPredictionController;
|
||||
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
|
||||
+4
-3
@@ -27,16 +27,16 @@ import android.view.View;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import com.android.launcher3.CellLayout;
|
||||
import com.android.launcher3.FolderInfo;
|
||||
import com.android.launcher3.Hotseat;
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.uioverrides.QuickstepLauncher;
|
||||
import com.android.launcher3.util.ActivityTracker;
|
||||
import com.android.launcher3.util.GridOccupancy;
|
||||
@@ -200,6 +200,7 @@ public class HotseatEduController {
|
||||
pageId = LauncherSettings.Settings.call(mLauncher.getContentResolver(),
|
||||
LauncherSettings.Settings.METHOD_NEW_SCREEN_ID)
|
||||
.getInt(LauncherSettings.Settings.EXTRA_VALUE);
|
||||
mNewScreens = IntArray.wrap(pageId);
|
||||
}
|
||||
for (int i = 0; i < mLauncher.getDeviceProfile().inv.numHotseatIcons; i++) {
|
||||
View child = mHotseat.getChildAt(i, 0);
|
||||
|
||||
+10
-4
@@ -16,8 +16,7 @@
|
||||
package com.android.launcher3.hybridhotseat;
|
||||
|
||||
import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType
|
||||
.HYBRID_HOTSEAT_CANCELED;
|
||||
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.HYBRID_HOTSEAT_CANCELED;
|
||||
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.content.Context;
|
||||
@@ -34,10 +33,11 @@ import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Insettable;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.uioverrides.PredictedAppIcon;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.views.AbstractSlideInView;
|
||||
@@ -153,6 +153,12 @@ public class HotseatEduDialog extends AbstractSlideInView implements Insettable
|
||||
private void logUserAction(boolean migrated, int pageIndex) {
|
||||
LauncherLogProto.Action action = new LauncherLogProto.Action();
|
||||
LauncherLogProto.Target target = new LauncherLogProto.Target();
|
||||
|
||||
int hotseatItemsCount = mLauncher.getHotseat().getShortcutsAndWidgets().getChildCount();
|
||||
// -1 to exclude smart space
|
||||
int workspaceItemCount = mLauncher.getWorkspace().getScreenWithId(
|
||||
Workspace.FIRST_SCREEN_ID).getShortcutsAndWidgets().getChildCount() - 1;
|
||||
|
||||
action.type = LauncherLogProto.Action.Type.TOUCH;
|
||||
action.touch = LauncherLogProto.Action.Touch.TAP;
|
||||
target.containerType = LauncherLogProto.ContainerType.TIP;
|
||||
@@ -162,7 +168,7 @@ public class HotseatEduDialog extends AbstractSlideInView implements Insettable
|
||||
target.rank = MIGRATION_EXPERIMENT_IDENTIFIER;
|
||||
// encoding migration type on pageIndex
|
||||
target.pageIndex = pageIndex;
|
||||
target.cardinality = HotseatPredictionController.MAX_ITEMS_FOR_MIGRATION;
|
||||
target.cardinality = (workspaceItemCount * 1000) + hotseatItemsCount;
|
||||
LauncherLogProto.LauncherEvent event = newLauncherEvent(action, target);
|
||||
UserEventDispatcher.newInstance(getContext()).dispatchUserEvent(event, null);
|
||||
}
|
||||
|
||||
+142
-11
@@ -31,6 +31,7 @@ import android.app.prediction.AppTargetEvent;
|
||||
import android.app.prediction.AppTargetId;
|
||||
import android.content.ComponentName;
|
||||
import android.os.Bundle;
|
||||
import android.os.Process;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
@@ -39,22 +40,18 @@ import android.view.ViewGroup;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.CellLayout;
|
||||
import com.android.launcher3.DragSource;
|
||||
import com.android.launcher3.DropTarget;
|
||||
import com.android.launcher3.FolderInfo;
|
||||
import com.android.launcher3.Hotseat;
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.ItemInfoWithIcon;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.allapps.AllAppsStore;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.appprediction.ComponentKeyMapper;
|
||||
@@ -64,6 +61,12 @@ import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.logging.FileLog;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import com.android.launcher3.touch.ItemLongClickListener;
|
||||
@@ -76,6 +79,7 @@ import com.android.launcher3.util.ComponentKey;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
@@ -91,18 +95,19 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
private static final String TAG = "PredictiveHotseat";
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
public static final int MAX_ITEMS_FOR_MIGRATION = DeviceConfig.getInt(
|
||||
DeviceFlag.NAMESPACE_LAUNCHER, "max_homepage_items_for_migration", 5);
|
||||
|
||||
//TODO: replace this with AppTargetEvent.ACTION_UNPIN (b/144119543)
|
||||
private static final int APPTARGET_ACTION_UNPIN = 4;
|
||||
|
||||
private static final String PREDICTED_ITEMS_CACHE_KEY = "predicted_item_keys";
|
||||
|
||||
private static final String APP_LOCATION_HOTSEAT = "hotseat";
|
||||
private static final String APP_LOCATION_WORKSPACE = "workspace";
|
||||
|
||||
private static final String BUNDLE_KEY_HOTSEAT = "hotseat_apps";
|
||||
private static final String BUNDLE_KEY_WORKSPACE = "workspace_apps";
|
||||
|
||||
private static final String BUNDLE_KEY_PIN_EVENTS = "pin_events";
|
||||
|
||||
private static final String PREDICTION_CLIENT = "hotseat";
|
||||
private DropTarget.DragObject mDragObject;
|
||||
private int mHotSeatItemsCount;
|
||||
@@ -119,6 +124,7 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
private AllAppsStore mAllAppsStore;
|
||||
private AnimatorSet mIconRemoveAnimators;
|
||||
private boolean mUIUpdatePaused = false;
|
||||
private boolean mRequiresCacheUpdate = false;
|
||||
|
||||
private HotseatEduController mHotseatEduController;
|
||||
|
||||
@@ -145,6 +151,7 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
if (mHotseat.isAttachedToWindow()) {
|
||||
onViewAttachedToWindow(mHotseat);
|
||||
}
|
||||
showCachedItems();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -294,17 +301,57 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
mAppPredictor.requestPredictionUpdate();
|
||||
}
|
||||
|
||||
private void showCachedItems() {
|
||||
ArrayList<ComponentKey> componentKeys = getCachedComponentKeys();
|
||||
mComponentKeyMappers.clear();
|
||||
for (ComponentKey key : componentKeys) {
|
||||
mComponentKeyMappers.add(new ComponentKeyMapper(key, mDynamicItemCache));
|
||||
}
|
||||
updateDependencies();
|
||||
fillGapsWithPrediction();
|
||||
}
|
||||
|
||||
private Bundle getAppPredictionContextExtra() {
|
||||
Bundle bundle = new Bundle();
|
||||
|
||||
//TODO: remove this way of reporting items
|
||||
bundle.putParcelableArrayList(BUNDLE_KEY_HOTSEAT,
|
||||
getPinnedAppTargetsInViewGroup((mHotseat.getShortcutsAndWidgets())));
|
||||
bundle.putParcelableArrayList(BUNDLE_KEY_WORKSPACE, getPinnedAppTargetsInViewGroup(
|
||||
mLauncher.getWorkspace().getScreenWithId(
|
||||
Workspace.FIRST_SCREEN_ID).getShortcutsAndWidgets()));
|
||||
|
||||
ArrayList<AppTargetEvent> pinEvents = new ArrayList<>();
|
||||
getPinEventsForViewGroup(pinEvents, mHotseat.getShortcutsAndWidgets(),
|
||||
APP_LOCATION_HOTSEAT);
|
||||
getPinEventsForViewGroup(pinEvents, mLauncher.getWorkspace().getScreenWithId(
|
||||
Workspace.FIRST_SCREEN_ID).getShortcutsAndWidgets(), APP_LOCATION_WORKSPACE);
|
||||
bundle.putParcelableArrayList(BUNDLE_KEY_PIN_EVENTS, pinEvents);
|
||||
|
||||
return bundle;
|
||||
}
|
||||
|
||||
private ArrayList<AppTargetEvent> getPinEventsForViewGroup(ArrayList<AppTargetEvent> pinEvents,
|
||||
ViewGroup views, String root) {
|
||||
for (int i = 0; i < views.getChildCount(); i++) {
|
||||
View child = views.getChildAt(i);
|
||||
final AppTargetEvent event;
|
||||
if (child.getTag() instanceof ItemInfo && getAppTargetFromInfo(
|
||||
(ItemInfo) child.getTag()) != null) {
|
||||
ItemInfo info = (ItemInfo) child.getTag();
|
||||
event = wrapAppTargetWithLocation(getAppTargetFromInfo(info),
|
||||
AppTargetEvent.ACTION_PIN, info);
|
||||
} else {
|
||||
CellLayout.LayoutParams params = (CellLayout.LayoutParams) views.getLayoutParams();
|
||||
event = wrapAppTargetWithLocation(getBlockAppTarget(), AppTargetEvent.ACTION_PIN,
|
||||
root, 0, params.cellX, params.cellY, params.cellHSpan, params.cellVSpan);
|
||||
}
|
||||
pinEvents.add(event);
|
||||
}
|
||||
return pinEvents;
|
||||
}
|
||||
|
||||
|
||||
private ArrayList<AppTarget> getPinnedAppTargetsInViewGroup(ViewGroup viewGroup) {
|
||||
ArrayList<AppTarget> pinnedApps = new ArrayList<>();
|
||||
for (int i = 0; i < viewGroup.getChildCount(); i++) {
|
||||
@@ -320,6 +367,7 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
private void setPredictedApps(List<AppTarget> appTargets) {
|
||||
mComponentKeyMappers.clear();
|
||||
StringBuilder predictionLog = new StringBuilder("predictedApps: [\n");
|
||||
ArrayList<ComponentKey> componentKeys = new ArrayList<>();
|
||||
for (AppTarget appTarget : appTargets) {
|
||||
ComponentKey key;
|
||||
if (appTarget.getShortcutInfo() != null) {
|
||||
@@ -328,6 +376,7 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
key = new ComponentKey(new ComponentName(appTarget.getPackageName(),
|
||||
appTarget.getClassName()), appTarget.getUser());
|
||||
}
|
||||
componentKeys.add(key);
|
||||
predictionLog.append(key.toString());
|
||||
predictionLog.append(",rank:");
|
||||
predictionLog.append(appTarget.getRank());
|
||||
@@ -342,6 +391,35 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
} else if (mHotseatEduController != null) {
|
||||
mHotseatEduController.setPredictedApps(mapToWorkspaceItemInfo(mComponentKeyMappers));
|
||||
}
|
||||
// should invalidate cache if AiAi sends empty list of AppTargets
|
||||
if (appTargets.isEmpty()) {
|
||||
mRequiresCacheUpdate = true;
|
||||
}
|
||||
cachePredictionComponentKeys(componentKeys);
|
||||
}
|
||||
|
||||
private void cachePredictionComponentKeys(ArrayList<ComponentKey> componentKeys) {
|
||||
if (!mRequiresCacheUpdate) return;
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (ComponentKey componentKey : componentKeys) {
|
||||
builder.append(componentKey);
|
||||
builder.append("\n");
|
||||
}
|
||||
mLauncher.getDevicePrefs().edit().putString(PREDICTED_ITEMS_CACHE_KEY,
|
||||
builder.toString()).apply();
|
||||
mRequiresCacheUpdate = false;
|
||||
}
|
||||
|
||||
private ArrayList<ComponentKey> getCachedComponentKeys() {
|
||||
String cachedBlob = mLauncher.getDevicePrefs().getString(PREDICTED_ITEMS_CACHE_KEY, "");
|
||||
ArrayList<ComponentKey> results = new ArrayList<>();
|
||||
for (String line : cachedBlob.split("\n")) {
|
||||
ComponentKey key = ComponentKey.fromString(line);
|
||||
if (key != null) {
|
||||
results.add(key);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private void updateDependencies() {
|
||||
@@ -367,6 +445,7 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
icon.pin(workspaceItemInfo);
|
||||
AppTarget appTarget = getAppTargetFromItemInfo(workspaceItemInfo);
|
||||
notifyItemAction(appTarget, APP_LOCATION_HOTSEAT, AppTargetEvent.ACTION_PIN);
|
||||
mRequiresCacheUpdate = true;
|
||||
}
|
||||
|
||||
private List<WorkspaceItemInfo> mapToWorkspaceItemInfo(
|
||||
@@ -533,6 +612,7 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
}
|
||||
mDragObject = null;
|
||||
fillGapsWithPrediction(true, this::removeOutlineDrawings);
|
||||
mRequiresCacheUpdate = true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -606,6 +686,9 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
if (isReady()) return;
|
||||
int hotseatItemsCount = mHotseat.getShortcutsAndWidgets().getChildCount();
|
||||
|
||||
int maxItems = DeviceConfig.getInt(
|
||||
DeviceFlag.NAMESPACE_LAUNCHER, "max_homepage_items_for_migration", 5);
|
||||
|
||||
// -1 to exclude smart space
|
||||
int workspaceItemCount = mLauncher.getWorkspace().getScreenWithId(
|
||||
Workspace.FIRST_SCREEN_ID).getShortcutsAndWidgets().getChildCount() - 1;
|
||||
@@ -614,7 +697,7 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
// open spots in their hotseat and have more than maxItems in their hotseat + workspace
|
||||
|
||||
if (hotseatItemsCount == mHotSeatItemsCount && workspaceItemCount + hotseatItemsCount
|
||||
> MAX_ITEMS_FOR_MIGRATION) {
|
||||
> maxItems) {
|
||||
mLauncher.getSharedPrefs().edit().putBoolean(HotseatEduController.KEY_HOTSEAT_EDU_SEEN,
|
||||
true).apply();
|
||||
|
||||
@@ -626,8 +709,8 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
|
||||
// temporarily encode details in log target (go/hotseat_migration)
|
||||
target.rank = 2;
|
||||
target.cardinality = MAX_ITEMS_FOR_MIGRATION;
|
||||
target.pageIndex = (workspaceItemCount * 1000) + hotseatItemsCount;
|
||||
target.cardinality = (workspaceItemCount * 1000) + hotseatItemsCount;
|
||||
target.pageIndex = maxItems;
|
||||
LauncherLogProto.LauncherEvent event = newLauncherEvent(action, target);
|
||||
UserEventDispatcher.newInstance(mLauncher).dispatchUserEvent(event, null);
|
||||
|
||||
@@ -689,4 +772,52 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
return new AppTarget.Builder(new AppTargetId("app:" + cn.getPackageName()),
|
||||
cn.getPackageName(), info.user).setClassName(cn.getClassName()).build();
|
||||
}
|
||||
|
||||
private AppTarget getAppTargetFromInfo(ItemInfo info) {
|
||||
if (info == null) return null;
|
||||
if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET
|
||||
&& info instanceof LauncherAppWidgetInfo
|
||||
&& ((LauncherAppWidgetInfo) info).providerName != null) {
|
||||
ComponentName cn = ((LauncherAppWidgetInfo) info).providerName;
|
||||
return new AppTarget.Builder(new AppTargetId("widget:" + cn.getPackageName()),
|
||||
cn.getPackageName(), info.user).setClassName(cn.getClassName()).build();
|
||||
} else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION
|
||||
&& info.getTargetComponent() != null) {
|
||||
ComponentName cn = info.getTargetComponent();
|
||||
return new AppTarget.Builder(new AppTargetId("app:" + cn.getPackageName()),
|
||||
cn.getPackageName(), info.user).setClassName(cn.getClassName()).build();
|
||||
} else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT
|
||||
&& info instanceof WorkspaceItemInfo) {
|
||||
ShortcutKey shortcutKey = ShortcutKey.fromItemInfo(info);
|
||||
//TODO: switch to using full shortcut info
|
||||
return new AppTarget.Builder(new AppTargetId("shortcut:" + shortcutKey.getId()),
|
||||
shortcutKey.componentName.getPackageName(), shortcutKey.user).build();
|
||||
} else if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
|
||||
return new AppTarget.Builder(new AppTargetId("folder:" + info.id),
|
||||
mLauncher.getPackageName(), info.user).build();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private AppTargetEvent wrapAppTargetWithLocation(AppTarget target, int action, ItemInfo info) {
|
||||
return wrapAppTargetWithLocation(target, action,
|
||||
info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT
|
||||
? APP_LOCATION_HOTSEAT : APP_LOCATION_WORKSPACE, info.screenId, info.cellX,
|
||||
info.cellY, info.spanX, info.spanY);
|
||||
}
|
||||
|
||||
private AppTargetEvent wrapAppTargetWithLocation(AppTarget target, int action, String root,
|
||||
int screenId, int x, int y, int spanX, int spanY) {
|
||||
return new AppTargetEvent.Builder(target, action).setLaunchLocation(
|
||||
String.format(Locale.ENGLISH, "%s/%d/[%d,%d]/[%d,%d]", root, screenId, x, y, spanX,
|
||||
spanY)).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper method to generate an AppTarget that's used to communicate workspace layout
|
||||
*/
|
||||
private AppTarget getBlockAppTarget() {
|
||||
return new AppTarget.Builder(new AppTargetId("block"),
|
||||
mLauncher.getPackageName(), Process.myUserHandle()).build();
|
||||
}
|
||||
}
|
||||
|
||||
+7
-5
@@ -33,14 +33,14 @@ import androidx.core.graphics.ColorUtils;
|
||||
|
||||
import com.android.launcher3.CellLayout;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
||||
import com.android.launcher3.graphics.IconPalette;
|
||||
import com.android.launcher3.hybridhotseat.HotseatPredictionController;
|
||||
import com.android.launcher3.icons.IconNormalizer;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.touch.ItemClickHandler;
|
||||
import com.android.launcher3.touch.ItemLongClickListener;
|
||||
import com.android.launcher3.views.DoubleShadowBubbleTextView;
|
||||
@@ -136,9 +136,11 @@ public class PredictedAppIcon extends DoubleShadowBubbleTextView implements
|
||||
|
||||
@Override
|
||||
public void addSupportedAccessibilityActions(AccessibilityNodeInfo accessibilityNodeInfo) {
|
||||
accessibilityNodeInfo.addAction(
|
||||
new AccessibilityNodeInfo.AccessibilityAction(PIN_PREDICTION,
|
||||
getContext().getText(R.string.pin_prediction)));
|
||||
if (!mIsPinned) {
|
||||
accessibilityNodeInfo.addAction(
|
||||
new AccessibilityNodeInfo.AccessibilityAction(PIN_PREDICTION,
|
||||
getContext().getText(R.string.pin_prediction)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-2
@@ -28,14 +28,14 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.hybridhotseat.HotseatPredictionController;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
import com.android.launcher3.uioverrides.touchcontrollers.FlingAndHoldTouchController;
|
||||
import com.android.launcher3.uioverrides.touchcontrollers.LandscapeEdgeSwipeController;
|
||||
|
||||
@@ -46,11 +46,8 @@ import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.model.PagedViewOrientedState;
|
||||
import com.android.launcher3.states.RotationHelper;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.touch.PortraitPagedViewHandler;
|
||||
import com.android.launcher3.util.VibratorWrapper;
|
||||
import com.android.launcher3.views.FloatingIconView;
|
||||
import com.android.quickstep.BaseActivityInterface.HomeAnimationFactory;
|
||||
@@ -59,6 +56,7 @@ import com.android.quickstep.util.ActiveGestureLog;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper.TransformParams;
|
||||
import com.android.quickstep.util.RecentsOrientedState;
|
||||
import com.android.quickstep.util.RectFSpringAnim;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
@@ -127,7 +125,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
||||
protected boolean mCanceled;
|
||||
protected int mFinishingRecentsAnimationForNewTaskId = -1;
|
||||
|
||||
private PagedViewOrientedState mOrientedState;
|
||||
private RecentsOrientedState mOrientedState;
|
||||
|
||||
protected BaseSwipeUpHandler(Context context, RecentsAnimationDeviceState deviceState,
|
||||
GestureState gestureState, InputConsumerController inputConsumer) {
|
||||
@@ -199,18 +197,12 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
||||
}
|
||||
|
||||
protected void startNewTask(int successStateFlag, Consumer<Boolean> resultCallback) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_START_FROM_RECENTS, "startNewTask1");
|
||||
}
|
||||
// Launch the task user scrolled to (mRecentsView.getNextPage()).
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
// We finish recents animation inside launchTask() when live tile is enabled.
|
||||
mRecentsView.getNextPageTaskView().launchTask(false /* animate */,
|
||||
true /* freezeTaskList */);
|
||||
} else {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_START_FROM_RECENTS, "startNewTask2");
|
||||
}
|
||||
int taskId = mRecentsView.getNextPageTaskView().getTask().key.id;
|
||||
if (!mCanceled) {
|
||||
TaskView nextTask = mRecentsView.getTaskView(taskId);
|
||||
@@ -337,9 +329,11 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
||||
// TODO(b/150300347): The first recents animation after launcher is started with the
|
||||
// foreground app not in landscape will look funky until that bug is fixed
|
||||
displayRotation = mOrientedState.getDisplayRotation();
|
||||
|
||||
RectF tempRectF = new RectF(TEMP_RECT);
|
||||
mOrientedState.mapRectFromNormalOrientation(tempRectF, dp.widthPx, dp.heightPx);
|
||||
tempRectF.roundOut(TEMP_RECT);
|
||||
}
|
||||
RotationHelper.getTargetRectForRotation(TEMP_RECT, dp.widthPx, dp.heightPx,
|
||||
displayRotation);
|
||||
mAppWindowAnimationHelper.updateTargetRect(TEMP_RECT);
|
||||
if (mDeviceState.isFullyGesturalNavMode()) {
|
||||
// We can drag all the way to the top of the screen.
|
||||
@@ -434,7 +428,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
||||
|
||||
protected PagedOrientationHandler getOrientationHandler() {
|
||||
if (mOrientedState == null) {
|
||||
return new PortraitPagedViewHandler();
|
||||
return PagedOrientationHandler.PORTRAIT;
|
||||
}
|
||||
return mOrientedState.getOrientationHandler();
|
||||
}
|
||||
@@ -455,8 +449,8 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
||||
.setTargetSet(mRecentsAnimationTargets)
|
||||
.setLauncherOnTop(false)));
|
||||
if (isFloatingIconView) {
|
||||
RotationHelper.mapInverseRectFromNormalOrientation(startRect,
|
||||
mDp.widthPx, mDp.heightPx, mOrientedState.getDisplayRotation());
|
||||
mOrientedState.mapInverseRectFromNormalOrientation(
|
||||
startRect, mDp.widthPx, mDp.heightPx);
|
||||
}
|
||||
RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mContext);
|
||||
if (isFloatingIconView) {
|
||||
@@ -487,8 +481,8 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
||||
|
||||
rotatedRect.set(currentRect);
|
||||
if (isFloatingIconView) {
|
||||
RotationHelper.mapRectFromNormalOrientation(rotatedRect,
|
||||
mDp.widthPx, mDp.heightPx, mOrientedState.getDisplayRotation());
|
||||
mOrientedState.mapRectFromNormalOrientation(
|
||||
rotatedRect, mDp.widthPx, mDp.heightPx);
|
||||
mTransformParams.setCornerRadius(endRadius * progress + startRadius
|
||||
* (1f - progress));
|
||||
}
|
||||
|
||||
-2
@@ -33,8 +33,6 @@ import androidx.annotation.Nullable;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.touch.PortraitPagedViewHandler;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.quickstep.fallback.FallbackRecentsView;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
|
||||
@@ -40,9 +40,7 @@ import android.view.MotionEvent;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.touch.LandscapePagedViewHandler;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.touch.PortraitPagedViewHandler;
|
||||
import com.android.launcher3.util.ObjectWrapper;
|
||||
import com.android.quickstep.BaseActivityInterface.HomeAnimationFactory;
|
||||
import com.android.quickstep.GestureState.GestureEndTarget;
|
||||
@@ -503,8 +501,8 @@ public class FallbackSwipeHandler extends BaseSwipeUpHandler<RecentsActivity, Fa
|
||||
PagedOrientationHandler orientationHandler = mRecentsView != null
|
||||
? mRecentsView.getPagedOrientationHandler()
|
||||
: (mDp.isLandscape
|
||||
? new LandscapePagedViewHandler()
|
||||
: new PortraitPagedViewHandler());
|
||||
? PagedOrientationHandler.LANDSCAPE
|
||||
: PagedOrientationHandler.PORTRAIT);
|
||||
return HomeAnimationFactory
|
||||
.getDefaultWindowTargetRect(orientationHandler, mDp);
|
||||
}
|
||||
|
||||
@@ -984,9 +984,6 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
||||
windowAnim.addListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_START_FROM_RECENTS, "onAnimationSuccess");
|
||||
}
|
||||
if (mRecentsAnimationController == null) {
|
||||
// If the recents animation is interrupted, we still end the running
|
||||
// animation (not canceled) so this is still called. In that case, we can
|
||||
@@ -1210,9 +1207,6 @@ public class LauncherSwipeHandler<T extends BaseDraggingActivity>
|
||||
}
|
||||
|
||||
private void switchToScreenshot() {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_START_FROM_RECENTS, "switchToScreenshot");
|
||||
}
|
||||
final int runningTaskId = mGestureState.getRunningTaskId();
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
if (mRecentsAnimationController != null) {
|
||||
|
||||
@@ -35,8 +35,8 @@ import android.view.View;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.model.WellbeingModel;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
import com.android.launcher3.popup.SystemShortcut.AppInfo;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
@@ -71,7 +71,7 @@ public interface TaskShortcutFactory {
|
||||
WorkspaceItemInfo dummyInfo = new WorkspaceItemInfo();
|
||||
dummyInfo.intent = new Intent();
|
||||
ComponentName component = task.getTopComponent();
|
||||
dummyInfo.intent.setComponent(component);
|
||||
dummyInfo.getIntent().setComponent(component);
|
||||
dummyInfo.user = UserHandle.of(task.key.userId);
|
||||
dummyInfo.title = TaskUtils.getTitle(view.getContext(), task);
|
||||
return dummyInfo;
|
||||
|
||||
@@ -33,8 +33,8 @@ import android.view.View;
|
||||
|
||||
import com.android.launcher3.BaseActivity;
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper;
|
||||
import com.android.quickstep.util.MultiValueUpdateListener;
|
||||
|
||||
+68
-18
@@ -26,11 +26,12 @@ import static com.android.quickstep.GestureState.DEFAULT_STATE;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_INPUT_MONITOR;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.RemoteAction;
|
||||
import android.app.Service;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
@@ -38,6 +39,7 @@ import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Region;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
@@ -46,6 +48,7 @@ import android.util.Log;
|
||||
import android.view.Choreographer;
|
||||
import android.view.InputEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
|
||||
import androidx.annotation.BinderThread;
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -53,8 +56,8 @@ import androidx.annotation.UiThread;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.allapps.DiscoveryBounce;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.model.AppLaunchTracker;
|
||||
@@ -64,6 +67,7 @@ import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.tracing.nano.LauncherTraceProto;
|
||||
import com.android.launcher3.tracing.nano.TouchInteractionServiceProto;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
import com.android.launcher3.util.OnboardingPrefs;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.quickstep.inputconsumers.AccessibilityInputConsumer;
|
||||
import com.android.quickstep.inputconsumers.AssistantInputConsumer;
|
||||
@@ -126,6 +130,12 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
||||
private static final String HAS_ENABLED_QUICKSTEP_ONCE = "launcher.has_enabled_quickstep_once";
|
||||
private static final int MAX_BACK_NOTIFICATION_COUNT = 3;
|
||||
|
||||
/**
|
||||
* System Action ID to show all apps. This ID should follow the ones in
|
||||
* com.android.systemui.accessibility.SystemActions.
|
||||
*/
|
||||
private static final int SYSTEM_ACTION_ID_ALL_APPS = 100;
|
||||
|
||||
private int mBackGestureNotificationCounter = -1;
|
||||
@Nullable
|
||||
private OverscrollPlugin mOverscrollPlugin;
|
||||
@@ -351,6 +361,9 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
||||
|
||||
PluginManagerWrapper.INSTANCE.get(getBaseContext()).addPluginListener(this,
|
||||
OverscrollPlugin.class, false /* allowMultiple */);
|
||||
|
||||
mOverviewComponentObserver.setOverviewChangeListener(this::onOverviewTargetChange);
|
||||
onOverviewTargetChange(mOverviewComponentObserver.isHomeAndOverviewSame());
|
||||
}
|
||||
|
||||
private void resetHomeBounceSeenOnQuickstepEnabledFirstTime() {
|
||||
@@ -365,11 +378,29 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
||||
if (!sharedPrefs.getBoolean(HAS_ENABLED_QUICKSTEP_ONCE, true)) {
|
||||
sharedPrefs.edit()
|
||||
.putBoolean(HAS_ENABLED_QUICKSTEP_ONCE, true)
|
||||
.putBoolean(DiscoveryBounce.HOME_BOUNCE_SEEN, false)
|
||||
.putBoolean(OnboardingPrefs.HOME_BOUNCE_SEEN, false)
|
||||
.apply();
|
||||
}
|
||||
}
|
||||
|
||||
private void onOverviewTargetChange(boolean isHomeAndOverviewSame) {
|
||||
AccessibilityManager am = getSystemService(AccessibilityManager.class);
|
||||
|
||||
if (isHomeAndOverviewSame) {
|
||||
Intent intent = new Intent(mOverviewComponentObserver.getHomeIntent())
|
||||
.setAction(Intent.ACTION_ALL_APPS);
|
||||
RemoteAction allAppsAction = new RemoteAction(
|
||||
Icon.createWithResource(this, R.drawable.ic_apps),
|
||||
getString(R.string.all_apps_label),
|
||||
getString(R.string.all_apps_label),
|
||||
PendingIntent.getActivity(this, SYSTEM_ACTION_ID_ALL_APPS, intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT));
|
||||
am.registerSystemAction(allAppsAction, SYSTEM_ACTION_ID_ALL_APPS);
|
||||
} else {
|
||||
am.unregisterSystemAction(SYSTEM_ACTION_ID_ALL_APPS);
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void onSystemUiFlagsChanged() {
|
||||
if (mDeviceState.isUserUnlocked()) {
|
||||
@@ -408,6 +439,9 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
||||
ProtoTracer.INSTANCE.get(TouchInteractionService.this).stop();
|
||||
ProtoTracer.INSTANCE.get(this).remove(this);
|
||||
|
||||
getSystemService(AccessibilityManager.class)
|
||||
.unregisterSystemAction(SYSTEM_ACTION_ID_ALL_APPS);
|
||||
|
||||
sConnected = false;
|
||||
super.onDestroy();
|
||||
}
|
||||
@@ -451,7 +485,7 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
||||
mConsumer.onConsumerAboutToBeSwitched();
|
||||
mConsumer = newConsumer(prevGestureState, newGestureState, event);
|
||||
|
||||
ActiveGestureLog.INSTANCE.addLog("setInputConsumer", mConsumer.getType());
|
||||
ActiveGestureLog.INSTANCE.addLog("setInputConsumer: " + mConsumer.getName());
|
||||
mUncheckedConsumer = mConsumer;
|
||||
} else if (mDeviceState.isUserUnlocked()
|
||||
&& mDeviceState.isFullyGesturalNavMode()
|
||||
@@ -481,14 +515,14 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
||||
}
|
||||
|
||||
ActiveGestureLog.INSTANCE.addLog("onMotionEvent", event.getActionMasked());
|
||||
boolean cleanUpConsumer = (action == ACTION_UP || action == ACTION_CANCEL)
|
||||
&& mConsumer != null
|
||||
&& !mConsumer.getActiveConsumerInHierarchy().isConsumerDetachedFromGesture();
|
||||
mUncheckedConsumer.onMotionEvent(event);
|
||||
|
||||
if (action == ACTION_UP || action == ACTION_CANCEL) {
|
||||
if (mConsumer != null && !mConsumer.isConsumerDetachedFromGesture()) {
|
||||
onConsumerInactive(mConsumer);
|
||||
}
|
||||
if (cleanUpConsumer) {
|
||||
reset();
|
||||
}
|
||||
|
||||
TraceHelper.INSTANCE.endFlagsOverride(traceToken);
|
||||
}
|
||||
|
||||
@@ -496,7 +530,7 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
||||
GestureState gestureState = new GestureState(mOverviewComponentObserver,
|
||||
ActiveGestureLog.INSTANCE.generateAndSetLogId());
|
||||
gestureState.updateRunningTask(TraceHelper.whitelistIpcs("getRunningTask.0",
|
||||
() -> mAM.getRunningTask(true /* filterOnlyVisibleRecents */)));
|
||||
() -> mAM.getRunningTask(false /* filterOnlyVisibleRecents */)));
|
||||
return gestureState;
|
||||
}
|
||||
|
||||
@@ -505,6 +539,8 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
||||
boolean canStartSystemGesture = mDeviceState.canStartSystemGesture();
|
||||
|
||||
if (!mDeviceState.isUserUnlocked()) {
|
||||
Log.d(TAG, "User locked. Can start system gesture? " + canStartSystemGesture
|
||||
+ " sysUiFlags: " + mDeviceState.getSystemUiStateFlags());
|
||||
if (canStartSystemGesture) {
|
||||
// This handles apps launched in direct boot mode (e.g. dialer) as well as apps
|
||||
// launched while device is locked even after exiting direct boot mode (e.g. camera).
|
||||
@@ -596,10 +632,18 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
||||
return createDeviceLockedInputConsumer(gestureState);
|
||||
}
|
||||
|
||||
RunningTaskInfo runningTask = gestureState.getRunningTask();
|
||||
ComponentName homeComponent = mOverviewComponentObserver.getHomeIntent().getComponent();
|
||||
boolean forceOverviewInputConsumer = runningTask != null
|
||||
&& runningTask.baseIntent.getComponent().equals(homeComponent);
|
||||
boolean forceOverviewInputConsumer = false;
|
||||
if (AssistantUtilities.isExcludedAssistant(gestureState.getRunningTask())) {
|
||||
// In the case where we are in the excluded assistant state, ignore it and treat the
|
||||
// running activity as the task behind the assistant
|
||||
gestureState.updateRunningTask(TraceHelper.whitelistIpcs("getRunningTask.assistant",
|
||||
() -> mAM.getRunningTask(true /* filterOnlyVisibleRecents */)));
|
||||
ComponentName homeComponent = mOverviewComponentObserver.getHomeIntent().getComponent();
|
||||
ComponentName runningComponent =
|
||||
gestureState.getRunningTask().baseIntent.getComponent();
|
||||
forceOverviewInputConsumer =
|
||||
runningComponent != null && runningComponent.equals(homeComponent);
|
||||
}
|
||||
|
||||
if (previousGestureState.getFinishingRecentsAnimationTaskId() > 0) {
|
||||
// If the finish animation was interrupted, then continue using the other activity input
|
||||
@@ -678,15 +722,21 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
||||
}
|
||||
|
||||
/**
|
||||
* To be called by the consumer when it's no longer active.
|
||||
* To be called by the consumer when it's no longer active. This can be called by any consumer
|
||||
* in the hierarchy at any point during the gesture (ie. if a delegate consumer starts
|
||||
* intercepting touches, the base consumer can try to call this).
|
||||
*/
|
||||
private void onConsumerInactive(InputConsumer caller) {
|
||||
if (mConsumer != null && mConsumer.isInConsumerHierarchy(caller)) {
|
||||
mConsumer = mUncheckedConsumer = mResetGestureInputConsumer;
|
||||
mGestureState = new GestureState();
|
||||
if (mConsumer != null && mConsumer.getActiveConsumerInHierarchy() == caller) {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
mConsumer = mUncheckedConsumer = mResetGestureInputConsumer;
|
||||
mGestureState = new GestureState();
|
||||
}
|
||||
|
||||
private void preloadOverview(boolean fromInit) {
|
||||
if (!mDeviceState.isUserUnlocked()) {
|
||||
return;
|
||||
|
||||
+5
-7
@@ -25,13 +25,11 @@ public abstract class DelegateInputConsumer implements InputConsumer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConsumerDetachedFromGesture() {
|
||||
return mDelegate.isConsumerDetachedFromGesture();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInConsumerHierarchy(InputConsumer candidate) {
|
||||
return this == candidate || mDelegate.isInConsumerHierarchy(candidate);
|
||||
public InputConsumer getActiveConsumerInHierarchy() {
|
||||
if (mState == STATE_ACTIVE) {
|
||||
return this;
|
||||
}
|
||||
return mDelegate.getActiveConsumerInHierarchy();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -19,8 +19,8 @@ import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.appprediction.PredictionUiStateManager;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
+9
-10
@@ -15,6 +15,13 @@
|
||||
*/
|
||||
package com.android.quickstep.util;
|
||||
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
@@ -33,7 +40,6 @@ import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.model.PagedViewOrientedState;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.quickstep.RemoteAnimationTargets;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
@@ -47,13 +53,6 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.
|
||||
import com.android.systemui.shared.system.TransactionCompat;
|
||||
import com.android.systemui.shared.system.WindowManagerWrapper;
|
||||
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.getWindowCornerRadius;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.supportsRoundedCornersOnWindows;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
|
||||
|
||||
/**
|
||||
* Utility class to handle window clip animation
|
||||
*/
|
||||
@@ -86,7 +85,7 @@ public class AppWindowAnimationHelper {
|
||||
private final Rect mTmpRect = new Rect();
|
||||
private final RectF mTmpRectF = new RectF();
|
||||
private final RectF mCurrentRectWithInsets = new RectF();
|
||||
private PagedViewOrientedState mOrientedState;
|
||||
private RecentsOrientedState mOrientedState;
|
||||
// Corner radius of windows, in pixels
|
||||
private final float mWindowCornerRadius;
|
||||
// Corner radius of windows when they're in overview mode.
|
||||
@@ -105,7 +104,7 @@ public class AppWindowAnimationHelper {
|
||||
private TargetAlphaProvider mTaskAlphaCallback = (t, a) -> a;
|
||||
private TargetAlphaProvider mBaseAlphaCallback = (t, a) -> 1;
|
||||
|
||||
public AppWindowAnimationHelper(PagedViewOrientedState orientedState, Context context) {
|
||||
public AppWindowAnimationHelper(RecentsOrientedState orientedState, Context context) {
|
||||
Resources res = context.getResources();
|
||||
mOrientedState = orientedState;
|
||||
mWindowCornerRadius = getWindowCornerRadius(res);
|
||||
|
||||
@@ -78,21 +78,6 @@ public class ClearAllButton extends Button implements PageCallbacks {
|
||||
}
|
||||
}
|
||||
|
||||
public void onLayoutChanged() {
|
||||
if (mParent == null) {
|
||||
return;
|
||||
}
|
||||
setRotation(mParent.getPagedOrientationHandler().getDegreesRotated());
|
||||
}
|
||||
|
||||
public void setRtl(boolean rtl) {
|
||||
if (mIsRtl == rtl) {
|
||||
return;
|
||||
}
|
||||
mIsRtl = rtl;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setVisibilityAlpha(float alpha) {
|
||||
if (mVisibilityAlpha != alpha) {
|
||||
mVisibilityAlpha = alpha;
|
||||
|
||||
@@ -100,8 +100,8 @@ import com.android.launcher3.anim.SpringProperty;
|
||||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.launcher3.states.RotationHelper;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler.CurveProperties;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
||||
@@ -122,6 +122,7 @@ import com.android.quickstep.TaskUtils;
|
||||
import com.android.quickstep.ViewUtils;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.quickstep.util.RecentsOrientedState;
|
||||
import com.android.systemui.plugins.ResourceProvider;
|
||||
import com.android.systemui.shared.recents.IPinnedStackAnimationListener;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
@@ -171,6 +172,8 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
}
|
||||
};
|
||||
|
||||
protected final RecentsOrientedState mOrientationState = new RecentsOrientedState();
|
||||
|
||||
private OrientationEventListener mOrientationListener;
|
||||
private int mPreviousRotation;
|
||||
protected RecentsAnimationController mRecentsAnimationController;
|
||||
@@ -383,7 +386,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
mOrientationListener = new OrientationEventListener(getContext()) {
|
||||
@Override
|
||||
public void onOrientationChanged(int i) {
|
||||
int rotation = RotationHelper.getRotationFromDegrees(i);
|
||||
int rotation = RecentsOrientedState.getRotationForUserDegreesRotated(i);
|
||||
if (mPreviousRotation != rotation) {
|
||||
animateRecentsRotationInPlace(rotation);
|
||||
if (rotation == 0) {
|
||||
@@ -505,6 +508,29 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
mHasVisibleTaskData.delete(taskView.getTask().key.id);
|
||||
mTaskViewPool.recycle(taskView);
|
||||
}
|
||||
updateTaskStartIndex(child);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAdded(View child) {
|
||||
super.onViewAdded(child);
|
||||
child.setAlpha(mContentAlpha);
|
||||
// RecentsView is set to RTL in the constructor when system is using LTR. Here we set the
|
||||
// child direction back to match system settings.
|
||||
child.setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_LTR : View.LAYOUT_DIRECTION_RTL);
|
||||
updateTaskStartIndex(child);
|
||||
}
|
||||
|
||||
private void updateTaskStartIndex(View affectingView) {
|
||||
if (!(affectingView instanceof TaskView) && !(affectingView instanceof ClearAllButton)) {
|
||||
int childCount = getChildCount();
|
||||
|
||||
mTaskViewStartIndex = 0;
|
||||
while (mTaskViewStartIndex < childCount
|
||||
&& !(getChildAt(mTaskViewStartIndex) instanceof TaskView)) {
|
||||
mTaskViewStartIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isTaskViewVisible(TaskView tv) {
|
||||
@@ -661,7 +687,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
final int pageIndex = requiredTaskCount - i - 1 + mTaskViewStartIndex;
|
||||
final Task task = tasks.get(i);
|
||||
final TaskView taskView = (TaskView) getChildAt(pageIndex);
|
||||
taskView.bind(task, mLayoutRotation);
|
||||
taskView.bind(task, mOrientationState);
|
||||
}
|
||||
|
||||
if (mNextPage == INVALID_PAGE) {
|
||||
@@ -710,11 +736,15 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
int currentIndex = indexOfChild(taskView);
|
||||
TaskView previousTask = getTaskViewAt(currentIndex - 1);
|
||||
TaskView nextTask = getTaskViewAt(currentIndex + 1);
|
||||
float alpha = isTaskOverlayModal ? 0.0f : 1.0f;
|
||||
if (previousTask != null) {
|
||||
previousTask.setVisibility(isTaskOverlayModal ? View.INVISIBLE : View.VISIBLE);
|
||||
previousTask.animate().alpha(alpha)
|
||||
.translationX(isTaskOverlayModal ? previousTask.getWidth() / 2 : 0);
|
||||
}
|
||||
if (nextTask != null) {
|
||||
nextTask.setVisibility(isTaskOverlayModal ? View.INVISIBLE : View.VISIBLE);
|
||||
nextTask.animate().alpha(alpha)
|
||||
.translationX(isTaskOverlayModal ? -nextTask.getWidth() / 2 : 0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -819,7 +849,8 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
final int pageCount = getPageCount();
|
||||
for (int i = 0; i < pageCount; i++) {
|
||||
View page = getPageAt(i);
|
||||
mScrollState.updateInterpolation(mOrientationHandler.getChildStart(page), mPageSpacing);
|
||||
mScrollState.updateInterpolation(mOrientationHandler.getChildStartWithTranslation(page),
|
||||
mPageSpacing);
|
||||
((PageCallbacks) page).onPageScroll(mScrollState);
|
||||
}
|
||||
}
|
||||
@@ -973,7 +1004,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
|
||||
AnimatorSet pa = setRecentsChangedOrientation(true);
|
||||
pa.addListener(AnimationSuccessListener.forRunnable(() -> {
|
||||
updateLayoutRotation(newRotation);
|
||||
setLayoutRotation(newRotation, mOrientationState.getDisplayRotation());
|
||||
mActivity.getDragLayer().recreateControllers();
|
||||
rotateAllChildTasks();
|
||||
setRecentsChangedOrientation(false).start();
|
||||
@@ -999,8 +1030,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
|
||||
private void rotateAllChildTasks() {
|
||||
for (int i = 0; i < getTaskViewCount(); i++) {
|
||||
TaskView taskView = getTaskViewAt(i);
|
||||
taskView.setOverviewRotation(mLayoutRotation);
|
||||
getTaskViewAt(i).setOrientationState(mOrientationState);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1041,7 +1071,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
new ComponentName(getContext(), getClass()), 0, 0), null, null, "", "", 0, 0,
|
||||
false, true, false, false, new ActivityManager.TaskDescription(), 0,
|
||||
new ComponentName("", ""), false);
|
||||
taskView.bind(mTmpRunningTask, mLayoutRotation);
|
||||
taskView.bind(mTmpRunningTask, mOrientationState);
|
||||
}
|
||||
|
||||
boolean runningTaskTileHidden = mRunningTaskTileHidden;
|
||||
@@ -1207,7 +1237,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
/**
|
||||
* Updates linearInterpolation for the provided child position
|
||||
*/
|
||||
public void updateInterpolation(int childStart, int pageSpacing) {
|
||||
public void updateInterpolation(float childStart, int pageSpacing) {
|
||||
float pageCenter = childStart + halfPageSize;
|
||||
float distanceFromScreenCenter = screenCenter - pageCenter;
|
||||
float distanceToReachEdge = halfScreenSize + halfPageSize + pageSpacing;
|
||||
@@ -1530,22 +1560,28 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLayoutRotation(int touchRotation, int displayRotation) {
|
||||
if (!FeatureFlags.ENABLE_FIXED_ROTATION_TRANSFORM.get()) {
|
||||
return;
|
||||
if (mOrientationState.update(touchRotation, displayRotation)) {
|
||||
mOrientationHandler = mOrientationState.getOrientationHandler();
|
||||
mIsRtl = mOrientationHandler.getRecentsRtlSetting(getResources());
|
||||
setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
|
||||
mClearAllButton.setRotation(mOrientationHandler.getDegreesRotated());
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
super.setLayoutRotation(touchRotation, displayRotation);
|
||||
mClearAllButton.onLayoutChanged();
|
||||
mIsRtl = mOrientationHandler.getRecentsRtlSetting(getResources());
|
||||
setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAdded(View child) {
|
||||
super.onViewAdded(child);
|
||||
child.setAlpha(mContentAlpha);
|
||||
public void disableMultipleLayoutRotations(boolean disable) {
|
||||
mOrientationState.disableMultipleOrientations(disable);
|
||||
mOrientationHandler = mOrientationState.getOrientationHandler();
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
public RecentsOrientedState getPagedViewOrientedState() {
|
||||
return mOrientationState;
|
||||
}
|
||||
|
||||
public PagedOrientationHandler getPagedOrientationHandler() {
|
||||
return mOrientationHandler;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -1986,8 +2022,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
public Consumer<MotionEvent> getEventDispatcher(float navbarRotation) {
|
||||
float degreesRotated;
|
||||
if (navbarRotation == 0) {
|
||||
degreesRotated = mOrientationState.areMultipleLayoutOrientationsDisabled() ? 0 :
|
||||
RotationHelper.getDegreesFromRotation(mLayoutRotation);
|
||||
degreesRotated = mOrientationState.getTouchRotationDegrees();
|
||||
} else {
|
||||
degreesRotated = -navbarRotation;
|
||||
}
|
||||
@@ -2001,14 +2036,14 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
return e -> {
|
||||
if (navbarRotation != 0
|
||||
&& !mOrientationState.areMultipleLayoutOrientationsDisabled()) {
|
||||
RotationHelper.transformEventForNavBar(e, true);
|
||||
mOrientationState.flipVertical(e);
|
||||
super.onTouchEvent(e);
|
||||
RotationHelper.transformEventForNavBar(e, false);
|
||||
mOrientationState.flipVertical(e);
|
||||
return;
|
||||
}
|
||||
RotationHelper.transformEvent(-degreesRotated, e, true);
|
||||
mOrientationState.transformEvent(-degreesRotated, e, true);
|
||||
super.onTouchEvent(e);
|
||||
RotationHelper.transformEvent(-degreesRotated, e, false);
|
||||
mOrientationState.transformEvent(-degreesRotated, e, false);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -2056,37 +2091,11 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addView(View child, int index) {
|
||||
// RecentsView is set to RTL in the constructor when system is using LTR. Here we set the
|
||||
// child direction back to match system settings.
|
||||
child.setLayoutDirection(
|
||||
Utilities.isRtl(getResources())
|
||||
? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
|
||||
super.addView(child, index);
|
||||
if (isExtraCardView(child, index)) {
|
||||
mTaskViewStartIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeView(View view) {
|
||||
if (isExtraCardView(view, indexOfChild(view))) {
|
||||
mTaskViewStartIndex--;
|
||||
}
|
||||
super.removeView(view);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected DepthController getDepthController() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isExtraCardView(View view, int index) {
|
||||
return !(view instanceof TaskView) && !(view instanceof ClearAllButton)
|
||||
&& index <= mTaskViewStartIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to register callbacks for when our empty message state changes.
|
||||
*
|
||||
@@ -2131,13 +2140,15 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
&& SysUINavigationMode.removeShelfFromOverview(mActivity)) {
|
||||
mActionsView = ((ViewGroup) getParent()).findViewById(R.id.overview_actions_view);
|
||||
if (mActionsView != null) {
|
||||
Rect rect = new Rect();
|
||||
getTaskSize(rect);
|
||||
InsettableFrameLayout.LayoutParams layoutParams =
|
||||
new InsettableFrameLayout.LayoutParams(rect.width(),
|
||||
new InsettableFrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
|
||||
getResources().getDimensionPixelSize(
|
||||
R.dimen.overview_actions_height));
|
||||
layoutParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
|
||||
int margin = getResources().getDimensionPixelSize(
|
||||
R.dimen.overview_actions_horizontal_margin);
|
||||
layoutParams.setMarginStart(margin);
|
||||
layoutParams.setMarginEnd(margin);
|
||||
mActionsView.setLayoutParams(layoutParams);
|
||||
showActionsView();
|
||||
}
|
||||
|
||||
@@ -64,7 +64,6 @@ import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.logger.LauncherAtom;
|
||||
import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
import com.android.launcher3.states.RotationHelper;
|
||||
import com.android.launcher3.testing.TestLogging;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
@@ -79,6 +78,7 @@ import com.android.quickstep.TaskOverlayFactory;
|
||||
import com.android.quickstep.TaskThumbnailCache;
|
||||
import com.android.quickstep.TaskUtils;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.quickstep.util.RecentsOrientedState;
|
||||
import com.android.quickstep.util.TaskCornerRadius;
|
||||
import com.android.quickstep.views.RecentsView.PageCallbacks;
|
||||
import com.android.quickstep.views.RecentsView.ScrollState;
|
||||
@@ -119,19 +119,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT =
|
||||
Collections.singletonList(new Rect());
|
||||
|
||||
public static final FloatProperty<TaskView> FULLSCREEN_PROGRESS =
|
||||
new FloatProperty<TaskView>("fullscreenProgress") {
|
||||
@Override
|
||||
public void setValue(TaskView taskView, float v) {
|
||||
taskView.setFullscreenProgress(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Float get(TaskView taskView) {
|
||||
return taskView.mFullscreenProgress;
|
||||
}
|
||||
};
|
||||
|
||||
private static final FloatProperty<TaskView> FOCUS_TRANSITION =
|
||||
new FloatProperty<TaskView>("focusTransition") {
|
||||
@Override
|
||||
@@ -180,6 +167,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
private float mStableAlpha = 1;
|
||||
|
||||
private boolean mShowScreenshot;
|
||||
private boolean mRunningModalAnimation = false;
|
||||
|
||||
// The current background requests to load the task thumbnail and icon
|
||||
private TaskThumbnailCache.ThumbnailLoadRequest mThumbnailLoadRequest;
|
||||
@@ -262,17 +250,39 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
/** Updates UI based on whether the task is modal. */
|
||||
public void updateUiForModalTask() {
|
||||
boolean isOverlayModal = isTaskOverlayModal();
|
||||
mRunningModalAnimation = true;
|
||||
if (getRecentsView() != null) {
|
||||
getRecentsView().updateUiForModalTask(this, isOverlayModal);
|
||||
}
|
||||
// Hide footers when overlay is modal.
|
||||
|
||||
// Hides footers and icon when overlay is modal.
|
||||
if (isOverlayModal) {
|
||||
for (FooterWrapper footer : mFooters) {
|
||||
if (footer != null) {
|
||||
footer.animateHide();
|
||||
}
|
||||
}
|
||||
mIconView.animate().alpha(0.0f);
|
||||
} else {
|
||||
mIconView.animate().alpha(1.0f);
|
||||
}
|
||||
|
||||
// Sets animations for modal UI. We will remove the margins to zoom in the snapshot.
|
||||
float topMargin = getResources().getDimension(R.dimen.task_thumbnail_top_margin);
|
||||
float bottomMargin =
|
||||
getResources().getDimension(R.dimen.task_thumbnail_bottom_margin_with_actions);
|
||||
float newHeight = mSnapshotView.getHeight() + topMargin + bottomMargin;
|
||||
float scale = isOverlayModal ? newHeight / mSnapshotView.getHeight() : 1.0f;
|
||||
float centerDifference = (bottomMargin - topMargin) / 2;
|
||||
float translationY = isOverlayModal ? centerDifference : 0;
|
||||
this.animate().scaleX(scale).scaleY(scale).translationY(translationY)
|
||||
.withEndAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setCurveScale(scale);
|
||||
mRunningModalAnimation = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public TaskMenuView getMenuView() {
|
||||
@@ -286,11 +296,11 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
/**
|
||||
* Updates this task view to the given {@param task}.
|
||||
*/
|
||||
public void bind(Task task, int recentsRotation) {
|
||||
public void bind(Task task, RecentsOrientedState orientedState) {
|
||||
cancelPendingLoadTasks();
|
||||
mTask = task;
|
||||
mSnapshotView.bind(task);
|
||||
setOverviewRotation(recentsRotation);
|
||||
setOrientationState(orientedState);
|
||||
}
|
||||
|
||||
public Task getTask() {
|
||||
@@ -459,14 +469,15 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
}
|
||||
}
|
||||
|
||||
void setOverviewRotation(int iconRotation) {
|
||||
PagedOrientationHandler orientationHandler = getRecentsView().getPagedOrientationHandler();
|
||||
public void setOrientationState(RecentsOrientedState orientationState) {
|
||||
int iconRotation = orientationState.getTouchRotation();
|
||||
PagedOrientationHandler orientationHandler = orientationState.getOrientationHandler();
|
||||
boolean isRtl = orientationHandler.getRecentsRtlSetting(getResources());
|
||||
LayoutParams snapshotParams = (LayoutParams) mSnapshotView.getLayoutParams();
|
||||
snapshotParams.bottomMargin = LayoutUtils.thumbnailBottomMargin(getContext());
|
||||
int thumbnailPadding = (int) getResources().getDimension(R.dimen.task_thumbnail_top_margin);
|
||||
LayoutParams iconParams = (LayoutParams) mIconView.getLayoutParams();
|
||||
int rotation = RotationHelper.getDegreesFromRotation(iconRotation);
|
||||
int rotation = orientationState.getTouchRotationDegrees();
|
||||
switch (iconRotation) {
|
||||
case Surface.ROTATION_90:
|
||||
iconParams.gravity = (isRtl ? END : START) | CENTER_VERTICAL;
|
||||
@@ -579,11 +590,15 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
|
||||
@Override
|
||||
public void onPageScroll(ScrollState scrollState) {
|
||||
// Don't do anything if it's modal.
|
||||
if (mRunningModalAnimation || isTaskOverlayModal()) {
|
||||
return;
|
||||
}
|
||||
|
||||
float curveInterpolation =
|
||||
CURVE_INTERPOLATOR.getInterpolation(scrollState.linearInterpolation);
|
||||
float curveScaleForCurveInterpolation = getCurveScaleForCurveInterpolation(
|
||||
curveInterpolation);
|
||||
|
||||
mSnapshotView.setDimAlpha(curveInterpolation * MAX_PAGE_SCRIM_ALPHA);
|
||||
setCurveScale(curveScaleForCurveInterpolation);
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
<resources>
|
||||
|
||||
<dimen name="task_thumbnail_top_margin">24dp</dimen>
|
||||
<dimen name="task_thumbnail_bottom_margin_with_actions">44dp</dimen>
|
||||
<dimen name="task_thumbnail_half_top_margin">12dp</dimen>
|
||||
<dimen name="task_thumbnail_icon_size">48dp</dimen>
|
||||
<!-- For screens without rounded corners -->
|
||||
@@ -24,6 +25,7 @@
|
||||
|
||||
<!-- Overrideable in overlay that provides the Overview Actions. -->
|
||||
<dimen name="overview_actions_height">110dp</dimen>
|
||||
<dimen name="overview_actions_horizontal_margin">16dp</dimen>
|
||||
|
||||
<dimen name="recents_page_spacing">10dp</dimen>
|
||||
<dimen name="recents_clear_all_deadzone_vertical_margin">70dp</dimen>
|
||||
|
||||
@@ -17,14 +17,7 @@ package com.android.launcher3;
|
||||
|
||||
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
|
||||
import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON;
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.allapps.DiscoveryBounce.BOUNCE_MAX_COUNT;
|
||||
import static com.android.launcher3.allapps.DiscoveryBounce.HOME_BOUNCE_COUNT;
|
||||
import static com.android.launcher3.allapps.DiscoveryBounce.HOME_BOUNCE_SEEN;
|
||||
import static com.android.launcher3.allapps.DiscoveryBounce.SHELF_BOUNCE_COUNT;
|
||||
import static com.android.launcher3.allapps.DiscoveryBounce.SHELF_BOUNCE_SEEN;
|
||||
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
|
||||
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
|
||||
|
||||
@@ -32,13 +25,13 @@ import android.animation.AnimatorSet;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.LauncherState.ScaleAndTranslation;
|
||||
import com.android.launcher3.LauncherStateManager.StateHandler;
|
||||
import com.android.launcher3.accessibility.SystemActions;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.model.WellbeingModel;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
@@ -48,12 +41,14 @@ import com.android.launcher3.statehandlers.BackButtonAlphaHandler;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.uioverrides.RecentsViewStateController;
|
||||
import com.android.launcher3.util.OnboardingPrefs;
|
||||
import com.android.launcher3.util.UiThreadHelper;
|
||||
import com.android.quickstep.RecentsModel;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||
import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import com.android.quickstep.util.QuickstepOnboardingPrefs;
|
||||
import com.android.quickstep.util.RemoteAnimationProvider;
|
||||
import com.android.quickstep.util.RemoteFadeOutAnimationListener;
|
||||
import com.android.quickstep.util.ShelfPeekAnim;
|
||||
@@ -70,7 +65,6 @@ public abstract class BaseQuickstepLauncher extends Launcher
|
||||
implements NavigationModeChangeListener {
|
||||
|
||||
private DepthController mDepthController = new DepthController(this);
|
||||
protected SystemActions mSystemActions;
|
||||
|
||||
/**
|
||||
* Reusable command for applying the back button alpha on the background thread.
|
||||
@@ -86,48 +80,8 @@ public abstract class BaseQuickstepLauncher extends Launcher
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mSystemActions = new SystemActions(this);
|
||||
|
||||
SysUINavigationMode.INSTANCE.get(this).addModeChangeListener(this);
|
||||
|
||||
if (!getSharedPrefs().getBoolean(HOME_BOUNCE_SEEN, false)) {
|
||||
getStateManager().addStateListener(new LauncherStateManager.StateListener() {
|
||||
@Override
|
||||
public void onStateTransitionStart(LauncherState toState) { }
|
||||
|
||||
@Override
|
||||
public void onStateTransitionComplete(LauncherState finalState) {
|
||||
boolean swipeUpEnabled = SysUINavigationMode.INSTANCE
|
||||
.get(BaseQuickstepLauncher.this).getMode().hasGestures;
|
||||
LauncherState prevState = getStateManager().getLastState();
|
||||
|
||||
if (((swipeUpEnabled && finalState == OVERVIEW) || (!swipeUpEnabled
|
||||
&& finalState == ALL_APPS && prevState == NORMAL) || BOUNCE_MAX_COUNT
|
||||
<= getSharedPrefs().getInt(HOME_BOUNCE_COUNT, 0))) {
|
||||
getSharedPrefs().edit().putBoolean(HOME_BOUNCE_SEEN, true).apply();
|
||||
getStateManager().removeStateListener(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!getSharedPrefs().getBoolean(SHELF_BOUNCE_SEEN, false)) {
|
||||
getStateManager().addStateListener(new LauncherStateManager.StateListener() {
|
||||
@Override
|
||||
public void onStateTransitionStart(LauncherState toState) { }
|
||||
|
||||
@Override
|
||||
public void onStateTransitionComplete(LauncherState finalState) {
|
||||
LauncherState prevState = getStateManager().getLastState();
|
||||
|
||||
if ((finalState == ALL_APPS && prevState == OVERVIEW) || BOUNCE_MAX_COUNT
|
||||
<= getSharedPrefs().getInt(SHELF_BOUNCE_COUNT, 0)) {
|
||||
getSharedPrefs().edit().putBoolean(SHELF_BOUNCE_SEEN, true).apply();
|
||||
getStateManager().removeStateListener(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -141,12 +95,6 @@ public abstract class BaseQuickstepLauncher extends Launcher
|
||||
getDragLayer().recreateControllers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
mSystemActions.onActivityResult(requestCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnterAnimationComplete() {
|
||||
super.onEnterAnimationComplete();
|
||||
@@ -210,15 +158,6 @@ public abstract class BaseQuickstepLauncher extends Launcher
|
||||
// removes the task itself.
|
||||
startActivity(ProxyActivityStarter.getLaunchIntent(this, null));
|
||||
}
|
||||
|
||||
// Register all system actions once they are available
|
||||
mSystemActions.register();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mSystemActions.unregister();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -261,6 +200,12 @@ public abstract class BaseQuickstepLauncher extends Launcher
|
||||
return mDepthController;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OnboardingPrefs createOnboardingPrefs(SharedPreferences sharedPrefs,
|
||||
LauncherStateManager stateManager) {
|
||||
return new QuickstepOnboardingPrefs(this, sharedPrefs, stateManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ScaleAndTranslation getOverviewScaleAndTranslationForNormalState() {
|
||||
if (SysUINavigationMode.getMode(this) == Mode.NO_BUTTON) {
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.accessibility;
|
||||
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.app.RemoteAction;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager;
|
||||
import com.android.launcher3.R;
|
||||
|
||||
/**
|
||||
* Manages the launcher system actions presented to accessibility services.
|
||||
*/
|
||||
public class SystemActions {
|
||||
|
||||
/**
|
||||
* System Action ID to show all apps. This ID should follow the ones in
|
||||
* com.android.systemui.accessibility.SystemActions.
|
||||
*/
|
||||
private static final int SYSTEM_ACTION_ID_ALL_APPS = 100;
|
||||
|
||||
private Launcher mLauncher;
|
||||
private AccessibilityManager mAccessibilityManager;
|
||||
private RemoteAction mAllAppsAction;
|
||||
private boolean mRegistered;
|
||||
|
||||
public SystemActions(Launcher launcher) {
|
||||
mLauncher = launcher;
|
||||
mAccessibilityManager = (AccessibilityManager) launcher.getSystemService(
|
||||
Context.ACCESSIBILITY_SERVICE);
|
||||
mAllAppsAction = new RemoteAction(
|
||||
Icon.createWithResource(launcher, R.drawable.ic_apps),
|
||||
launcher.getString(R.string.all_apps_label),
|
||||
launcher.getString(R.string.all_apps_label),
|
||||
launcher.createPendingResult(SYSTEM_ACTION_ID_ALL_APPS, new Intent(),
|
||||
0 /* flags */));
|
||||
}
|
||||
|
||||
public void register() {
|
||||
if (mRegistered) {
|
||||
return;
|
||||
}
|
||||
mAccessibilityManager.registerSystemAction(mAllAppsAction, SYSTEM_ACTION_ID_ALL_APPS);
|
||||
mRegistered = true;
|
||||
}
|
||||
|
||||
public void unregister() {
|
||||
if (!mRegistered) {
|
||||
return;
|
||||
}
|
||||
mAccessibilityManager.unregisterSystemAction(SYSTEM_ACTION_ID_ALL_APPS);
|
||||
mRegistered = false;
|
||||
}
|
||||
|
||||
public void onActivityResult(int requestCode) {
|
||||
if (requestCode == SYSTEM_ACTION_ID_ALL_APPS) {
|
||||
showAllApps();
|
||||
}
|
||||
}
|
||||
|
||||
private void showAllApps() {
|
||||
LauncherStateManager stateManager = mLauncher.getStateManager();
|
||||
stateManager.goToState(NORMAL);
|
||||
stateManager.goToState(ALL_APPS);
|
||||
}
|
||||
}
|
||||
@@ -45,8 +45,8 @@ import android.util.Log;
|
||||
import androidx.annotation.MainThread;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.popup.RemoteActionShortcut;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
import com.android.launcher3.util.MainThreadInitializedObject;
|
||||
|
||||
+11
-4
@@ -62,10 +62,13 @@ public abstract class BaseRecentsViewStateController<T extends View>
|
||||
|
||||
@Override
|
||||
public void setState(@NonNull LauncherState state) {
|
||||
ScaleAndTranslation scaleAndTranslation = state
|
||||
.getOverviewScaleAndTranslation(mLauncher);
|
||||
ScaleAndTranslation scaleAndTranslation = state.getOverviewScaleAndTranslation(mLauncher);
|
||||
float translationX = scaleAndTranslation.translationX;
|
||||
if (mRecentsView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
|
||||
translationX = -translationX;
|
||||
}
|
||||
SCALE_PROPERTY.set(mRecentsView, scaleAndTranslation.scale);
|
||||
mRecentsView.setTranslationX(scaleAndTranslation.translationX);
|
||||
mRecentsView.setTranslationX(translationX);
|
||||
mRecentsView.setTranslationY(scaleAndTranslation.translationY);
|
||||
|
||||
getContentAlphaProperty().set(mRecentsView, state.overviewUi ? 1f : 0);
|
||||
@@ -96,9 +99,13 @@ public abstract class BaseRecentsViewStateController<T extends View>
|
||||
void setStateWithAnimationInternal(@NonNull final LauncherState toState,
|
||||
@NonNull StateAnimationConfig config, @NonNull PendingAnimation setter) {
|
||||
ScaleAndTranslation scaleAndTranslation = toState.getOverviewScaleAndTranslation(mLauncher);
|
||||
float translationX = scaleAndTranslation.translationX;
|
||||
if (mRecentsView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
|
||||
translationX = -translationX;
|
||||
}
|
||||
setter.setFloat(mRecentsView, SCALE_PROPERTY, scaleAndTranslation.scale,
|
||||
config.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR));
|
||||
setter.setFloat(mRecentsView, VIEW_TRANSLATE_X, scaleAndTranslation.translationX,
|
||||
setter.setFloat(mRecentsView, VIEW_TRANSLATE_X, translationX,
|
||||
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_X, LINEAR));
|
||||
setter.setFloat(mRecentsView, VIEW_TRANSLATE_Y, scaleAndTranslation.translationY,
|
||||
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR));
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.uioverrides;
|
||||
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.util.Size;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.graphics.LauncherPreviewRenderer;
|
||||
import com.android.systemui.shared.system.SurfaceViewRequestReceiver;
|
||||
|
||||
/** Render preview using surface view. */
|
||||
public class PreviewSurfaceRenderer {
|
||||
|
||||
/** Handle a received surface view request. */
|
||||
public static void render(Context context, Bundle bundle) {
|
||||
String gridName = bundle.getString("name");
|
||||
bundle.remove("name");
|
||||
if (gridName == null) {
|
||||
gridName = InvariantDeviceProfile.getCurrentGridName(context);
|
||||
}
|
||||
final InvariantDeviceProfile idp = new InvariantDeviceProfile(context, gridName);
|
||||
|
||||
MAIN_EXECUTOR.execute(() -> {
|
||||
View view = new LauncherPreviewRenderer(context, idp).getRenderedView();
|
||||
new SurfaceViewRequestReceiver().onReceive(context, bundle, view,
|
||||
new Size(view.getMeasuredWidth(), view.getMeasuredHeight()));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -70,10 +70,10 @@ public interface InputConsumer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given input consumer is in the hierarchy of this input consumer.
|
||||
* Returns the active input consumer is in the hierarchy of this input consumer.
|
||||
*/
|
||||
default boolean isInConsumerHierarchy(InputConsumer candidate) {
|
||||
return this == candidate;
|
||||
default InputConsumer getActiveConsumerInHierarchy() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,15 +96,15 @@ public interface InputConsumer {
|
||||
}
|
||||
|
||||
default String getName() {
|
||||
String name = "";
|
||||
StringBuilder name = new StringBuilder();
|
||||
for (int i = 0; i < NAMES.length; i++) {
|
||||
if ((getType() & (1 << i)) != 0) {
|
||||
if (name.length() > 0) {
|
||||
name += ":";
|
||||
name.append(":");
|
||||
}
|
||||
name += NAMES[i];
|
||||
name.append(NAMES[i]);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
return name.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.util.InstantAppResolver;
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,6 +22,8 @@ import static android.view.MotionEvent.ACTION_MOVE;
|
||||
import static android.view.MotionEvent.ACTION_POINTER_DOWN;
|
||||
import static android.view.MotionEvent.ACTION_UP;
|
||||
|
||||
import static com.android.quickstep.util.RecentsOrientedState.postDisplayRotation;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Point;
|
||||
@@ -33,8 +35,8 @@ import android.view.Surface;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.ResourceUtils;
|
||||
import com.android.launcher3.states.RotationHelper;
|
||||
import com.android.launcher3.util.DefaultDisplay;
|
||||
import com.android.quickstep.util.RecentsOrientedState.SurfaceRotation;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
@@ -52,15 +54,30 @@ class OrientationTouchTransformer {
|
||||
private static final boolean DEBUG = false;
|
||||
private static final int MAX_ORIENTATIONS = 4;
|
||||
|
||||
private final Matrix mTmpMatrix = new Matrix();
|
||||
private final float[] mTmpPoint = new float[2];
|
||||
|
||||
private SparseArray<OrientationRectF> mSwipeTouchRegions = new SparseArray<>(MAX_ORIENTATIONS);
|
||||
private final RectF mAssistantLeftRegion = new RectF();
|
||||
private final RectF mAssistantRightRegion = new RectF();
|
||||
private int mCurrentRotation;
|
||||
private int mCurrentDisplayRotation;
|
||||
private boolean mEnableMultipleRegions;
|
||||
private Resources mResources;
|
||||
private OrientationRectF mLastRectTouched;
|
||||
private SysUINavigationMode.Mode mMode;
|
||||
private QuickStepContractInfo mContractInfo;
|
||||
|
||||
/**
|
||||
* Represents if we're currently in a swipe "session" of sorts. If value is -1, then user
|
||||
* has not tapped on an active nav region. Otherwise it will be the rotation of the display
|
||||
* when the user first interacted with the active nav bar region.
|
||||
* The "session" ends when {@link #enableMultipleRegions(boolean, DefaultDisplay.Info)} is
|
||||
* called - usually from a timeout or if user starts interacting w/ the foreground app.
|
||||
*
|
||||
* This is different than {@link #mLastRectTouched} as it can get reset by the system whereas
|
||||
* the rect is purely used for tracking touch interactions and usually this "session" will
|
||||
* outlast the touch interaction.
|
||||
*/
|
||||
private int mQuickStepStartingRotation = -1;
|
||||
|
||||
/** For testability */
|
||||
@@ -68,6 +85,7 @@ class OrientationTouchTransformer {
|
||||
float getWindowCornerRadius();
|
||||
}
|
||||
|
||||
|
||||
OrientationTouchTransformer(Resources resources, SysUINavigationMode.Mode mode,
|
||||
QuickStepContractInfo contractInfo) {
|
||||
mResources = resources;
|
||||
@@ -92,20 +110,21 @@ class OrientationTouchTransformer {
|
||||
* @see #enableMultipleRegions(boolean, DefaultDisplay.Info)
|
||||
*/
|
||||
void createOrAddTouchRegion(DefaultDisplay.Info info) {
|
||||
mCurrentRotation = info.rotation;
|
||||
if (mQuickStepStartingRotation > -1 && mCurrentRotation == mQuickStepStartingRotation) {
|
||||
// Ignore nav bars in other rotations except for the one we started out in
|
||||
mCurrentDisplayRotation = info.rotation;
|
||||
if (mQuickStepStartingRotation > -1
|
||||
&& mCurrentDisplayRotation == mQuickStepStartingRotation) {
|
||||
// User already was swiping and the current screen is same rotation as the starting one
|
||||
// Remove active nav bars in other rotations except for the one we started out in
|
||||
resetSwipeRegions(info);
|
||||
return;
|
||||
}
|
||||
|
||||
OrientationRectF region = mSwipeTouchRegions.get(mCurrentRotation);
|
||||
OrientationRectF region = mSwipeTouchRegions.get(mCurrentDisplayRotation);
|
||||
if (region != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mEnableMultipleRegions) {
|
||||
mSwipeTouchRegions.put(mCurrentRotation, createRegionForDisplay(info));
|
||||
mSwipeTouchRegions.put(mCurrentDisplayRotation, createRegionForDisplay(info));
|
||||
} else {
|
||||
resetSwipeRegions(info);
|
||||
}
|
||||
@@ -123,12 +142,6 @@ class OrientationTouchTransformer {
|
||||
if (!enableMultipleRegions) {
|
||||
mQuickStepStartingRotation = -1;
|
||||
resetSwipeRegions(info);
|
||||
} else {
|
||||
if (mLastRectTouched != null) {
|
||||
// mLastRectTouched can be null if gesture type is changed (ex. from settings)
|
||||
// but nav bar hasn't been interacted with yet.
|
||||
mQuickStepStartingRotation = mLastRectTouched.mRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,17 +153,25 @@ class OrientationTouchTransformer {
|
||||
*/
|
||||
private void resetSwipeRegions(DefaultDisplay.Info region) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "clearing all regions except rotation: " + mCurrentRotation);
|
||||
Log.d(TAG, "clearing all regions except rotation: " + mCurrentDisplayRotation);
|
||||
}
|
||||
|
||||
mCurrentRotation = region.rotation;
|
||||
mCurrentDisplayRotation = region.rotation;
|
||||
OrientationRectF regionToKeep = mSwipeTouchRegions.get(mCurrentDisplayRotation);
|
||||
mSwipeTouchRegions.clear();
|
||||
mSwipeTouchRegions.put(mCurrentRotation, createRegionForDisplay(region));
|
||||
mSwipeTouchRegions.put(mCurrentDisplayRotation,
|
||||
regionToKeep != null ? regionToKeep : createRegionForDisplay(region));
|
||||
}
|
||||
|
||||
private void resetSwipeRegions() {
|
||||
OrientationRectF regionToKeep = mSwipeTouchRegions.get(mCurrentDisplayRotation);
|
||||
mSwipeTouchRegions.clear();
|
||||
mSwipeTouchRegions.put(mCurrentDisplayRotation, regionToKeep);
|
||||
}
|
||||
|
||||
private OrientationRectF createRegionForDisplay(DefaultDisplay.Info display) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "creating rotation region for: " + mCurrentRotation);
|
||||
Log.d(TAG, "creating rotation region for: " + mCurrentDisplayRotation);
|
||||
}
|
||||
|
||||
Point size = display.realSize;
|
||||
@@ -220,6 +241,10 @@ class OrientationTouchTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
int getQuickStepStartingRotation() {
|
||||
return mQuickStepStartingRotation;
|
||||
}
|
||||
|
||||
public void transform(MotionEvent event) {
|
||||
int eventAction = event.getActionMasked();
|
||||
switch (eventAction) {
|
||||
@@ -252,6 +277,11 @@ class OrientationTouchTransformer {
|
||||
}
|
||||
if (rect.applyTransform(event, false)) {
|
||||
mLastRectTouched = rect;
|
||||
if (mCurrentDisplayRotation == mLastRectTouched.mRotation) {
|
||||
// Start a touch session for the default nav region for the display
|
||||
mQuickStepStartingRotation = mLastRectTouched.mRotation;
|
||||
resetSwipeRegions();
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "set active region: " + rect);
|
||||
}
|
||||
@@ -304,42 +334,46 @@ class OrientationTouchTransformer {
|
||||
}
|
||||
|
||||
boolean applyTransform(MotionEvent event, boolean forceTransform) {
|
||||
// TODO(b/149658423): See if we can use RotationHelper.getRotationMatrix here
|
||||
MotionEvent tmp = MotionEvent.obtain(event);
|
||||
Matrix outMatrix = new Matrix();
|
||||
int delta = RotationHelper.deltaRotation(mCurrentRotation, mRotation);
|
||||
switch (delta) {
|
||||
case Surface.ROTATION_0:
|
||||
outMatrix.reset();
|
||||
break;
|
||||
case Surface.ROTATION_90:
|
||||
outMatrix.setRotate(270);
|
||||
outMatrix.postTranslate(0, mHeight);
|
||||
break;
|
||||
case Surface.ROTATION_180:
|
||||
outMatrix.setRotate(180);
|
||||
outMatrix.postTranslate(mHeight, mWidth);
|
||||
break;
|
||||
case Surface.ROTATION_270:
|
||||
outMatrix.setRotate(90);
|
||||
outMatrix.postTranslate(mWidth, 0);
|
||||
break;
|
||||
mTmpMatrix.reset();
|
||||
postDisplayRotation(deltaRotation(mCurrentDisplayRotation, mRotation),
|
||||
mHeight, mWidth, mTmpMatrix);
|
||||
if (forceTransform) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Transforming rotation due to forceTransform, "
|
||||
+ "mCurrentRotation: " + mCurrentDisplayRotation
|
||||
+ "mRotation: " + mRotation);
|
||||
}
|
||||
event.transform(mTmpMatrix);
|
||||
return true;
|
||||
}
|
||||
mTmpPoint[0] = event.getX();
|
||||
mTmpPoint[1] = event.getY();
|
||||
mTmpMatrix.mapPoints(mTmpPoint);
|
||||
|
||||
tmp.transform(outMatrix);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "original: " + event.getX() + ", " + event.getY()
|
||||
+ " new: " + tmp.getX() + ", " + tmp.getY()
|
||||
+ " new: " + mTmpPoint[0] + ", " + mTmpPoint[1]
|
||||
+ " rect: " + this + " forceTransform: " + forceTransform
|
||||
+ " contains: " + contains(tmp.getX(), tmp.getY()));
|
||||
+ " contains: " + contains(mTmpPoint[0], mTmpPoint[1]));
|
||||
}
|
||||
|
||||
if (forceTransform || contains(tmp.getX(), tmp.getY())) {
|
||||
event.transform(outMatrix);
|
||||
tmp.recycle();
|
||||
if (contains(mTmpPoint[0], mTmpPoint[1])) {
|
||||
event.transform(mTmpMatrix);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return how many factors {@param newRotation} is rotated 90 degrees clockwise.
|
||||
* E.g. 1->Rotated by 90 degrees clockwise, 2->Rotated 180 clockwise...
|
||||
* A value of 0 means no rotation has been applied
|
||||
*/
|
||||
@SurfaceRotation
|
||||
private static int deltaRotation(int oldRotation, int newRotation) {
|
||||
int delta = newRotation - oldRotation;
|
||||
if (delta < 0) delta += 4;
|
||||
return delta;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,7 @@ import com.android.systemui.shared.system.PackageManagerWrapper;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Class to keep track of the current overview component based off user preferences and app updates
|
||||
@@ -57,6 +58,9 @@ public final class OverviewComponentObserver {
|
||||
private final Intent mMyHomeIntent;
|
||||
private final Intent mFallbackIntent;
|
||||
private final SparseIntArray mConfigChangesMap = new SparseIntArray();
|
||||
|
||||
private Consumer<Boolean> mOverviewChangeListener = b -> { };
|
||||
|
||||
private String mUpdateRegisteredPackage;
|
||||
private BaseActivityInterface mActivityInterface;
|
||||
private Intent mOverviewIntent;
|
||||
@@ -64,10 +68,10 @@ public final class OverviewComponentObserver {
|
||||
private boolean mIsDefaultHome;
|
||||
private boolean mIsHomeDisabled;
|
||||
|
||||
|
||||
public OverviewComponentObserver(Context context, RecentsAnimationDeviceState deviceState) {
|
||||
mContext = context;
|
||||
mDeviceState = deviceState;
|
||||
|
||||
mCurrentHomeIntent = new Intent(Intent.ACTION_MAIN)
|
||||
.addCategory(Intent.CATEGORY_HOME)
|
||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
@@ -95,6 +99,13 @@ public final class OverviewComponentObserver {
|
||||
updateOverviewTargets();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a listener for changes in {@link #isHomeAndOverviewSame()}
|
||||
*/
|
||||
public void setOverviewChangeListener(Consumer<Boolean> overviewChangeListener) {
|
||||
mOverviewChangeListener = overviewChangeListener;
|
||||
}
|
||||
|
||||
public void onSystemUiStateChanged() {
|
||||
if (mDeviceState.isHomeDisabled() != mIsHomeDisabled) {
|
||||
updateOverviewTargets();
|
||||
@@ -159,6 +170,7 @@ public final class OverviewComponentObserver {
|
||||
ACTION_PACKAGE_REMOVED));
|
||||
}
|
||||
}
|
||||
mOverviewChangeListener.accept(mIsHomeAndOverviewSame);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -123,6 +123,17 @@ public class RecentTasksList extends TaskStackChangeListener {
|
||||
mChangeId++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentTaskListUpdated() {
|
||||
// In some cases immediately after booting, the tasks in the system recent task list may be
|
||||
// loaded, but not in the active task hierarchy in the system. These tasks are displayed in
|
||||
// overview, but removing them don't result in a onTaskStackChanged() nor a onTaskRemoved()
|
||||
// callback (those are for changes to the active tasks), but the task list is still updated,
|
||||
// so we should also invalidate the change id to ensure we load a new list instead of
|
||||
// reusing a stale list.
|
||||
mChangeId++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskRemoved(int taskId) {
|
||||
mTasks = loadTasksInBackground(Integer.MAX_VALUE, false);
|
||||
|
||||
@@ -91,9 +91,6 @@ public class RecentsAnimationCallbacks implements
|
||||
RemoteAnimationTargetCompat[] appTargets,
|
||||
RemoteAnimationTargetCompat[] wallpaperTargets,
|
||||
Rect homeContentInsets, Rect minimizedHomeBounds) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_START_FROM_RECENTS, "onAnimationStart");
|
||||
}
|
||||
RecentsAnimationTargets targets = new RecentsAnimationTargets(appTargets,
|
||||
wallpaperTargets, homeContentInsets, minimizedHomeBounds);
|
||||
mController = new RecentsAnimationController(animationController,
|
||||
|
||||
@@ -22,13 +22,13 @@ import static android.view.MotionEvent.ACTION_UP;
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.os.SystemClock;
|
||||
import android.util.Log;
|
||||
import android.view.InputEvent;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.util.Preconditions;
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.android.quickstep;
|
||||
|
||||
import static android.content.Intent.ACTION_USER_UNLOCKED;
|
||||
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.THREE_BUTTONS;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
|
||||
@@ -73,6 +74,8 @@ public class RecentsAnimationDeviceState implements
|
||||
NavigationModeChangeListener,
|
||||
DefaultDisplay.DisplayInfoChangeListener {
|
||||
|
||||
private static final String TAG = "RecentsAnimationDeviceState";
|
||||
|
||||
private final Context mContext;
|
||||
private final SysUINavigationMode mSysUiNavMode;
|
||||
private final DefaultDisplay mDefaultDisplay;
|
||||
@@ -95,6 +98,7 @@ public class RecentsAnimationDeviceState implements
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (ACTION_USER_UNLOCKED.equals(intent.getAction())) {
|
||||
Log.d(TAG, "User Unlocked Broadcast Received");
|
||||
mIsUserUnlocked = true;
|
||||
notifyUserUnlocked();
|
||||
}
|
||||
@@ -120,7 +124,6 @@ public class RecentsAnimationDeviceState implements
|
||||
private Runnable mOnDestroyFrozenTaskRunnable;
|
||||
|
||||
public RecentsAnimationDeviceState(Context context) {
|
||||
final ContentResolver resolver = context.getContentResolver();
|
||||
mContext = context;
|
||||
mSysUiNavMode = SysUINavigationMode.INSTANCE.get(context);
|
||||
mDefaultDisplay = DefaultDisplay.INSTANCE.get(context);
|
||||
@@ -511,8 +514,16 @@ public class RecentsAnimationDeviceState implements
|
||||
mOrientationTouchTransformer.transform(event);
|
||||
}
|
||||
|
||||
public void enableMultipleRegions(boolean enable) {
|
||||
void enableMultipleRegions(boolean enable) {
|
||||
mOrientationTouchTransformer.enableMultipleRegions(enable, mDefaultDisplay.getInfo());
|
||||
if (enable) {
|
||||
UI_HELPER_EXECUTOR.execute(() -> {
|
||||
int quickStepStartingRotation =
|
||||
mOrientationTouchTransformer.getQuickStepStartingRotation();
|
||||
SystemUiProxy.INSTANCE.get(mContext)
|
||||
.onQuickSwitchToNewTask(quickStepStartingRotation);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public int getCurrentActiveRotation() {
|
||||
|
||||
@@ -334,6 +334,7 @@ public class SystemUiProxy implements ISystemUiProxy {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuickSwitchToNewTask(int rotation) {
|
||||
if (mSystemUiProxy != null) {
|
||||
try {
|
||||
|
||||
@@ -53,9 +53,6 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
||||
@UiThread
|
||||
public RecentsAnimationCallbacks startRecentsAnimation(GestureState gestureState,
|
||||
Intent intent, RecentsAnimationCallbacks.RecentsAnimationListener listener) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
Log.d(TestProtocol.NO_START_FROM_RECENTS, "startRecentsAnimation");
|
||||
}
|
||||
// Notify if recents animation is still running
|
||||
if (mController != null) {
|
||||
String msg = "New recents animation started before old animation completed";
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ final class BackGestureTutorialEngagedController extends BackGestureTutorialCont
|
||||
@Override
|
||||
void transitToController() {
|
||||
super.transitToController();
|
||||
mHandCoachingAnimation.maybeStartLoopedAnimation(mTutorialTypeInfo.get().getTutorialType());
|
||||
mHandCoachingAnimation.startLoopedAnimation(mTutorialTypeInfo.get().getTutorialType());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+7
-20
@@ -38,8 +38,6 @@ final class BackGestureTutorialHandAnimation {
|
||||
private final ImageView mHandCoachingView;
|
||||
private final AnimatedVectorDrawable mGestureAnimation;
|
||||
|
||||
private boolean mIsAnimationPlayed = false;
|
||||
|
||||
BackGestureTutorialHandAnimation(Context context, View rootView) {
|
||||
mHandCoachingView = rootView.findViewById(
|
||||
R.id.back_gesture_tutorial_fragment_hand_coaching);
|
||||
@@ -47,20 +45,15 @@ final class BackGestureTutorialHandAnimation {
|
||||
R.drawable.back_gesture);
|
||||
}
|
||||
|
||||
boolean isRunning() {
|
||||
return mGestureAnimation.isRunning();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts animation if the playground is launched for the first time.
|
||||
* [Re]starts animation for the given tutorial.
|
||||
*/
|
||||
void maybeStartLoopedAnimation(TutorialType tutorialType) {
|
||||
if (isRunning() || mIsAnimationPlayed) {
|
||||
return;
|
||||
void startLoopedAnimation(TutorialType tutorialType) {
|
||||
if (mGestureAnimation.isRunning()) {
|
||||
stop();
|
||||
}
|
||||
|
||||
mIsAnimationPlayed = true;
|
||||
clearAnimationCallbacks();
|
||||
mGestureAnimation.clearAnimationCallbacks();
|
||||
mGestureAnimation.registerAnimationCallback(
|
||||
new Animatable2.AnimationCallback() {
|
||||
@Override
|
||||
@@ -78,17 +71,11 @@ final class BackGestureTutorialHandAnimation {
|
||||
float rotationY = tutorialType == TutorialType.LEFT_EDGE_BACK_NAVIGATION ? 180f : 0f;
|
||||
mHandCoachingView.setRotationY(rotationY);
|
||||
mHandCoachingView.setImageDrawable(mGestureAnimation);
|
||||
mHandCoachingView.postDelayed(() -> mGestureAnimation.start(),
|
||||
ANIMATION_START_DELAY.toMillis());
|
||||
}
|
||||
|
||||
private void clearAnimationCallbacks() {
|
||||
mGestureAnimation.clearAnimationCallbacks();
|
||||
mHandCoachingView.postDelayed(mGestureAnimation::start, ANIMATION_START_DELAY.toMillis());
|
||||
}
|
||||
|
||||
void stop() {
|
||||
mIsAnimationPlayed = false;
|
||||
clearAnimationCallbacks();
|
||||
mGestureAnimation.clearAnimationCallbacks();
|
||||
mGestureAnimation.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,16 +23,16 @@ import static android.stats.launcher.nano.Launcher.OVERVIEW;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.launcher3.FolderInfo;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.logger.LauncherAtom;
|
||||
import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.logging.StatsLogUtils;
|
||||
import com.android.launcher3.model.AllAppsList;
|
||||
import com.android.launcher3.model.BaseModelUpdateTask;
|
||||
import com.android.launcher3.model.BgDataModel;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.util.IntSparseArrayMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.quickstep.util;
|
||||
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager;
|
||||
import com.android.launcher3.LauncherStateManager.StateListener;
|
||||
import com.android.launcher3.util.OnboardingPrefs;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
|
||||
/**
|
||||
* Extends {@link OnboardingPrefs} for quickstep-specific onboarding data.
|
||||
*/
|
||||
public class QuickstepOnboardingPrefs extends OnboardingPrefs<BaseQuickstepLauncher> {
|
||||
|
||||
public QuickstepOnboardingPrefs(BaseQuickstepLauncher launcher, SharedPreferences sharedPrefs,
|
||||
LauncherStateManager stateManager) {
|
||||
super(launcher, sharedPrefs, stateManager);
|
||||
|
||||
if (!getBoolean(HOME_BOUNCE_SEEN)) {
|
||||
mStateManager.addStateListener(new StateListener() {
|
||||
@Override
|
||||
public void onStateTransitionStart(LauncherState toState) { }
|
||||
|
||||
@Override
|
||||
public void onStateTransitionComplete(LauncherState finalState) {
|
||||
boolean swipeUpEnabled = SysUINavigationMode.INSTANCE
|
||||
.get(mLauncher).getMode().hasGestures;
|
||||
LauncherState prevState = mStateManager.getLastState();
|
||||
|
||||
if (((swipeUpEnabled && finalState == OVERVIEW) || (!swipeUpEnabled
|
||||
&& finalState == ALL_APPS && prevState == NORMAL) ||
|
||||
hasReachedMaxCount(HOME_BOUNCE_COUNT))) {
|
||||
mSharedPrefs.edit().putBoolean(HOME_BOUNCE_SEEN, true).apply();
|
||||
mStateManager.removeStateListener(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!getBoolean(SHELF_BOUNCE_SEEN)) {
|
||||
mStateManager.addStateListener(new StateListener() {
|
||||
@Override
|
||||
public void onStateTransitionStart(LauncherState toState) { }
|
||||
|
||||
@Override
|
||||
public void onStateTransitionComplete(LauncherState finalState) {
|
||||
LauncherState prevState = mStateManager.getLastState();
|
||||
|
||||
if ((finalState == ALL_APPS && prevState == OVERVIEW) ||
|
||||
hasReachedMaxCount(SHELF_BOUNCE_COUNT)) {
|
||||
mSharedPrefs.edit().putBoolean(SHELF_BOUNCE_SEEN, true).apply();
|
||||
mStateManager.removeStateListener(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!hasReachedMaxCount(ALL_APPS_COUNT)) {
|
||||
mStateManager.addStateListener(new StateListener() {
|
||||
@Override
|
||||
public void onStateTransitionStart(LauncherState toState) { }
|
||||
|
||||
@Override
|
||||
public void onStateTransitionComplete(LauncherState finalState) {
|
||||
if (finalState == ALL_APPS) {
|
||||
if (incrementEventCount(ALL_APPS_COUNT)) {
|
||||
mStateManager.removeStateListener(this);
|
||||
mLauncher.getScrimView().updateDragHandleVisibility();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.quickstep.util;
|
||||
|
||||
import static android.hardware.camera2.params.OutputConfiguration.ROTATION_180;
|
||||
import static android.view.Surface.ROTATION_0;
|
||||
import static android.view.Surface.ROTATION_270;
|
||||
import static android.view.Surface.ROTATION_90;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.RectF;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.Surface;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.touch.PortraitPagedViewHandler;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
/**
|
||||
* Container to hold orientation/rotation related information for Launcher.
|
||||
* This is not meant to be an abstraction layer for applying different functionality between
|
||||
* the different orientation/rotations. For that see {@link PagedOrientationHandler}
|
||||
*
|
||||
* This class has initial default state assuming the device and foreground app have
|
||||
* no ({@link Surface#ROTATION_0} rotation.
|
||||
*/
|
||||
public final class RecentsOrientedState {
|
||||
|
||||
@Retention(SOURCE)
|
||||
@IntDef({ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270})
|
||||
public @interface SurfaceRotation {}
|
||||
|
||||
private PagedOrientationHandler mOrientationHandler = PagedOrientationHandler.PORTRAIT;
|
||||
|
||||
private @SurfaceRotation int mTouchRotation = ROTATION_0;
|
||||
private @SurfaceRotation int mDisplayRotation = ROTATION_0;
|
||||
/**
|
||||
* If {@code true} we default to {@link PortraitPagedViewHandler} and don't support any fake
|
||||
* launcher orientations.
|
||||
*/
|
||||
private boolean mDisableMultipleOrientations;
|
||||
|
||||
private final Matrix mTmpMatrix = new Matrix();
|
||||
private final Matrix mTmpInverseMatrix = new Matrix();
|
||||
|
||||
/**
|
||||
* Sets the appropriate {@link PagedOrientationHandler} for {@link #mOrientationHandler}
|
||||
* @param touchRotation The rotation the nav bar region that is touched is in
|
||||
* @param displayRotation Rotation of the display/device
|
||||
*
|
||||
* @return true if there was any change in the internal state as a result of this call,
|
||||
* false otherwise
|
||||
*/
|
||||
public boolean update(
|
||||
@SurfaceRotation int touchRotation, @SurfaceRotation int displayRotation) {
|
||||
if (!FeatureFlags.ENABLE_FIXED_ROTATION_TRANSFORM.get()) {
|
||||
return false;
|
||||
}
|
||||
if (mDisableMultipleOrientations) {
|
||||
return false;
|
||||
}
|
||||
if (mDisplayRotation == displayRotation && mTouchRotation == touchRotation) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mDisplayRotation = displayRotation;
|
||||
mTouchRotation = touchRotation;
|
||||
if (mTouchRotation == ROTATION_90) {
|
||||
mOrientationHandler = PagedOrientationHandler.LANDSCAPE;
|
||||
} else if (mTouchRotation == ROTATION_270) {
|
||||
mOrientationHandler = PagedOrientationHandler.SEASCAPE;
|
||||
} else {
|
||||
mOrientationHandler = PagedOrientationHandler.PORTRAIT;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean areMultipleLayoutOrientationsDisabled() {
|
||||
return mDisableMultipleOrientations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting this preference will render future calls to {@link #update(int, int)} as a no-op.
|
||||
*/
|
||||
public void disableMultipleOrientations(boolean disable) {
|
||||
mDisableMultipleOrientations = disable;
|
||||
if (disable) {
|
||||
mDisplayRotation = mTouchRotation = ROTATION_0;
|
||||
mOrientationHandler = PagedOrientationHandler.PORTRAIT;
|
||||
}
|
||||
}
|
||||
|
||||
@SurfaceRotation
|
||||
public int getDisplayRotation() {
|
||||
return mDisplayRotation;
|
||||
}
|
||||
|
||||
@SurfaceRotation
|
||||
public int getTouchRotation() {
|
||||
return mTouchRotation;
|
||||
}
|
||||
|
||||
public int getTouchRotationDegrees() {
|
||||
switch (mTouchRotation) {
|
||||
case ROTATION_90:
|
||||
return 90;
|
||||
case ROTATION_180:
|
||||
return 180;
|
||||
case ROTATION_270:
|
||||
return 270;
|
||||
case ROTATION_0:
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public PagedOrientationHandler getOrientationHandler() {
|
||||
return mOrientationHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* For landscape, since the navbar is already in a vertical position, we don't have to do any
|
||||
* rotations as the change in Y coordinate is what is read. We only flip the sign of the
|
||||
* y coordinate to make it match existing behavior of swipe to the top to go previous
|
||||
*/
|
||||
public void flipVertical(MotionEvent ev) {
|
||||
mTmpMatrix.setScale(1, -1);
|
||||
ev.transform(mTmpMatrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a matrix to transform the given motion event specified by degrees.
|
||||
* If inverse is {@code true}, the inverse of that matrix will be applied
|
||||
*/
|
||||
public void transformEvent(float degrees, MotionEvent ev, boolean inverse) {
|
||||
mTmpMatrix.setRotate(inverse ? -degrees : degrees);
|
||||
ev.transform(mTmpMatrix);
|
||||
|
||||
// TODO: Add scaling back in based on degrees
|
||||
/*
|
||||
if (getWidth() > 0 && getHeight() > 0) {
|
||||
float scale = ((float) getWidth()) / getHeight();
|
||||
transform.postScale(scale, 1 / scale);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
public void mapRectFromNormalOrientation(RectF src, int screenWidth, int screenHeight) {
|
||||
mTmpMatrix.reset();
|
||||
postDisplayRotation(mDisplayRotation, screenWidth, screenHeight, mTmpMatrix);
|
||||
mTmpMatrix.mapRect(src);
|
||||
}
|
||||
|
||||
public void mapInverseRectFromNormalOrientation(RectF src, int screenWidth, int screenHeight) {
|
||||
mTmpMatrix.reset();
|
||||
postDisplayRotation(mDisplayRotation, screenWidth, screenHeight, mTmpMatrix);
|
||||
mTmpMatrix.invert(mTmpInverseMatrix);
|
||||
mTmpInverseMatrix.mapRect(src);
|
||||
}
|
||||
|
||||
@SurfaceRotation
|
||||
public static int getRotationForUserDegreesRotated(float degrees) {
|
||||
int threshold = 70;
|
||||
if (degrees >= (360 - threshold) || degrees < (threshold)) {
|
||||
return ROTATION_0;
|
||||
} else if (degrees < (90 + threshold)) {
|
||||
return ROTATION_270;
|
||||
} else if (degrees < 180 + threshold) {
|
||||
return ROTATION_180;
|
||||
} else {
|
||||
return ROTATION_90;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Posts the transformation on the matrix representing the provided display rotation
|
||||
*/
|
||||
public static void postDisplayRotation(@SurfaceRotation int displayRotation,
|
||||
float screenWidth, float screenHeight, Matrix out) {
|
||||
switch (displayRotation) {
|
||||
case ROTATION_0:
|
||||
return;
|
||||
case ROTATION_90:
|
||||
out.postRotate(270);
|
||||
out.postTranslate(0, screenWidth);
|
||||
break;
|
||||
case ROTATION_180:
|
||||
out.postRotate(180);
|
||||
out.postTranslate(screenHeight, screenWidth);
|
||||
break;
|
||||
case ROTATION_270:
|
||||
out.postRotate(90);
|
||||
out.postTranslate(screenHeight, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.uioverrides.states.OverviewState;
|
||||
import com.android.launcher3.util.OnboardingPrefs;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.views.ScrimView;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
@@ -75,6 +76,7 @@ public class ShelfScrimView extends ScrimView<BaseQuickstepLauncher>
|
||||
private final float mRadius;
|
||||
private final int mMaxScrimAlpha;
|
||||
private final Paint mPaint;
|
||||
private final OnboardingPrefs mOnboardingPrefs;
|
||||
|
||||
// Mid point where the alpha changes
|
||||
private int mMidAlpha;
|
||||
@@ -100,6 +102,7 @@ public class ShelfScrimView extends ScrimView<BaseQuickstepLauncher>
|
||||
private boolean mRemainingScreenPathValid = false;
|
||||
|
||||
private Mode mSysUINavigationMode;
|
||||
private boolean mIsTwoZoneSwipeModel;
|
||||
|
||||
public ShelfScrimView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
@@ -108,6 +111,7 @@ public class ShelfScrimView extends ScrimView<BaseQuickstepLauncher>
|
||||
mEndAlpha = Color.alpha(mEndScrim);
|
||||
mRadius = BOTTOM_CORNER_RADIUS_RATIO * Themes.getDialogCornerRadius(context);
|
||||
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mOnboardingPrefs = mLauncher.getOnboardingPrefs();
|
||||
|
||||
// Just assume the easiest UI for now, until we have the proper layout information.
|
||||
mDrawingFlatColor = true;
|
||||
@@ -140,9 +144,11 @@ public class ShelfScrimView extends ScrimView<BaseQuickstepLauncher>
|
||||
// Show the shelf more quickly before reaching overview progress.
|
||||
mBeforeMidProgressColorInterpolator = ACCEL_2;
|
||||
mAfterMidProgressColorInterpolator = ACCEL;
|
||||
mIsTwoZoneSwipeModel = FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get();
|
||||
} else {
|
||||
mBeforeMidProgressColorInterpolator = ACCEL;
|
||||
mAfterMidProgressColorInterpolator = Interpolators.clampToProgress(ACCEL, 0.5f, 1f);
|
||||
mIsTwoZoneSwipeModel = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,9 +242,9 @@ public class ShelfScrimView extends ScrimView<BaseQuickstepLauncher>
|
||||
|
||||
@Override
|
||||
protected boolean shouldDragHandleBeVisible() {
|
||||
boolean twoZoneSwipeModel = FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get()
|
||||
&& SysUINavigationMode.removeShelfFromOverview(mLauncher);
|
||||
return twoZoneSwipeModel || super.shouldDragHandleBeVisible();
|
||||
boolean needsAllAppsEdu = mIsTwoZoneSwipeModel
|
||||
&& !mOnboardingPrefs.hasReachedMaxCount(OnboardingPrefs.ALL_APPS_COUNT);
|
||||
return needsAllAppsEdu || super.shouldDragHandleBeVisible();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -48,9 +48,9 @@ import androidx.test.uiautomator.By;
|
||||
import androidx.test.uiautomator.UiDevice;
|
||||
import androidx.test.uiautomator.Until;
|
||||
|
||||
import com.android.launcher3.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.tapl.Background;
|
||||
import com.android.launcher3.testcomponent.ListViewService;
|
||||
import com.android.launcher3.testcomponent.ListViewService.SimpleViewsFactory;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
style="@style/PrimaryMediumText"
|
||||
style="@style/PrimaryHeadline"
|
||||
android:textColor="?attr/workProfileOverlayTextColor"
|
||||
android:id="@+id/work_apps_paused_title"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@@ -118,6 +118,8 @@
|
||||
<!-- numHotseatIcons defaults to numColumns, if not specified -->
|
||||
<attr name="numHotseatIcons" format="integer" />
|
||||
<attr name="dbFile" format="string" />
|
||||
<!-- numAllAppsColumns defaults to numColumns, if not specified -->
|
||||
<attr name="numAllAppsColumns" format="integer" />
|
||||
<attr name="defaultLayoutId" format="reference" />
|
||||
<attr name="demoModeLayoutId" format="reference" />
|
||||
</declare-styleable>
|
||||
@@ -133,6 +135,12 @@
|
||||
<attr name="iconTextSize" format="float" />
|
||||
<!-- If true, this display option is used to determine the default grid -->
|
||||
<attr name="canBeDefault" format="boolean" />
|
||||
|
||||
<!-- The following values are only enabled if grid is supported. -->
|
||||
<!-- allAppsIconSize defaults to iconSize, if not specified -->
|
||||
<attr name="allAppsIconSize" format="float" />
|
||||
<!-- allAppsIconTextSize defaults to iconTextSize, if not specified -->
|
||||
<attr name="allAppsIconTextSize" format="float" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="CellLayout">
|
||||
|
||||
@@ -131,8 +131,8 @@
|
||||
<item name="dismiss_task_trans_x_damping_ratio" type="dimen" format="float">0.5</item>
|
||||
<item name="dismiss_task_trans_x_stiffness" type="dimen" format="float">1500</item>
|
||||
|
||||
<item name="horizontal_spring_damping_ratio" type="dimen" format="float">0.75</item>
|
||||
<item name="horizontal_spring_stiffness" type="dimen" format="float">200</item>
|
||||
<item name="horizontal_spring_damping_ratio" type="dimen" format="float">0.8</item>
|
||||
<item name="horizontal_spring_stiffness" type="dimen" format="float">400</item>
|
||||
|
||||
<item name="swipe_up_rect_scale_damping_ratio" type="dimen" format="float">0.75</item>
|
||||
<item name="swipe_up_rect_scale_stiffness" type="dimen" format="float">200</item>
|
||||
|
||||
@@ -343,6 +343,10 @@
|
||||
<string name="work_apps_paused_title">Work profile is paused</string>
|
||||
<!--- body shown when user opens work apps tab while work apps are paused -->
|
||||
<string name="work_apps_paused_body">Work apps can\’t send you notifications, use your battery, or access your location</string>
|
||||
<!-- content description for paused work apps list -->
|
||||
<string name="work_apps_paused_content_description">Work profile is paused. Work apps can\’t send you notifications, use your battery, or access your location</string>
|
||||
|
||||
|
||||
|
||||
<!-- A tip shown pointing at work toggle -->
|
||||
<string name="work_switch_tip">Pause work apps and notifications</string>
|
||||
|
||||
@@ -226,6 +226,9 @@
|
||||
|
||||
<style name="TextHeadline" parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle" />
|
||||
<style name="PrimaryMediumText" parent="@android:style/TextAppearance.DeviceDefault.Medium"/>
|
||||
<style name="PrimaryHeadline" parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle">
|
||||
<item name="android:textStyle">bold</item>
|
||||
</style>
|
||||
|
||||
<style name="TextTitle" parent="@android:style/TextAppearance.DeviceDefault" />
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := LauncherRoboTests
|
||||
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
|
||||
|
||||
LOCAL_SDK_VERSION := current
|
||||
LOCAL_SDK_VERSION := system_current
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
LOCAL_STATIC_JAVA_LIBRARIES := \
|
||||
androidx.test.runner \
|
||||
@@ -47,7 +47,7 @@ include $(BUILD_STATIC_JAVA_LIBRARY)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := RunLauncherRoboTests
|
||||
LOCAL_SDK_VERSION := current
|
||||
LOCAL_SDK_VERSION := system_current
|
||||
LOCAL_JAVA_LIBRARIES := LauncherRoboTests
|
||||
|
||||
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
|
||||
|
||||
@@ -1 +1,17 @@
|
||||
sdk=29
|
||||
shadows= \
|
||||
com.android.launcher3.shadows.LShadowAppPredictionManager \
|
||||
com.android.launcher3.shadows.LShadowAppWidgetManager \
|
||||
com.android.launcher3.shadows.LShadowBackupManager \
|
||||
com.android.launcher3.shadows.LShadowBitmap \
|
||||
com.android.launcher3.shadows.LShadowLauncherApps \
|
||||
com.android.launcher3.shadows.LShadowTypeface \
|
||||
com.android.launcher3.shadows.LShadowUserManager \
|
||||
com.android.launcher3.shadows.LShadowWallpaperManager \
|
||||
com.android.launcher3.shadows.ShadowDeviceFlag \
|
||||
com.android.launcher3.shadows.ShadowLooperExecutor \
|
||||
com.android.launcher3.shadows.ShadowMainThreadInitializedObject \
|
||||
com.android.launcher3.shadows.ShadowOverrides \
|
||||
com.android.launcher3.shadows.ShadowSyncRtSurfaceTransactionApplierCompat \
|
||||
|
||||
application=com.android.launcher3.util.LauncherTestApplication
|
||||
@@ -1,6 +1,6 @@
|
||||
# Model data used by CacheDataUpdatedTaskTest
|
||||
|
||||
classMap s com.android.launcher3.WorkspaceItemInfo
|
||||
classMap s com.android.launcher3.model.data.WorkspaceItemInfo
|
||||
|
||||
# Items for the BgDataModel
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Model data used by PackageInstallStateChangeTaskTest
|
||||
|
||||
classMap s com.android.launcher3.WorkspaceItemInfo
|
||||
classMap w com.android.launcher3.LauncherAppWidgetInfo
|
||||
classMap s com.android.launcher3.model.data.WorkspaceItemInfo
|
||||
classMap w com.android.launcher3.model.data.LauncherAppWidgetInfo
|
||||
|
||||
# Items for the BgDataModel
|
||||
|
||||
|
||||
@@ -20,20 +20,20 @@ import static org.junit.Assert.assertEquals;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.shadows.LShadowUserManager;
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public final class FolderNameProviderTest {
|
||||
private Context mContext;
|
||||
private WorkspaceItemInfo mItem1;
|
||||
@@ -45,13 +45,13 @@ public final class FolderNameProviderTest {
|
||||
mItem1 = new WorkspaceItemInfo(new AppInfo(
|
||||
new ComponentName("a.b.c", "a.b.c/a.b.c.d"),
|
||||
"title1",
|
||||
LShadowUserManager.newUserHandle(10),
|
||||
UserHandle.of(10),
|
||||
new Intent().setComponent(new ComponentName("a.b.c", "a.b.c/a.b.c.d"))
|
||||
));
|
||||
mItem2 = new WorkspaceItemInfo(new AppInfo(
|
||||
new ComponentName("a.b.c", "a.b.c/a.b.c.d"),
|
||||
"title2",
|
||||
LShadowUserManager.newUserHandle(10),
|
||||
UserHandle.of(10),
|
||||
new Intent().setComponent(new ComponentName("a.b.c", "a.b.c/a.b.c.d"))
|
||||
));
|
||||
}
|
||||
|
||||
@@ -3,12 +3,11 @@ package com.android.launcher3.logging;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.util.Scheduler;
|
||||
@@ -21,7 +20,7 @@ import java.util.Calendar;
|
||||
/**
|
||||
* Tests for {@link FileLog}
|
||||
*/
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class FileLogTest {
|
||||
|
||||
private File mTempDir;
|
||||
|
||||
@@ -14,23 +14,23 @@ import android.graphics.Rect;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.model.BgDataModel.Callbacks;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.util.ContentWriter;
|
||||
import com.android.launcher3.util.GridOccupancy;
|
||||
import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.util.IntSparseArrayMap;
|
||||
import com.android.launcher3.util.LauncherModelHelper;
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.LooperMode;
|
||||
import org.robolectric.annotation.LooperMode.Mode;
|
||||
@@ -41,7 +41,7 @@ import java.util.List;
|
||||
/**
|
||||
* Tests for {@link AddWorkspaceItemsTask}
|
||||
*/
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@LooperMode(Mode.PAUSED)
|
||||
public class AddWorkspaceItemsTaskTest {
|
||||
|
||||
|
||||
@@ -43,11 +43,11 @@ import com.android.launcher3.provider.RestoreDbTask;
|
||||
import com.android.launcher3.shadows.LShadowBackupManager;
|
||||
import com.android.launcher3.shadows.LShadowUserManager;
|
||||
import com.android.launcher3.util.LauncherModelHelper;
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.LooperMode;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
@@ -55,7 +55,7 @@ import org.robolectric.shadow.api.Shadow;
|
||||
/**
|
||||
* Tests to verify backup and restore flow.
|
||||
*/
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@LooperMode(LooperMode.Mode.PAUSED)
|
||||
public class BackupRestoreTest {
|
||||
|
||||
|
||||
@@ -17,19 +17,19 @@ import android.os.UserManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.icons.cache.CachingLogic;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.util.LauncherModelHelper;
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.LooperMode;
|
||||
import org.robolectric.annotation.LooperMode.Mode;
|
||||
@@ -40,7 +40,7 @@ import java.util.HashSet;
|
||||
/**
|
||||
* Tests for {@link CacheDataUpdatedTask}
|
||||
*/
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@LooperMode(Mode.PAUSED)
|
||||
public class CacheDataUpdatedTaskTest {
|
||||
|
||||
|
||||
@@ -36,11 +36,11 @@ import com.android.launcher3.LauncherProvider;
|
||||
import com.android.launcher3.LauncherProvider.DatabaseHelper;
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.io.File;
|
||||
@@ -48,7 +48,7 @@ import java.io.File;
|
||||
/**
|
||||
* Tests for {@link DbDowngradeHelper}
|
||||
*/
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class DbDowngradeHelperTest {
|
||||
|
||||
private static final String SCHEMA_FILE = "test_schema.json";
|
||||
|
||||
@@ -28,17 +28,17 @@ import android.content.pm.PackageInstaller;
|
||||
import android.content.pm.PackageInstaller.SessionInfo;
|
||||
import android.content.pm.PackageInstaller.SessionParams;
|
||||
|
||||
import com.android.launcher3.FolderInfo;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.util.LauncherLayoutBuilder;
|
||||
import com.android.launcher3.util.LauncherModelHelper;
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.LooperMode;
|
||||
import org.robolectric.annotation.LooperMode.Mode;
|
||||
@@ -46,7 +46,7 @@ import org.robolectric.annotation.LooperMode.Mode;
|
||||
/**
|
||||
* Tests for layout parser for remote layout
|
||||
*/
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@LooperMode(Mode.PAUSED)
|
||||
public class DefaultLayoutProviderTest {
|
||||
|
||||
|
||||
@@ -23,17 +23,17 @@ import android.graphics.Point;
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.LauncherSettings.Settings;
|
||||
import com.android.launcher3.util.LauncherModelHelper;
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link GridBackupTable}
|
||||
*/
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class GridBackupTableTest {
|
||||
|
||||
private static final int BACKUP_ITEM_COUNT = 12;
|
||||
|
||||
@@ -20,11 +20,11 @@ import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.model.GridSizeMigrationTask.MultiStepMigrationTask;
|
||||
import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.util.LauncherModelHelper;
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.HashSet;
|
||||
@@ -33,7 +33,7 @@ import java.util.LinkedList;
|
||||
/**
|
||||
* Unit tests for {@link GridSizeMigrationTask}
|
||||
*/
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class GridSizeMigrationTaskTest {
|
||||
|
||||
private LauncherModelHelper mModelHelper;
|
||||
|
||||
@@ -39,17 +39,17 @@ import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.pm.UserCache;
|
||||
import com.android.launcher3.util.LauncherModelHelper;
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.HashSet;
|
||||
|
||||
/** Unit tests for {@link GridSizeMigrationTaskV2} */
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class GridSizeMigrationTaskV2Test {
|
||||
|
||||
private LauncherModelHelper mModelHelper;
|
||||
|
||||
@@ -50,17 +50,17 @@ import android.database.MatrixCursor;
|
||||
import android.os.Process;
|
||||
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.util.Executors;
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.LooperMode;
|
||||
import org.robolectric.annotation.LooperMode.Mode;
|
||||
@@ -68,7 +68,7 @@ import org.robolectric.annotation.LooperMode.Mode;
|
||||
/**
|
||||
* Tests for {@link LoaderCursor}
|
||||
*/
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@LooperMode(Mode.PAUSED)
|
||||
public class LoaderCursorTest {
|
||||
|
||||
@@ -127,7 +127,7 @@ public class LoaderCursorTest {
|
||||
new Intent().setComponent(cn), false /* allowMissingTarget */, true))
|
||||
.get();
|
||||
assertNotNull(info);
|
||||
assertTrue(PackageManagerHelper.isLauncherAppTarget(info.intent));
|
||||
assertTrue(PackageManagerHelper.isLauncherAppTarget(info.getIntent()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -141,7 +141,7 @@ public class LoaderCursorTest {
|
||||
new Intent().setComponent(cn), true /* allowMissingTarget */, true))
|
||||
.get();
|
||||
assertNotNull(info);
|
||||
assertTrue(PackageManagerHelper.isLauncherAppTarget(info.intent));
|
||||
assertTrue(PackageManagerHelper.isLauncherAppTarget(info.getIntent()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -26,20 +26,20 @@ import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.os.Process;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.PagedView;
|
||||
import com.android.launcher3.model.BgDataModel.Callbacks;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.util.Executors;
|
||||
import com.android.launcher3.util.LauncherLayoutBuilder;
|
||||
import com.android.launcher3.util.LauncherModelHelper;
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
import com.android.launcher3.util.LooperExecutor;
|
||||
import com.android.launcher3.util.ViewOnDrawExecutor;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.LooperMode;
|
||||
import org.robolectric.annotation.LooperMode.Mode;
|
||||
@@ -55,7 +55,7 @@ import java.util.stream.Collectors;
|
||||
/**
|
||||
* Tests to verify multiple callbacks in Loader
|
||||
*/
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@LooperMode(Mode.PAUSED)
|
||||
public class ModelMultiCallbacksTest {
|
||||
|
||||
|
||||
+5
-5
@@ -2,16 +2,16 @@ package com.android.launcher3.model;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.WorkspaceItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.pm.PackageInstallInfo;
|
||||
import com.android.launcher3.util.LauncherModelHelper;
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.annotation.LooperMode;
|
||||
import org.robolectric.annotation.LooperMode.Mode;
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.util.HashSet;
|
||||
/**
|
||||
* Tests for {@link PackageInstallStateChangedTask}
|
||||
*/
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@LooperMode(Mode.PAUSED)
|
||||
public class PackageInstallStateChangedTaskTest {
|
||||
|
||||
|
||||
@@ -27,10 +27,9 @@ import static org.mockito.Mockito.spy;
|
||||
|
||||
import android.content.pm.ShortcutInfo;
|
||||
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -40,7 +39,7 @@ import java.util.List;
|
||||
/**
|
||||
* Tests the sorting and filtering of shortcuts in {@link PopupPopulator}.
|
||||
*/
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class PopupPopulatorTest {
|
||||
|
||||
@Test
|
||||
|
||||
@@ -23,16 +23,16 @@ import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import com.android.launcher3.LauncherProvider.DatabaseHelper;
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
/**
|
||||
* Tests for {@link RestoreDbTask}
|
||||
*/
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class RestoreDbTaskTest {
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.shadows;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import android.app.prediction.AppPredictionContext;
|
||||
import android.app.prediction.AppPredictionManager;
|
||||
import android.app.prediction.AppPredictor;
|
||||
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
|
||||
/**
|
||||
* Shadow for {@link AppPredictionManager} which create mock predictors
|
||||
*/
|
||||
@Implements(value = AppPredictionManager.class)
|
||||
public class LShadowAppPredictionManager {
|
||||
|
||||
@Implementation
|
||||
public AppPredictor createAppPredictionSession(AppPredictionContext predictionContext) {
|
||||
return mock(AppPredictor.class);
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.launcher3.shadows;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.SparseBooleanArray;
|
||||
@@ -51,12 +50,4 @@ public class LShadowUserManager extends ShadowUserManager {
|
||||
public void setUserLocked(UserHandle userHandle, boolean enabled) {
|
||||
mLockedUsers.put(userHandle.hashCode(), enabled);
|
||||
}
|
||||
|
||||
// Create user handle from parcel since UserHandle.of() was only added in later APIs.
|
||||
public static UserHandle newUserHandle(int uid) {
|
||||
Parcel userParcel = Parcel.obtain();
|
||||
userParcel.writeInt(uid);
|
||||
userParcel.setDataPosition(0);
|
||||
return new UserHandle(userParcel);
|
||||
}
|
||||
}
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.shadows;
|
||||
|
||||
import static org.robolectric.shadow.api.Shadow.invokeConstructor;
|
||||
import static org.robolectric.util.ReflectionHelpers.ClassParameter.from;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
import org.robolectric.annotation.RealObject;
|
||||
|
||||
/**
|
||||
* Shadow for SyncRtSurfaceTransactionApplierCompat to override default functionality
|
||||
*/
|
||||
@Implements(className = "com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat",
|
||||
isInAndroidSdk = false)
|
||||
public class ShadowSyncRtSurfaceTransactionApplierCompat {
|
||||
|
||||
@RealObject
|
||||
private Object mRealObject;
|
||||
|
||||
@Implementation
|
||||
protected void __constructor__(View view) {
|
||||
invokeConstructor(mRealObject.getClass(), mRealObject, from(View.class, null));
|
||||
}
|
||||
}
|
||||
@@ -14,23 +14,20 @@
|
||||
* limitations under the License.
|
||||
*/package com.android.launcher3.ui;
|
||||
|
||||
import static android.view.View.MeasureSpec.EXACTLY;
|
||||
import static android.view.View.MeasureSpec.makeMeasureSpec;
|
||||
|
||||
import static com.android.launcher3.util.LauncherModelHelper.TEST_PACKAGE;
|
||||
import static com.android.launcher3.util.LauncherUIHelper.buildAndBindLauncher;
|
||||
import static com.android.launcher3.util.LauncherUIHelper.doLayout;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.SystemClock;
|
||||
import android.provider.Settings;
|
||||
import android.view.InputDevice;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.MotionEvent.PointerProperties;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
@@ -44,24 +41,21 @@ import com.android.launcher3.shadows.ShadowOverrides;
|
||||
import com.android.launcher3.util.LauncherLayoutBuilder;
|
||||
import com.android.launcher3.util.LauncherLayoutBuilder.FolderBuilder;
|
||||
import com.android.launcher3.util.LauncherModelHelper;
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
import com.android.launcher3.util.ViewOnDrawExecutor;
|
||||
import com.android.launcher3.widget.WidgetsFullSheet;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.LooperMode;
|
||||
import org.robolectric.annotation.LooperMode.Mode;
|
||||
import org.robolectric.shadows.ShadowLooper;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
/**
|
||||
* Tests scroll behavior at various Launcher UI components
|
||||
*/
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@LooperMode(Mode.PAUSED)
|
||||
public class LauncherUIScrollTest {
|
||||
|
||||
@@ -166,23 +160,7 @@ public class LauncherUIScrollTest {
|
||||
|
||||
private Launcher loadLauncher() throws Exception {
|
||||
mModelHelper.setupDefaultLayoutProvider(mLayoutBuilder).loadModelSync();
|
||||
|
||||
Launcher launcher = Robolectric.buildActivity(Launcher.class).setup().get();
|
||||
doLayout(launcher);
|
||||
ViewOnDrawExecutor executor = ReflectionHelpers.getField(launcher, "mPendingExecutor");
|
||||
if (executor != null) {
|
||||
executor.runAllTasks();
|
||||
}
|
||||
return launcher;
|
||||
}
|
||||
|
||||
private static void doLayout(Activity activity) {
|
||||
DeviceProfile dp = InvariantDeviceProfile.INSTANCE
|
||||
.get(RuntimeEnvironment.application).portraitProfile;
|
||||
View view = activity.getWindow().getDecorView();
|
||||
view.measure(makeMeasureSpec(dp.widthPx, EXACTLY), makeMeasureSpec(dp.heightPx, EXACTLY));
|
||||
view.layout(0, 0, dp.widthPx, dp.heightPx);
|
||||
ShadowLooper.idleMainLooper();
|
||||
return buildAndBindLauncher();
|
||||
}
|
||||
|
||||
private static MotionEvent createScrollEvent(int scroll) {
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
package com.android.launcher3.util;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link GridOccupancy}
|
||||
*/
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class GridOccupancyTest {
|
||||
|
||||
@Test
|
||||
|
||||
@@ -19,11 +19,12 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
/**
|
||||
* Robolectric unit tests for {@link IntArray}
|
||||
*/
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class IntArrayTest {
|
||||
|
||||
@Test
|
||||
|
||||
@@ -17,17 +17,18 @@ package com.android.launcher3.util;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
|
||||
/**
|
||||
* Robolectric unit tests for {@link IntSet}
|
||||
*/
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class IntSetTest {
|
||||
|
||||
@Test
|
||||
|
||||
@@ -36,9 +36,7 @@ import android.net.Uri;
|
||||
import android.os.Process;
|
||||
import android.provider.Settings;
|
||||
|
||||
import com.android.launcher3.AppInfo;
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.ItemInfo;
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherModel;
|
||||
import com.android.launcher3.LauncherModel.ModelUpdateTask;
|
||||
@@ -47,6 +45,8 @@ import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.model.AllAppsList;
|
||||
import com.android.launcher3.model.BgDataModel;
|
||||
import com.android.launcher3.model.BgDataModel.Callbacks;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.pm.UserCache;
|
||||
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 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 static org.mockito.Mockito.mock;
|
||||
|
||||
import com.android.launcher3.shadows.LShadowAppWidgetManager;
|
||||
import com.android.launcher3.shadows.LShadowBackupManager;
|
||||
import com.android.launcher3.shadows.LShadowBitmap;
|
||||
import com.android.launcher3.shadows.LShadowLauncherApps;
|
||||
import com.android.launcher3.shadows.LShadowTypeface;
|
||||
import com.android.launcher3.shadows.LShadowUserManager;
|
||||
import com.android.launcher3.shadows.LShadowWallpaperManager;
|
||||
import com.android.launcher3.shadows.ShadowDeviceFlag;
|
||||
import com.android.launcher3.shadows.ShadowLooperExecutor;
|
||||
import com.android.launcher3.shadows.ShadowMainThreadInitializedObject;
|
||||
import com.android.launcher3.shadows.ShadowOverrides;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
|
||||
import org.junit.runners.model.InitializationError;
|
||||
import org.robolectric.DefaultTestLifecycle;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.TestLifecycle;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowLog;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Test runner with Launcher specific configurations
|
||||
*/
|
||||
public class LauncherRoboTestRunner extends RobolectricTestRunner {
|
||||
|
||||
private static final Class<?>[] SHADOWS = new Class<?>[] {
|
||||
LShadowAppWidgetManager.class,
|
||||
LShadowUserManager.class,
|
||||
LShadowLauncherApps.class,
|
||||
LShadowBitmap.class,
|
||||
LShadowBackupManager.class,
|
||||
LShadowTypeface.class,
|
||||
LShadowWallpaperManager.class,
|
||||
ShadowLooperExecutor.class,
|
||||
ShadowMainThreadInitializedObject.class,
|
||||
ShadowDeviceFlag.class,
|
||||
ShadowOverrides.class
|
||||
};
|
||||
|
||||
public LauncherRoboTestRunner(Class<?> testClass) throws InitializationError {
|
||||
super(testClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Config buildGlobalConfig() {
|
||||
return new Config.Builder().setShadows(SHADOWS).build();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected Class<? extends TestLifecycle> getTestLifecycleClass() {
|
||||
return LauncherTestLifecycle.class;
|
||||
}
|
||||
|
||||
public static class LauncherTestLifecycle extends DefaultTestLifecycle {
|
||||
|
||||
@Override
|
||||
public void beforeTest(Method method) {
|
||||
super.beforeTest(method);
|
||||
ShadowLog.stream = System.out;
|
||||
|
||||
// Disable plugins
|
||||
PluginManagerWrapper.INSTANCE.initializeForTesting(mock(PluginManagerWrapper.class));
|
||||
|
||||
// Initialize mock wallpaper manager
|
||||
LShadowWallpaperManager.initializeMock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTest(Method method) {
|
||||
super.afterTest(method);
|
||||
|
||||
ShadowLog.stream = null;
|
||||
ShadowMainThreadInitializedObject.resetInitializedObjects();
|
||||
ShadowOverrides.clearProvider();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 static org.mockito.Mockito.mock;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import com.android.launcher3.shadows.LShadowWallpaperManager;
|
||||
import com.android.launcher3.shadows.ShadowMainThreadInitializedObject;
|
||||
import com.android.launcher3.shadows.ShadowOverrides;
|
||||
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
|
||||
|
||||
import org.robolectric.TestLifecycleApplication;
|
||||
import org.robolectric.shadows.ShadowLog;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class LauncherTestApplication extends Application implements TestLifecycleApplication {
|
||||
|
||||
@Override
|
||||
public void beforeTest(Method method) {
|
||||
ShadowLog.stream = System.out;
|
||||
|
||||
// Disable plugins
|
||||
PluginManagerWrapper.INSTANCE.initializeForTesting(mock(PluginManagerWrapper.class));
|
||||
|
||||
// Initialize mock wallpaper manager
|
||||
LShadowWallpaperManager.initializeMock();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareTest(Object test) { }
|
||||
|
||||
@Override
|
||||
public void afterTest(Method method) {
|
||||
ShadowLog.stream = null;
|
||||
ShadowMainThreadInitializedObject.resetInitializedObjects();
|
||||
ShadowOverrides.clearProvider();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 static android.view.View.MeasureSpec.EXACTLY;
|
||||
import static android.view.View.MeasureSpec.makeMeasureSpec;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.Point;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.android.controller.ActivityController;
|
||||
import org.robolectric.shadows.ShadowLooper;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Utility class to help manage Launcher UI and related objects for test.
|
||||
*/
|
||||
public class LauncherUIHelper {
|
||||
|
||||
/**
|
||||
* Returns the class name for the Launcher activity as defined in the manifest
|
||||
*/
|
||||
public static String getLauncherClassName() {
|
||||
Context context = RuntimeEnvironment.application;
|
||||
Intent homeIntent = new Intent(Intent.ACTION_MAIN)
|
||||
.addCategory(Intent.CATEGORY_HOME)
|
||||
.setPackage(context.getPackageName())
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
List<ResolveInfo> launchers = context.getPackageManager()
|
||||
.queryIntentActivities(homeIntent, 0);
|
||||
if (launchers.size() != 1) {
|
||||
return null;
|
||||
}
|
||||
return launchers.get(0).activityInfo.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an activity controller for Launcher activity defined in the manifest
|
||||
*/
|
||||
public static <T extends Launcher> ActivityController<T> buildLauncher() {
|
||||
try {
|
||||
Class<T> tClass = (Class<T>) Class.forName(getLauncherClassName());
|
||||
return Robolectric.buildActivity(tClass);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and binds a Launcher activity defined in the manifest.
|
||||
* Note that the model must be bound before calling this
|
||||
*/
|
||||
public static <T extends Launcher> T buildAndBindLauncher() {
|
||||
ActivityController<T> controller = buildLauncher();
|
||||
|
||||
T launcher = controller.setup().get();
|
||||
doLayout(launcher);
|
||||
ViewOnDrawExecutor executor = ReflectionHelpers.getField(launcher, "mPendingExecutor");
|
||||
if (executor != null) {
|
||||
executor.runAllTasks();
|
||||
}
|
||||
return launcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a measure and layout pass for the given activity
|
||||
*/
|
||||
public static void doLayout(Activity activity) {
|
||||
Point size = new Point();
|
||||
RuntimeEnvironment.application.getSystemService(WindowManager.class)
|
||||
.getDefaultDisplay().getSize(size);
|
||||
View view = activity.getWindow().getDecorView();
|
||||
view.measure(makeMeasureSpec(size.x, EXACTLY), makeMeasureSpec(size.y, EXACTLY));
|
||||
view.layout(0, 0, size.x, size.y);
|
||||
ShadowLooper.idleMainLooper();
|
||||
}
|
||||
}
|
||||
@@ -34,15 +34,15 @@ import com.android.launcher3.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.WidgetPreviewLoader;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.model.PackageItemInfo;
|
||||
import com.android.launcher3.model.WidgetItem;
|
||||
import com.android.launcher3.util.LauncherRoboTestRunner;
|
||||
import com.android.launcher3.model.data.PackageItemInfo;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.shadows.ShadowPackageManager;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
@@ -50,7 +50,7 @@ import org.robolectric.util.ReflectionHelpers;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
@RunWith(LauncherRoboTestRunner.class)
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class WidgetsListAdapterTest {
|
||||
|
||||
@Mock private LayoutInflater mMockLayoutInflater;
|
||||
|
||||
@@ -350,7 +350,7 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
|
||||
mWidgetView.requestLayout();
|
||||
}
|
||||
|
||||
static void updateWidgetSizeRanges(AppWidgetHostView widgetView, Launcher launcher,
|
||||
public static void updateWidgetSizeRanges(AppWidgetHostView widgetView, Launcher launcher,
|
||||
int spanX, int spanY) {
|
||||
getWidgetSizeRanges(launcher, spanX, spanY, sTmpRect);
|
||||
widgetView.updateAppWidgetSize(null, sTmpRect.left, sTmpRect.top,
|
||||
|
||||
@@ -17,6 +17,7 @@ import androidx.annotation.WorkerThread;
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.model.LoaderTask;
|
||||
import com.android.launcher3.model.WidgetsModel;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.pm.UserCache;
|
||||
import com.android.launcher3.provider.RestoreDbTask;
|
||||
import com.android.launcher3.util.ContentWriter;
|
||||
|
||||
@@ -44,6 +44,8 @@ import com.android.launcher3.LauncherProvider.SqlArguments;
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.icons.GraphicsUtils;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.qsb.QsbContainerView;
|
||||
import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
|
||||
@@ -39,6 +39,8 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.model.AppLaunchTracker;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.testing.TestLogging;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.touch.ItemClickHandler;
|
||||
|
||||
@@ -53,7 +53,12 @@ import com.android.launcher3.graphics.PreloadIconDrawable;
|
||||
import com.android.launcher3.icons.DotRenderer;
|
||||
import com.android.launcher3.icons.IconCache.IconLoadRequest;
|
||||
import com.android.launcher3.icons.IconCache.ItemInfoUpdateReceiver;
|
||||
import com.android.launcher3.model.PackageItemInfo;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.model.data.PackageItemInfo;
|
||||
import com.android.launcher3.model.data.PromiseAppInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.IconLabelDotView;
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ 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.model.data.ItemInfo;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
|
||||
@@ -59,6 +59,7 @@ import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.dragndrop.DraggableView;
|
||||
import com.android.launcher3.folder.PreviewBackground;
|
||||
import com.android.launcher3.graphics.DragPreviewProvider;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.util.CellAndSpan;
|
||||
import com.android.launcher3.util.GridOccupancy;
|
||||
import com.android.launcher3.util.ParcelableSparseArray;
|
||||
@@ -959,8 +960,13 @@ public class CellLayout extends ViewGroup {
|
||||
height = r.height();
|
||||
}
|
||||
|
||||
if (v != null && v.getViewType() == DraggableView.DRAGGABLE_ICON) {
|
||||
left += ((mCellWidth * spanX) - dragOutline.getWidth()) / 2;
|
||||
// Center horizontaly
|
||||
left += ((mCellWidth * spanX) - dragOutline.getWidth()) / 2;
|
||||
|
||||
if (v != null && v.getViewType() == DraggableView.DRAGGABLE_WIDGET) {
|
||||
// Center vertically
|
||||
top += ((mCellHeight * spanY) - dragOutline.getHeight()) / 2;
|
||||
} else if (v != null && v.getViewType() == DraggableView.DRAGGABLE_ICON) {
|
||||
int cHeight = getShortcutsAndWidgets().getCellContentHeight();
|
||||
int cellPaddingY = (int) Math.max(0, ((mCellHeight - cHeight) / 2f));
|
||||
top += cellPaddingY;
|
||||
|
||||
@@ -28,6 +28,10 @@ import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
||||
import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.logging.LoggerUtils;
|
||||
import com.android.launcher3.model.ModelWriter;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
import com.android.launcher3.views.Snackbar;
|
||||
|
||||
@@ -25,8 +25,6 @@ import android.graphics.Rect;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.Surface;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.CellLayout.ContainerType;
|
||||
import com.android.launcher3.graphics.IconShape;
|
||||
import com.android.launcher3.icons.DotRenderer;
|
||||
@@ -36,8 +34,6 @@ import com.android.launcher3.util.DefaultDisplay;
|
||||
public class DeviceProfile {
|
||||
|
||||
public final InvariantDeviceProfile inv;
|
||||
// IDP with no grid override values.
|
||||
@Nullable private final InvariantDeviceProfile originalIdp;
|
||||
|
||||
// Device properties
|
||||
public final boolean isTablet;
|
||||
@@ -138,11 +134,10 @@ public class DeviceProfile {
|
||||
public DotRenderer mDotRendererAllApps;
|
||||
|
||||
public DeviceProfile(Context context, InvariantDeviceProfile inv,
|
||||
InvariantDeviceProfile originalIDP, Point minSize, Point maxSize,
|
||||
Point minSize, Point maxSize,
|
||||
int width, int height, boolean isLandscape, boolean isMultiWindowMode) {
|
||||
|
||||
this.inv = inv;
|
||||
this.originalIdp = inv;
|
||||
this.isLandscape = isLandscape;
|
||||
this.isMultiWindowMode = isMultiWindowMode;
|
||||
|
||||
@@ -234,19 +229,6 @@ public class DeviceProfile {
|
||||
// Recalculate the available dimensions using the new hotseat size.
|
||||
updateAvailableDimensions(dm, res);
|
||||
}
|
||||
|
||||
if (originalIDP != null) {
|
||||
// Grid size change should not affect All Apps UI, so we use the original profile
|
||||
// measurements here.
|
||||
DeviceProfile originalProfile = isLandscape
|
||||
? originalIDP.landscapeProfile
|
||||
: originalIDP.portraitProfile;
|
||||
allAppsIconSizePx = originalProfile.iconSizePx;
|
||||
allAppsIconTextSizePx = originalProfile.iconTextSizePx;
|
||||
allAppsCellHeightPx = originalProfile.allAppsCellHeightPx;
|
||||
allAppsIconDrawablePaddingPx = originalProfile.iconDrawablePaddingOriginalPx;
|
||||
allAppsCellWidthPx = allAppsIconSizePx + 2 * allAppsIconDrawablePaddingPx;
|
||||
}
|
||||
updateWorkspacePadding();
|
||||
|
||||
// This is done last, after iconSizePx is calculated above.
|
||||
@@ -259,8 +241,8 @@ public class DeviceProfile {
|
||||
|
||||
public DeviceProfile copy(Context context) {
|
||||
Point size = new Point(availableWidthPx, availableHeightPx);
|
||||
return new DeviceProfile(context, inv, originalIdp, size, size, widthPx, heightPx,
|
||||
isLandscape, isMultiWindowMode);
|
||||
return new DeviceProfile(context, inv, size, size, widthPx, heightPx, isLandscape,
|
||||
isMultiWindowMode);
|
||||
}
|
||||
|
||||
public DeviceProfile getMultiWindowProfile(Context context, Point mwSize) {
|
||||
@@ -271,8 +253,8 @@ public class DeviceProfile {
|
||||
// In multi-window mode, we can have widthPx = availableWidthPx
|
||||
// and heightPx = availableHeightPx because Launcher uses the InvariantDeviceProfiles'
|
||||
// widthPx and heightPx values where it's needed.
|
||||
DeviceProfile profile = new DeviceProfile(context, inv, null, mwSize, mwSize,
|
||||
mwSize.x, mwSize.y, isLandscape, true);
|
||||
DeviceProfile profile = new DeviceProfile(context, inv, mwSize, mwSize, mwSize.x, mwSize.y,
|
||||
isLandscape, true);
|
||||
|
||||
// If there isn't enough vertical cell padding with the labels displayed, hide the labels.
|
||||
float workspaceCellPaddingY = profile.getCellSize().y - profile.iconSizePx
|
||||
@@ -356,11 +338,19 @@ public class DeviceProfile {
|
||||
}
|
||||
cellWidthPx = iconSizePx + iconDrawablePaddingPx;
|
||||
|
||||
allAppsIconSizePx = iconSizePx;
|
||||
allAppsIconTextSizePx = iconTextSizePx;
|
||||
allAppsIconDrawablePaddingPx = iconDrawablePaddingPx;
|
||||
allAppsCellHeightPx = getCellSize().y;
|
||||
allAppsCellWidthPx = allAppsIconSizePx + 2 * allAppsIconDrawablePaddingPx;
|
||||
// All apps
|
||||
if (allAppsHasDifferentNumColumns()) {
|
||||
allAppsIconSizePx = ResourceUtils.pxFromDp(inv.allAppsIconSize, dm);
|
||||
allAppsIconTextSizePx = Utilities.pxFromSp(inv.allAppsIconTextSize, dm);
|
||||
allAppsCellHeightPx = getCellSize(inv.numAllAppsColumns, inv.numAllAppsColumns).y;
|
||||
allAppsIconDrawablePaddingPx = iconDrawablePaddingOriginalPx;
|
||||
} else {
|
||||
allAppsIconSizePx = iconSizePx;
|
||||
allAppsIconTextSizePx = iconTextSizePx;
|
||||
allAppsIconDrawablePaddingPx = iconDrawablePaddingPx;
|
||||
allAppsCellHeightPx = getCellSize().y;
|
||||
}
|
||||
allAppsCellWidthPx = allAppsIconSizePx + allAppsIconDrawablePaddingPx;
|
||||
|
||||
if (isVerticalBarLayout()) {
|
||||
// Always hide the Workspace text with vertical bar layout.
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.dragndrop.DragView;
|
||||
import com.android.launcher3.dragndrop.DraggableView;
|
||||
import com.android.launcher3.folder.FolderNameProvider;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
|
||||
/**
|
||||
* Interface defining an object that can receive a drag.
|
||||
|
||||
@@ -35,6 +35,7 @@ import android.util.Property;
|
||||
|
||||
import com.android.launcher3.graphics.PlaceHolderIconDrawable;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
|
||||
|
||||
public class FastBitmapDrawable extends Drawable {
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.view.ViewGroup;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.folder.FolderPagedView;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.util.FocusLogic;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.launcher3.logging.StatsLogUtils.LogContainerProvider;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||
|
||||
|
||||
@@ -46,6 +46,10 @@ import androidx.annotation.WorkerThread;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.icons.GraphicsUtils;
|
||||
import com.android.launcher3.icons.LauncherIcons;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.pm.UserCache;
|
||||
import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import com.android.launcher3.shortcuts.ShortcutRequest;
|
||||
|
||||
@@ -47,7 +47,6 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.launcher3.graphics.IconShape;
|
||||
import com.android.launcher3.graphics.LauncherPreviewRenderer;
|
||||
import com.android.launcher3.util.ConfigMonitor;
|
||||
import com.android.launcher3.util.DefaultDisplay;
|
||||
import com.android.launcher3.util.DefaultDisplay.Info;
|
||||
@@ -61,7 +60,6 @@ import org.xmlpull.v1.XmlPullParserException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class InvariantDeviceProfile {
|
||||
|
||||
@@ -107,6 +105,8 @@ public class InvariantDeviceProfile {
|
||||
public int iconBitmapSize;
|
||||
public int fillResIconDpi;
|
||||
public float iconTextSize;
|
||||
public float allAppsIconSize;
|
||||
public float allAppsIconTextSize;
|
||||
|
||||
private SparseArray<TypedValue> mExtraAttrs;
|
||||
|
||||
@@ -149,6 +149,8 @@ public class InvariantDeviceProfile {
|
||||
numHotseatIcons = p.numHotseatIcons;
|
||||
numAllAppsColumns = p.numAllAppsColumns;
|
||||
dbFile = p.dbFile;
|
||||
allAppsIconSize = p.allAppsIconSize;
|
||||
allAppsIconTextSize = p.allAppsIconTextSize;
|
||||
defaultLayoutId = p.defaultLayoutId;
|
||||
demoModeLayoutId = p.demoModeLayoutId;
|
||||
mExtraAttrs = p.mExtraAttrs;
|
||||
@@ -157,12 +159,9 @@ public class InvariantDeviceProfile {
|
||||
|
||||
@TargetApi(23)
|
||||
private InvariantDeviceProfile(Context context) {
|
||||
if (context instanceof LauncherPreviewRenderer.PreviewContext) {
|
||||
throw new IllegalArgumentException(
|
||||
"PreviewContext is passed into this IDP constructor");
|
||||
}
|
||||
|
||||
String gridName = getCurrentGridName(context);
|
||||
String gridName = Utilities.getPrefs(context).getBoolean(GRID_OPTIONS_PREFERENCE_KEY, false)
|
||||
? Utilities.getPrefs(context).getString(KEY_IDP_GRID_NAME, null)
|
||||
: null;
|
||||
initGrid(context, gridName);
|
||||
mConfigMonitor = new ConfigMonitor(context,
|
||||
APPLY_CONFIG_AT_RUNTIME.get() ? this::onConfigChanged : this::killProcess);
|
||||
@@ -179,7 +178,7 @@ public class InvariantDeviceProfile {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* This constructor should NOT have any monitors by design.
|
||||
*/
|
||||
public InvariantDeviceProfile(Context context, Display display) {
|
||||
@@ -211,11 +210,55 @@ public class InvariantDeviceProfile {
|
||||
Point smallestSize = new Point(displayInfo.smallestSize);
|
||||
Point largestSize = new Point(displayInfo.largestSize);
|
||||
|
||||
ArrayList<DisplayOption> allOptions = getPredefinedDeviceProfiles(context, gridName);
|
||||
// This guarantees that width < height
|
||||
float minWidthDps = Utilities.dpiFromPx(Math.min(smallestSize.x, smallestSize.y),
|
||||
displayInfo.metrics);
|
||||
float minHeightDps = Utilities.dpiFromPx(Math.min(largestSize.x, largestSize.y),
|
||||
displayInfo.metrics);
|
||||
// Sort the profiles based on the closeness to the device size
|
||||
Collections.sort(allOptions, (a, b) ->
|
||||
Float.compare(dist(minWidthDps, minHeightDps, a.minWidthDps, a.minHeightDps),
|
||||
dist(minWidthDps, minHeightDps, b.minWidthDps, b.minHeightDps)));
|
||||
DisplayOption interpolatedDisplayOption =
|
||||
invDistWeightedInterpolate(minWidthDps, minHeightDps, allOptions);
|
||||
|
||||
GridOption closestProfile = allOptions.get(0).grid;
|
||||
numRows = closestProfile.numRows;
|
||||
numColumns = closestProfile.numColumns;
|
||||
numHotseatIcons = closestProfile.numHotseatIcons;
|
||||
dbFile = closestProfile.dbFile;
|
||||
defaultLayoutId = closestProfile.defaultLayoutId;
|
||||
demoModeLayoutId = closestProfile.demoModeLayoutId;
|
||||
numFolderRows = closestProfile.numFolderRows;
|
||||
numFolderColumns = closestProfile.numFolderColumns;
|
||||
numAllAppsColumns = closestProfile.numAllAppsColumns;
|
||||
|
||||
mExtraAttrs = closestProfile.extraAttrs;
|
||||
|
||||
if (!closestProfile.name.equals(gridName)) {
|
||||
Utilities.getPrefs(context).edit()
|
||||
.putString(KEY_IDP_GRID_NAME, closestProfile.name).apply();
|
||||
}
|
||||
|
||||
iconSize = interpolatedDisplayOption.iconSize;
|
||||
iconShapePath = getIconShapePath(context);
|
||||
landscapeIconSize = interpolatedDisplayOption.landscapeIconSize;
|
||||
iconBitmapSize = ResourceUtils.pxFromDp(iconSize, displayInfo.metrics);
|
||||
iconTextSize = interpolatedDisplayOption.iconTextSize;
|
||||
fillResIconDpi = getLauncherIconDensity(iconBitmapSize);
|
||||
|
||||
if (Utilities.getPrefs(context).getBoolean(GRID_OPTIONS_PREFERENCE_KEY, false)) {
|
||||
allAppsIconSize = interpolatedDisplayOption.allAppsIconSize;
|
||||
allAppsIconTextSize = interpolatedDisplayOption.allAppsIconTextSize;
|
||||
} else {
|
||||
allAppsIconSize = iconSize;
|
||||
allAppsIconTextSize = iconTextSize;
|
||||
}
|
||||
|
||||
// If the partner customization apk contains any grid overrides, apply them
|
||||
// Supported overrides: numRows, numColumns, iconSize
|
||||
applyPartnerDeviceProfileOverrides(context, displayInfo.metrics);
|
||||
|
||||
Point realSize = new Point(displayInfo.realSize);
|
||||
// The real size never changes. smallSide and largeSide will remain the
|
||||
@@ -223,64 +266,10 @@ public class InvariantDeviceProfile {
|
||||
int smallSide = Math.min(realSize.x, realSize.y);
|
||||
int largeSide = Math.max(realSize.x, realSize.y);
|
||||
|
||||
// We want a list of all options as well as the list of filtered options. This allows us
|
||||
// to have a consistent UI for areas that the grid size change should not affect
|
||||
// ie. All Apps should be consistent between grid sizes.
|
||||
ArrayList<DisplayOption> allOptions = new ArrayList<>();
|
||||
ArrayList<DisplayOption> filteredOptions = new ArrayList<>();
|
||||
getPredefinedDeviceProfiles(context, gridName, filteredOptions, allOptions);
|
||||
|
||||
if (allOptions.isEmpty() && filteredOptions.isEmpty()) {
|
||||
throw new RuntimeException("No display option with canBeDefault=true");
|
||||
}
|
||||
|
||||
// Sort the profiles based on the closeness to the device size
|
||||
Comparator<DisplayOption> comparator = (a, b) -> Float.compare(dist(minWidthDps,
|
||||
minHeightDps, a.minWidthDps, a.minHeightDps),
|
||||
dist(minWidthDps, minHeightDps, b.minWidthDps, b.minHeightDps));
|
||||
|
||||
// Calculate the device profiles as if there is no grid override.
|
||||
Collections.sort(allOptions, comparator);
|
||||
DisplayOption interpolatedDisplayOption =
|
||||
invDistWeightedInterpolate(minWidthDps, minHeightDps, allOptions);
|
||||
initGridOption(context, allOptions, interpolatedDisplayOption, displayInfo.metrics);
|
||||
|
||||
// Create IDP with no grid override values.
|
||||
InvariantDeviceProfile originalIDP = new InvariantDeviceProfile(this);
|
||||
originalIDP.landscapeProfile = new DeviceProfile(context, this, null, smallestSize,
|
||||
largestSize, largeSide, smallSide, true /* isLandscape */,
|
||||
false /* isMultiWindowMode */);
|
||||
originalIDP.portraitProfile = new DeviceProfile(context, this, null, smallestSize,
|
||||
largestSize, smallSide, largeSide, false /* isLandscape */,
|
||||
false /* isMultiWindowMode */);
|
||||
|
||||
if (filteredOptions.isEmpty()) {
|
||||
filteredOptions = allOptions;
|
||||
|
||||
landscapeProfile = originalIDP.landscapeProfile;
|
||||
portraitProfile = originalIDP.portraitProfile;
|
||||
} else {
|
||||
Collections.sort(filteredOptions, comparator);
|
||||
interpolatedDisplayOption =
|
||||
invDistWeightedInterpolate(minWidthDps, minHeightDps, filteredOptions);
|
||||
|
||||
initGridOption(context, filteredOptions, interpolatedDisplayOption,
|
||||
displayInfo.metrics);
|
||||
numAllAppsColumns = originalIDP.numAllAppsColumns;
|
||||
|
||||
landscapeProfile = new DeviceProfile(context, this, originalIDP, smallestSize,
|
||||
largestSize, largeSide, smallSide, true /* isLandscape */,
|
||||
false /* isMultiWindowMode */);
|
||||
portraitProfile = new DeviceProfile(context, this, originalIDP, smallestSize,
|
||||
largestSize, smallSide, largeSide, false /* isLandscape */,
|
||||
false /* isMultiWindowMode */);
|
||||
}
|
||||
|
||||
GridOption closestProfile = filteredOptions.get(0).grid;
|
||||
if (!closestProfile.name.equals(gridName)) {
|
||||
Utilities.getPrefs(context).edit()
|
||||
.putString(KEY_IDP_GRID_NAME, closestProfile.name).apply();
|
||||
}
|
||||
landscapeProfile = new DeviceProfile(context, this, smallestSize, largestSize,
|
||||
largeSide, smallSide, true /* isLandscape */, false /* isMultiWindowMode */);
|
||||
portraitProfile = new DeviceProfile(context, this, smallestSize, largestSize,
|
||||
smallSide, largeSide, false /* isLandscape */, false /* isMultiWindowMode */);
|
||||
|
||||
// We need to ensure that there is enough extra space in the wallpaper
|
||||
// for the intended parallax effects
|
||||
@@ -298,34 +287,6 @@ public class InvariantDeviceProfile {
|
||||
return closestProfile.name;
|
||||
}
|
||||
|
||||
private void initGridOption(Context context, ArrayList<DisplayOption> options,
|
||||
DisplayOption displayOption, DisplayMetrics metrics) {
|
||||
GridOption closestProfile = options.get(0).grid;
|
||||
numRows = closestProfile.numRows;
|
||||
numColumns = closestProfile.numColumns;
|
||||
numHotseatIcons = closestProfile.numHotseatIcons;
|
||||
dbFile = closestProfile.dbFile;
|
||||
defaultLayoutId = closestProfile.defaultLayoutId;
|
||||
demoModeLayoutId = closestProfile.demoModeLayoutId;
|
||||
numFolderRows = closestProfile.numFolderRows;
|
||||
numFolderColumns = closestProfile.numFolderColumns;
|
||||
numAllAppsColumns = numColumns;
|
||||
|
||||
mExtraAttrs = closestProfile.extraAttrs;
|
||||
|
||||
iconSize = displayOption.iconSize;
|
||||
iconShapePath = getIconShapePath(context);
|
||||
landscapeIconSize = displayOption.landscapeIconSize;
|
||||
iconBitmapSize = ResourceUtils.pxFromDp(iconSize, metrics);
|
||||
iconTextSize = displayOption.iconTextSize;
|
||||
fillResIconDpi = getLauncherIconDensity(iconBitmapSize);
|
||||
|
||||
// If the partner customization apk contains any grid overrides, apply them
|
||||
// Supported overrides: numRows, numColumns, iconSize
|
||||
applyPartnerDeviceProfileOverrides(context, metrics);
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public TypedValue getAttrValue(int attr) {
|
||||
return mExtraAttrs == null ? null : mExtraAttrs.get(attr);
|
||||
@@ -403,13 +364,7 @@ public class InvariantDeviceProfile {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param gridName The current grid name.
|
||||
* @param filteredOptionsOut List filled with all the filtered options based on gridName.
|
||||
* @param allOptionsOut List filled with all the options that can be the default option.
|
||||
*/
|
||||
static void getPredefinedDeviceProfiles(Context context, String gridName,
|
||||
ArrayList<DisplayOption> filteredOptionsOut, ArrayList<DisplayOption> allOptionsOut) {
|
||||
static ArrayList<DisplayOption> getPredefinedDeviceProfiles(Context context, String gridName) {
|
||||
ArrayList<DisplayOption> profiles = new ArrayList<>();
|
||||
try (XmlResourceParser parser = context.getResources().getXml(R.xml.device_profiles)) {
|
||||
final int depth = parser.getDepth();
|
||||
@@ -436,19 +391,26 @@ public class InvariantDeviceProfile {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
ArrayList<DisplayOption> filteredProfiles = new ArrayList<>();
|
||||
if (!TextUtils.isEmpty(gridName)) {
|
||||
for (DisplayOption option : profiles) {
|
||||
if (gridName.equals(option.grid.name)) {
|
||||
filteredOptionsOut.add(option);
|
||||
filteredProfiles.add(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (DisplayOption option : profiles) {
|
||||
if (option.canBeDefault) {
|
||||
allOptionsOut.add(option);
|
||||
if (filteredProfiles.isEmpty()) {
|
||||
// No grid found, use the default options
|
||||
for (DisplayOption option : profiles) {
|
||||
if (option.canBeDefault) {
|
||||
filteredProfiles.add(option);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filteredProfiles.isEmpty()) {
|
||||
throw new RuntimeException("No display option with canBeDefault=true");
|
||||
}
|
||||
return filteredProfiles;
|
||||
}
|
||||
|
||||
private int getLauncherIconDensity(int requiredSize) {
|
||||
@@ -493,7 +455,7 @@ public class InvariantDeviceProfile {
|
||||
|
||||
@VisibleForTesting
|
||||
static DisplayOption invDistWeightedInterpolate(float width, float height,
|
||||
ArrayList<DisplayOption> points) {
|
||||
ArrayList<DisplayOption> points) {
|
||||
float weights = 0;
|
||||
|
||||
DisplayOption p = points.get(0);
|
||||
@@ -573,6 +535,8 @@ public class InvariantDeviceProfile {
|
||||
private final int numHotseatIcons;
|
||||
|
||||
private final String dbFile;
|
||||
private final int numAllAppsColumns;
|
||||
|
||||
private final int defaultLayoutId;
|
||||
private final int demoModeLayoutId;
|
||||
|
||||
@@ -596,6 +560,8 @@ public class InvariantDeviceProfile {
|
||||
R.styleable.GridDisplayOption_numFolderRows, numRows);
|
||||
numFolderColumns = a.getInt(
|
||||
R.styleable.GridDisplayOption_numFolderColumns, numColumns);
|
||||
numAllAppsColumns = a.getInt(
|
||||
R.styleable.GridDisplayOption_numAllAppsColumns, numColumns);
|
||||
|
||||
a.recycle();
|
||||
|
||||
@@ -615,6 +581,8 @@ public class InvariantDeviceProfile {
|
||||
private float iconSize;
|
||||
private float iconTextSize;
|
||||
private float landscapeIconSize;
|
||||
private float allAppsIconSize;
|
||||
private float allAppsIconTextSize;
|
||||
|
||||
DisplayOption(GridOption grid, Context context, AttributeSet attrs) {
|
||||
this.grid = grid;
|
||||
@@ -633,6 +601,10 @@ public class InvariantDeviceProfile {
|
||||
iconSize);
|
||||
iconTextSize = a.getFloat(R.styleable.ProfileDisplayOption_iconTextSize, 0);
|
||||
|
||||
allAppsIconSize = a.getFloat(R.styleable.ProfileDisplayOption_allAppsIconSize,
|
||||
iconSize);
|
||||
allAppsIconTextSize = a.getFloat(R.styleable.ProfileDisplayOption_allAppsIconTextSize,
|
||||
iconTextSize);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
@@ -647,14 +619,18 @@ public class InvariantDeviceProfile {
|
||||
private DisplayOption multiply(float w) {
|
||||
iconSize *= w;
|
||||
landscapeIconSize *= w;
|
||||
allAppsIconSize *= w;
|
||||
iconTextSize *= w;
|
||||
allAppsIconTextSize *= w;
|
||||
return this;
|
||||
}
|
||||
|
||||
private DisplayOption add(DisplayOption p) {
|
||||
iconSize += p.iconSize;
|
||||
landscapeIconSize += p.landscapeIconSize;
|
||||
allAppsIconSize += p.allAppsIconSize;
|
||||
iconTextSize += p.iconTextSize;
|
||||
allAppsIconTextSize += p.allAppsIconTextSize;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -672,4 +648,4 @@ public class InvariantDeviceProfile {
|
||||
onConfigChanged(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,6 +110,12 @@ import com.android.launcher3.logging.UserEventDispatcher;
|
||||
import com.android.launcher3.model.AppLaunchTracker;
|
||||
import com.android.launcher3.model.BgDataModel.Callbacks;
|
||||
import com.android.launcher3.model.ModelWriter;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.model.data.PromiseAppInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.notification.NotificationListener;
|
||||
import com.android.launcher3.pm.PinRequestHelper;
|
||||
import com.android.launcher3.pm.UserCache;
|
||||
@@ -133,6 +139,7 @@ import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
import com.android.launcher3.util.MultiValueAlpha;
|
||||
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
|
||||
import com.android.launcher3.util.OnboardingPrefs;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
import com.android.launcher3.util.PackageUserKey;
|
||||
import com.android.launcher3.util.PendingRequestArgs;
|
||||
@@ -294,6 +301,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
// We only want to get the SharedPreferences once since it does an FS stat each time we get
|
||||
// it from the context.
|
||||
private SharedPreferences mSharedPrefs;
|
||||
private OnboardingPrefs mOnboardingPrefs;
|
||||
|
||||
// Activity result which needs to be processed after workspace has loaded.
|
||||
private ActivityResultInfo mPendingActivityResult;
|
||||
@@ -361,6 +369,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
mAllAppsController = new AllAppsTransitionController(this);
|
||||
mStateManager = new LauncherStateManager(this);
|
||||
|
||||
mOnboardingPrefs = createOnboardingPrefs(mSharedPrefs, mStateManager);
|
||||
|
||||
mAppWidgetManager = new WidgetManagerHelper(this);
|
||||
mAppWidgetHost = new LauncherAppWidgetHost(this,
|
||||
appWidgetId -> getWorkspace().removeWidget(appWidgetId));
|
||||
@@ -452,6 +462,15 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
return new LauncherOverlayManager() { };
|
||||
}
|
||||
|
||||
protected OnboardingPrefs createOnboardingPrefs(SharedPreferences sharedPrefs,
|
||||
LauncherStateManager stateManager) {
|
||||
return new OnboardingPrefs<>(this, sharedPrefs, stateManager);
|
||||
}
|
||||
|
||||
public OnboardingPrefs getOnboardingPrefs() {
|
||||
return mOnboardingPrefs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPluginConnected(OverlayPlugin overlayManager, Context context) {
|
||||
switchOverlay(() -> overlayManager.createOverlayManager(this, this));
|
||||
@@ -1443,6 +1462,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
mLauncherCallbacks.onHomeIntent(internalStateHandled);
|
||||
}
|
||||
mOverlayManager.hideOverlay(isStarted() && !isForceInvisible());
|
||||
} else if (Intent.ACTION_ALL_APPS.equals(intent.getAction())) {
|
||||
getStateManager().goToState(ALL_APPS, alreadyOnHome);
|
||||
}
|
||||
|
||||
TraceHelper.INSTANCE.endSection(traceToken);
|
||||
@@ -2557,9 +2578,10 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
||||
writer.println(prefix + "\tmRotationHelper: " + mRotationHelper);
|
||||
writer.println(prefix + "\tmAppWidgetHost.isListening: " + mAppWidgetHost.isListening());
|
||||
|
||||
// Extra logging for b/116853349
|
||||
// Extra logging for general debugging
|
||||
mDragLayer.dump(prefix, writer);
|
||||
mStateManager.dump(prefix, writer);
|
||||
mPopupDataProvider.dump(prefix, writer);
|
||||
|
||||
try {
|
||||
FileLog.flushAll(writer);
|
||||
|
||||
@@ -13,6 +13,7 @@ import android.os.UserHandle;
|
||||
|
||||
import com.android.launcher3.icons.ComponentWithLabelAndIcon;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
|
||||
/**
|
||||
* This class is a thin wrapper around the framework AppWidgetProviderInfo class. This class affords
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user