Merge "Exit hover after taskbar unstash to clean up events between tests." into udc-dev
diff --git a/quickstep/res/layout/transient_taskbar.xml b/quickstep/res/layout/transient_taskbar.xml
index 62c6933..bf4b811 100644
--- a/quickstep/res/layout/transient_taskbar.xml
+++ b/quickstep/res/layout/transient_taskbar.xml
@@ -38,6 +38,20 @@
android:layout_width="match_parent"
android:layout_height="match_parent"/>
+ <com.android.launcher3.taskbar.bubbles.BubbleBarView
+ android:id="@+id/taskbar_bubbles"
+ android:layout_width="wrap_content"
+ android:layout_height="@dimen/bubblebar_size"
+ android:layout_gravity="bottom|end"
+ android:layout_marginEnd="@dimen/transient_taskbar_bottom_margin"
+ android:layout_marginBottom="@dimen/transient_taskbar_bottom_margin"
+ android:paddingEnd="@dimen/taskbar_icon_spacing"
+ android:paddingStart="@dimen/taskbar_icon_spacing"
+ android:visibility="gone"
+ android:gravity="center"
+ android:clipChildren="false"
+ />
+
<FrameLayout
android:id="@+id/navbuttons_view"
android:layout_width="match_parent"
@@ -74,10 +88,20 @@
<com.android.launcher3.taskbar.StashedHandleView
android:id="@+id/stashed_handle"
tools:comment1="The actual size and shape will be set as a ViewOutlineProvider at runtime"
- android:layout_width="match_parent"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/taskbar_stashed_handle_dark_color"
android:clipToOutline="true"
android:layout_gravity="bottom"/>
+ <com.android.launcher3.taskbar.StashedHandleView
+ android:id="@+id/stashed_bubble_handle"
+ tools:comment1="The actual size and shape will be set as a ViewOutlineProvider at runtime"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:background="@color/taskbar_stashed_handle_dark_color"
+ android:clipToOutline="true"
+ android:layout_gravity="bottom"/>
+
</com.android.launcher3.taskbar.TaskbarDragLayer>
\ No newline at end of file
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 45163cb..682fccd 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -1086,7 +1086,7 @@
* Adds remote animations to a {@link RemoteAnimationDefinition}. May be overridden to add
* additional animations.
*/
- protected void addRemoteAnimations(RemoteAnimationDefinition definition) {
+ private void addRemoteAnimations(RemoteAnimationDefinition definition) {
mWallpaperOpenRunner = createWallpaperOpenRunner(false /* fromUnlock */);
definition.addRemoteAnimation(WindowManager.TRANSIT_OLD_WALLPAPER_OPEN,
WindowConfiguration.ACTIVITY_TYPE_STANDARD,
@@ -1151,7 +1151,7 @@
SystemUiProxy.INSTANCE.get(mLauncher).setStartingWindowListener(null);
}
- protected void unregisterRemoteAnimations() {
+ private void unregisterRemoteAnimations() {
if (SEPARATE_RECENTS_ACTIVITY.get()) {
return;
}
@@ -1165,7 +1165,7 @@
}
}
- private void unregisterRemoteTransitions() {
+ protected void unregisterRemoteTransitions() {
if (ENABLE_SHELL_TRANSITIONS) {
SystemUiProxy.INSTANCE.get(mLauncher).unshareTransactionQueue();
}
@@ -1448,7 +1448,6 @@
*/
private Animator getFallbackClosingWindowAnimators(RemoteAnimationTarget[] appTargets) {
final int rotationChange = getRotationChange(appTargets);
- SurfaceTransactionApplier surfaceApplier = new SurfaceTransactionApplier(mDragLayer);
Matrix matrix = new Matrix();
Point tmpPos = new Point();
Rect tmpRect = new Rect();
@@ -1504,7 +1503,7 @@
.setAlpha(1f);
}
}
- surfaceApplier.scheduleApply(transaction);
+ transaction.getTransaction().apply();
}
});
@@ -1592,7 +1591,8 @@
boolean playFallBackAnimation = (launcherView == null
&& launcherIsForceInvisibleOrOpening)
|| mLauncher.getWorkspace().isOverlayShown()
- || hasMultipleTargetsWithMode(appTargets, MODE_CLOSING);
+ || hasMultipleTargetsWithMode(appTargets, MODE_CLOSING)
+ || mLauncher.isDestroyed();
boolean playWorkspaceReveal = true;
boolean skipAllAppsScale = false;
diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
index 268024f..885afff 100644
--- a/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
@@ -47,9 +47,7 @@
mStartContextualContainer = mNavButtonsView.findViewById(R.id.start_contextual_buttons);
mAllAppsButton = LayoutInflater.from(context)
.inflate(R.layout.taskbar_all_apps_button, mStartContextualContainer, false);
- mAllAppsButton.setOnClickListener((View v) -> {
- mControllers.taskbarAllAppsController.show();
- });
+ mAllAppsButton.setOnClickListener(v -> mControllers.taskbarAllAppsController.toggle());
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 37f6284..d94d8f7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -24,6 +24,7 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_ALL;
import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
+import static com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_OVERLAY_PROXY;
import static com.android.launcher3.Utilities.isRunningInTestHarness;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN;
import static com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_DRAGGING;
@@ -83,6 +84,12 @@
import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.AutohideSuspendFlag;
import com.android.launcher3.taskbar.TaskbarTranslationController.TransitionCallback;
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController;
+import com.android.launcher3.taskbar.bubbles.BubbleBarController;
+import com.android.launcher3.taskbar.bubbles.BubbleBarView;
+import com.android.launcher3.taskbar.bubbles.BubbleBarViewController;
+import com.android.launcher3.taskbar.bubbles.BubbleControllers;
+import com.android.launcher3.taskbar.bubbles.BubbleStashController;
+import com.android.launcher3.taskbar.bubbles.BubbleStashedHandleViewController;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
@@ -106,6 +113,7 @@
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
import java.io.PrintWriter;
+import java.util.Optional;
/**
* The {@link ActivityContext} with which we inflate Taskbar-related Views. This allows UI elements
@@ -195,11 +203,23 @@
TaskbarScrimView taskbarScrimView = mDragLayer.findViewById(R.id.taskbar_scrim);
FrameLayout navButtonsView = mDragLayer.findViewById(R.id.navbuttons_view);
StashedHandleView stashedHandleView = mDragLayer.findViewById(R.id.stashed_handle);
+ BubbleBarView bubbleBarView = mDragLayer.findViewById(R.id.taskbar_bubbles);
+ StashedHandleView bubbleHandleView = mDragLayer.findViewById(R.id.stashed_bubble_handle);
mAccessibilityDelegate = new TaskbarShortcutMenuAccessibilityDelegate(this);
final boolean isDesktopMode = getPackageManager().hasSystemFeature(FEATURE_PC);
+ // If Bubble bar is present, TaskbarControllers depends on it so build it first.
+ Optional<BubbleControllers> bubbleControllersOptional = Optional.empty();
+ if (BubbleBarController.BUBBLE_BAR_ENABLED) {
+ bubbleControllersOptional = Optional.of(new BubbleControllers(
+ new BubbleBarController(this, bubbleBarView),
+ new BubbleBarViewController(this, bubbleBarView),
+ new BubbleStashController(this),
+ new BubbleStashedHandleViewController(this, bubbleHandleView)));
+ }
+
// Construct controllers.
mControllers = new TaskbarControllers(this,
new TaskbarDragController(this),
@@ -239,7 +259,8 @@
: TaskbarRecentAppsController.DEFAULT,
new TaskbarEduTooltipController(this),
new KeyboardQuickSwitchController(),
- new TaskbarDividerPopupController(this));
+ new TaskbarDividerPopupController(this),
+ bubbleControllersOptional);
}
public void init(@NonNull TaskbarSharedState sharedState) {
@@ -661,7 +682,10 @@
void onDragEndOrViewRemoved() {
boolean isDragInProgress = mControllers.taskbarDragController.isSystemDragInProgress();
- if (!isDragInProgress && !AbstractFloatingView.hasOpenView(this, TYPE_ALL)) {
+ // Overlay AFVs are in a separate window and do not require Taskbar to be fullscreen.
+ if (!isDragInProgress
+ && !AbstractFloatingView.hasOpenView(
+ this, TYPE_ALL & ~TYPE_TASKBAR_OVERLAY_PROXY)) {
// Reverts Taskbar window to its original size
setTaskbarWindowFullscreen(false);
}
@@ -773,6 +797,7 @@
}
protected void onTaskbarIconClicked(View view) {
+ boolean shouldCloseAllOpenViews = true;
Object tag = view.getTag();
if (tag instanceof Task) {
Task task = (Task) tag;
@@ -780,6 +805,7 @@
ActivityOptions.makeBasic());
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
} else if (tag instanceof FolderInfo) {
+ shouldCloseAllOpenViews = false;
FolderIcon folderIcon = (FolderIcon) view;
Folder folder = folderIcon.getFolder();
@@ -876,7 +902,9 @@
Log.e(TAG, "Unknown type clicked: " + tag);
}
- AbstractFloatingView.closeAllOpenViews(this);
+ if (shouldCloseAllOpenViews) {
+ AbstractFloatingView.closeAllOpenViews(this);
+ }
}
/**
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index 1cd6f50..66c2eb3 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -23,12 +23,14 @@
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController;
+import com.android.launcher3.taskbar.bubbles.BubbleControllers;
import com.android.launcher3.taskbar.overlay.TaskbarOverlayController;
import com.android.systemui.shared.rotation.RotationButtonController;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
/**
* Hosts various taskbar controllers to facilitate passing between one another.
@@ -61,6 +63,7 @@
public final TaskbarEduTooltipController taskbarEduTooltipController;
public final KeyboardQuickSwitchController keyboardQuickSwitchController;
public final TaskbarDividerPopupController taskbarPinningController;
+ public final Optional<BubbleControllers> bubbleControllers;
@Nullable private LoggableTaskbarController[] mControllersToLog = null;
@Nullable private BackgroundRendererController[] mBackgroundRendererControllers = null;
@@ -107,7 +110,8 @@
TaskbarRecentAppsController taskbarRecentAppsController,
TaskbarEduTooltipController taskbarEduTooltipController,
KeyboardQuickSwitchController keyboardQuickSwitchController,
- TaskbarDividerPopupController taskbarPinningController) {
+ TaskbarDividerPopupController taskbarPinningController,
+ Optional<BubbleControllers> bubbleControllers) {
this.taskbarActivityContext = taskbarActivityContext;
this.taskbarDragController = taskbarDragController;
this.navButtonController = navButtonController;
@@ -133,6 +137,7 @@
this.taskbarEduTooltipController = taskbarEduTooltipController;
this.keyboardQuickSwitchController = keyboardQuickSwitchController;
this.taskbarPinningController = taskbarPinningController;
+ this.bubbleControllers = bubbleControllers;
}
/**
@@ -167,6 +172,7 @@
taskbarEduTooltipController.init(this);
keyboardQuickSwitchController.init(this);
taskbarPinningController.init(this);
+ bubbleControllers.ifPresent(controllers -> controllers.init(this));
mControllersToLog = new LoggableTaskbarController[] {
taskbarDragController, navButtonController, navbarButtonsViewController,
@@ -226,6 +232,7 @@
taskbarRecentAppsController.onDestroy();
keyboardQuickSwitchController.onDestroy();
taskbarStashController.onDestroy();
+ bubbleControllers.ifPresent(controllers -> controllers.onDestroy());
mControllersToLog = null;
mBackgroundRendererControllers = null;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index 41093bd..72add4f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -308,15 +308,12 @@
// Pre-drag has ended, start the global system drag.
if (mDisallowGlobalDrag) {
AbstractFloatingView.closeAllOpenViewsExcept(mActivity, TYPE_TASKBAR_ALL_APPS);
- } else {
- AbstractFloatingView.closeAllOpenViews(mActivity);
+ return;
}
-
startSystemDrag((BubbleTextView) mDragObject.originalView);
}
private void startSystemDrag(BubbleTextView btv) {
- if (mDisallowGlobalDrag) return;
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(btv) {
@Override
@@ -412,6 +409,9 @@
.log(StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DRAG_STARTED);
}
}
+
+ // Wait to close until after system drag has started, if applicable.
+ AbstractFloatingView.closeAllOpenViews(mActivity);
}
private void onSystemDragStarted(BubbleTextView btv) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
index 19b9a18..4422fd4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarInsetsController.kt
@@ -34,8 +34,6 @@
import android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD
import android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION
import com.android.internal.policy.GestureNavigationSettingsObserver
-import com.android.launcher3.AbstractFloatingView
-import com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_OVERLAY_PROXY
import com.android.launcher3.DeviceProfile
import com.android.launcher3.R
import com.android.launcher3.anim.AlphaUpdateListener
@@ -190,7 +188,7 @@
/**
* Called to update the touchable insets.
*
- * @see InternalInsetsInfo.setTouchableInsets
+ * @see ViewTreeObserver.InternalInsetsInfo.setTouchableInsets
*/
fun updateInsetsTouchability(insetsInfo: ViewTreeObserver.InternalInsetsInfo) {
insetsInfo.touchableRegion.setEmpty()
@@ -205,7 +203,7 @@
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
} else if (
controllers.navbarButtonsViewController.isImeVisible &&
- controllers.taskbarStashController.isStashed()
+ controllers.taskbarStashController.isStashed
) {
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
} else if (!controllers.uiController.isTaskbarTouchable) {
@@ -214,26 +212,16 @@
} else if (controllers.taskbarDragController.isSystemDragInProgress) {
// Let touches pass through us.
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
- } else if (AbstractFloatingView.hasOpenView(context, TYPE_TASKBAR_OVERLAY_PROXY)) {
- // Let touches pass through us if icons are hidden.
- if (controllers.taskbarViewController.areIconsVisible()) {
- insetsInfo.touchableRegion.set(touchableRegion)
- }
- insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
+ } else if (context.isTaskbarWindowFullscreen) {
+ // Intercept entire fullscreen window.
+ insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_FRAME)
+ insetsIsTouchableRegion = false
} else if (
- controllers.taskbarViewController.areIconsVisible() ||
- AbstractFloatingView.hasOpenView(context, AbstractFloatingView.TYPE_ALL) ||
- context.isNavBarKidsModeActive
+ controllers.taskbarViewController.areIconsVisible() || context.isNavBarKidsModeActive
) {
// Taskbar has some touchable elements, take over the full taskbar area
- insetsInfo.setTouchableInsets(
- if (context.isTaskbarWindowFullscreen) {
- TOUCHABLE_INSETS_FRAME
- } else {
- insetsInfo.touchableRegion.set(touchableRegion)
- TOUCHABLE_INSETS_REGION
- }
- )
+ insetsInfo.touchableRegion.set(touchableRegion)
+ insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
insetsIsTouchableRegion = false
} else {
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION)
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 5de5904..c2175f2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -934,20 +934,6 @@
}
/**
- * Resets the flag if no system gesture is in progress.
- * <p>
- * Otherwise, the reset should be deferred until after the gesture is finished.
- *
- * @see #setSystemGestureInProgress
- */
- public void resetFlagIfNoGestureInProgress(int flag) {
- if (!mIsSystemGestureInProgress) {
- updateStateForFlag(flag, false);
- applyState(mControllers.taskbarOverlayController.getCloseDuration());
- }
- }
-
- /**
* When hiding the IME, delay the unstash animation to align with the end of the transition.
*/
private long getTaskbarStashStartDelayForIme() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index a7e2daa..7429185 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -639,7 +639,7 @@
public View.OnClickListener getAllAppsButtonClickListener() {
return v -> {
mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP);
- mControllers.taskbarAllAppsController.show();
+ mControllers.taskbarAllAppsController.toggle();
};
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
index 4266c71..459a658 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
@@ -100,9 +100,13 @@
}
}
- /** Opens the {@link TaskbarAllAppsContainerView} in a new window. */
- public void show() {
- show(true);
+ /** Toggles visibility of {@link TaskbarAllAppsContainerView} in the overlay window. */
+ public void toggle() {
+ if (isOpen()) {
+ mSlideInView.close(true);
+ } else {
+ show(true);
+ }
}
/** Returns {@code true} if All Apps is open. */
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
index 7a3b3e8..01342af 100644
--- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
@@ -16,7 +16,6 @@
package com.android.launcher3.taskbar.allapps;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_STASHED_IN_TASKBAR_ALL_APPS;
-import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.OnboardingPrefs.ALL_APPS_VISITED_COUNT;
import com.android.launcher3.AbstractFloatingView;
@@ -88,8 +87,10 @@
}
private void setUpTaskbarStashing() {
- mTaskbarStashController.updateStateForFlag(FLAG_STASHED_IN_TASKBAR_ALL_APPS, true);
- mTaskbarStashController.applyState(mOverlayController.getOpenDuration());
+ if (DisplayController.isTransientTaskbar(mContext)) {
+ mTaskbarStashController.updateStateForFlag(FLAG_STASHED_IN_TASKBAR_ALL_APPS, true);
+ mTaskbarStashController.applyState(mOverlayController.getOpenDuration());
+ }
mNavbarButtonsViewController.setSlideInViewVisible(true);
mSlideInView.setOnCloseBeginListener(() -> {
@@ -100,11 +101,6 @@
if (DisplayController.isTransientTaskbar(mContext)) {
mTaskbarStashController.updateStateForFlag(FLAG_STASHED_IN_TASKBAR_ALL_APPS, false);
mTaskbarStashController.applyState(mOverlayController.getCloseDuration());
- } else {
- // Post in case view is closing due to gesture navigation. If a gesture is in
- // progress, wait to unstash until after the gesture is finished.
- MAIN_EXECUTOR.post(() -> mTaskbarStashController.resetFlagIfNoGestureInProgress(
- FLAG_STASHED_IN_TASKBAR_ALL_APPS));
}
});
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBubble.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBubble.kt
index b1633e7..3cd5f75 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBubble.kt
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarBubble.kt
@@ -30,7 +30,5 @@
val appName: String
) {
- fun getKey(): String {
- return info.key
- }
+ val key: String = info.key
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
index 228aabd..a466548 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java
@@ -152,7 +152,9 @@
mContext = context;
mBarView = bubbleView; // Need the view for inflating bubble views.
- // TODO: register the listener with SysUiProxu
+ if (BUBBLE_BAR_ENABLED) {
+ SystemUiProxy.INSTANCE.get(context).setBubblesListener(this);
+ }
mMainExecutor = MAIN_EXECUTOR;
mLauncherApps = context.getSystemService(LauncherApps.class);
mIconFactory = new BubbleIconFactory(context,
@@ -164,7 +166,7 @@
}
public void onDestroy() {
- // TODO: unregister the listener with SysUiProxy
+ SystemUiProxy.INSTANCE.get(mContext).setBubblesListener(null);
}
public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index 0afc2cb..82494c6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -30,6 +30,7 @@
import com.android.launcher3.taskbar.TaskbarControllers;
import com.android.launcher3.util.MultiPropertyFactory;
import com.android.launcher3.util.MultiValueAlpha;
+import com.android.quickstep.SystemUiProxy;
import java.util.List;
import java.util.Objects;
@@ -42,6 +43,7 @@
private static final String TAG = BubbleBarViewController.class.getSimpleName();
+ private final SystemUiProxy mSystemUiProxy;
private final TaskbarActivityContext mActivity;
private final BubbleBarView mBarView;
private final int mIconSize;
@@ -69,6 +71,7 @@
public BubbleBarViewController(TaskbarActivityContext activity, BubbleBarView barView) {
mActivity = activity;
mBarView = barView;
+ mSystemUiProxy = SystemUiProxy.INSTANCE.get(mActivity);
mBubbleBarAlpha = new MultiValueAlpha(mBarView, 1 /* num alpha channels */);
mBubbleBarAlpha.setUpdateVisibility(true);
mIconSize = activity.getResources().getDimensionPixelSize(R.dimen.bubblebar_icon_size);
@@ -101,7 +104,8 @@
mBubbleStashController.stashBubbleBar();
} else {
mBubbleBarController.setSelectedBubble(bubble);
- // TODO: Tell SysUi to show the expanded view for this bubble.
+ mSystemUiProxy.showBubble(bubble.getKey(),
+ mBubbleStashController.isBubblesShowingOnHome());
}
}
@@ -270,11 +274,12 @@
if (isExpanded != mBarView.isExpanded()) {
mBarView.setExpanded(isExpanded);
if (!isExpanded) {
- // TODO: Tell SysUi to collapse the bubble
+ mSystemUiProxy.collapseBubbles();
} else {
final String selectedKey = mBubbleBarController.getSelectedBubbleKey();
if (selectedKey != null) {
- // TODO: Tell SysUi to show the bubble
+ mSystemUiProxy.showBubble(selectedKey,
+ mBubbleStashController.isBubblesShowingOnHome());
} else {
Log.w(TAG, "trying to expand bubbles when there isn't one selected");
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
index 66d5918..84a5228 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayContext.java
@@ -80,6 +80,12 @@
return mOverlayController;
}
+ /** Returns {@code true} if overlay or Taskbar windows are handling a system drag. */
+ boolean isAnySystemDragInProgress() {
+ return mDragController.isSystemDragInProgress()
+ || mTaskbarContext.getDragController().isSystemDragInProgress();
+ }
+
@Override
public DeviceProfile getDeviceProfile() {
return mOverlayController.getLauncherDeviceProfile();
diff --git a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
index 2c3e1ac..b4ec682 100644
--- a/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/overlay/TaskbarOverlayDragLayer.java
@@ -112,7 +112,7 @@
@Override
public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo inoutInfo) {
- if (mActivity.getDragController().isSystemDragInProgress()) {
+ if (mActivity.isAnySystemDragInProgress()) {
inoutInfo.touchableRegion.setEmpty();
inoutInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
}
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 36aa6f5..0549d9f 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -71,6 +71,8 @@
import com.android.systemui.unfold.progress.IUnfoldAnimation;
import com.android.systemui.unfold.progress.IUnfoldTransitionListener;
import com.android.wm.shell.back.IBackAnimation;
+import com.android.wm.shell.bubbles.IBubbles;
+import com.android.wm.shell.bubbles.IBubblesListener;
import com.android.wm.shell.desktopmode.IDesktopMode;
import com.android.wm.shell.draganddrop.IDragAndDrop;
import com.android.wm.shell.onehanded.IOneHanded;
@@ -103,6 +105,7 @@
private ISystemUiProxy mSystemUiProxy;
private IPip mPip;
+ private IBubbles mBubbles;
private ISysuiUnlockAnimationController mSysuiUnlockAnimationController;
private ISplitScreen mSplitScreen;
private IOneHanded mOneHanded;
@@ -121,6 +124,7 @@
// up to the caller to clear the listeners to prevent leaks as these can be held indefinitely
// in case SysUI needs to rebind.
private IPipAnimationListener mPipAnimationListener;
+ private IBubblesListener mBubblesListener;
private ISplitScreenListener mSplitScreenListener;
private IStartingWindowListener mStartingWindowListener;
private ILauncherUnlockAnimationController mLauncherUnlockAnimationController;
@@ -206,7 +210,7 @@
* Sets proxy state, including death linkage, various listeners, and other configuration objects
*/
@MainThread
- public void setProxy(ISystemUiProxy proxy, IPip pip, ISplitScreen splitScreen,
+ public void setProxy(ISystemUiProxy proxy, IPip pip, IBubbles bubbles, ISplitScreen splitScreen,
IOneHanded oneHanded, IShellTransitions shellTransitions,
IStartingWindow startingWindow, IRecentTasks recentTasks,
ISysuiUnlockAnimationController sysuiUnlockAnimationController,
@@ -216,6 +220,7 @@
unlinkToDeath();
mSystemUiProxy = proxy;
mPip = pip;
+ mBubbles = bubbles;
mSplitScreen = splitScreen;
mOneHanded = oneHanded;
mShellTransitions = shellTransitions;
@@ -229,6 +234,7 @@
linkToDeath();
// re-attach the listeners once missing due to setProxy has not been initialized yet.
setPipAnimationListener(mPipAnimationListener);
+ setBubblesListener(mBubblesListener);
registerSplitScreenListener(mSplitScreenListener);
setStartingWindowListener(mStartingWindowListener);
setLauncherUnlockAnimationController(mLauncherUnlockAnimationController);
@@ -244,7 +250,7 @@
*/
@MainThread
public void clearProxy() {
- setProxy(null, null, null, null, null, null, null, null, null, null, null, null);
+ setProxy(null, null, null, null, null, null, null, null, null, null, null, null, null);
}
// TODO(141886704): Find a way to remove this
@@ -585,6 +591,59 @@
}
//
+ // Bubbles
+ //
+
+ /**
+ * Sets the listener to be notified of bubble state changes.
+ */
+ public void setBubblesListener(IBubblesListener listener) {
+ if (mBubbles != null) {
+ try {
+ if (mBubblesListener != null) {
+ // Clear out any previous listener
+ mBubbles.unregisterBubbleListener(mBubblesListener);
+ }
+ if (listener != null) {
+ mBubbles.registerBubbleListener(listener);
+ }
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call registerBubblesListener");
+ }
+ }
+ mBubblesListener = listener;
+ }
+
+ /**
+ * Tells SysUI to show the bubble with the provided key.
+ * @param key the key of the bubble to show.
+ * @param onLauncherHome whether the bubble is showing on launcher home or not (modifies where
+ * the expanded bubble view is placed).
+ */
+ public void showBubble(String key, boolean onLauncherHome) {
+ if (mBubbles != null) {
+ try {
+ mBubbles.showBubble(key, onLauncherHome);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call showBubble");
+ }
+ }
+ }
+
+ /**
+ * Tells SysUI to collapse the bubbles.
+ */
+ public void collapseBubbles() {
+ if (mBubbles != null) {
+ try {
+ mBubbles.collapseBubbles();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call collapseBubbles");
+ }
+ }
+ }
+
+ //
// Splitscreen
//
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 66aeee7..682763f 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -43,6 +43,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BACK_ANIMATION;
+import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_BUBBLES;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DESKTOP_MODE;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DRAG_AND_DROP;
import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_ONE_HANDED;
@@ -126,6 +127,7 @@
import com.android.systemui.shared.tracing.ProtoTraceable;
import com.android.systemui.unfold.progress.IUnfoldAnimation;
import com.android.wm.shell.back.IBackAnimation;
+import com.android.wm.shell.bubbles.IBubbles;
import com.android.wm.shell.desktopmode.IDesktopMode;
import com.android.wm.shell.draganddrop.IDragAndDrop;
import com.android.wm.shell.onehanded.IOneHanded;
@@ -169,6 +171,7 @@
ISystemUiProxy proxy = ISystemUiProxy.Stub.asInterface(
bundle.getBinder(KEY_EXTRA_SYSUI_PROXY));
IPip pip = IPip.Stub.asInterface(bundle.getBinder(KEY_EXTRA_SHELL_PIP));
+ IBubbles bubbles = IBubbles.Stub.asInterface(bundle.getBinder(KEY_EXTRA_SHELL_BUBBLES));
ISplitScreen splitscreen = ISplitScreen.Stub.asInterface(bundle.getBinder(
KEY_EXTRA_SHELL_SPLIT_SCREEN));
IOneHanded onehanded = IOneHanded.Stub.asInterface(
@@ -192,7 +195,7 @@
bundle.getBinder(KEY_EXTRA_SHELL_DRAG_AND_DROP));
MAIN_EXECUTOR.execute(() -> {
SystemUiProxy.INSTANCE.get(TouchInteractionService.this).setProxy(proxy, pip,
- splitscreen, onehanded, shellTransitions, startingWindow,
+ bubbles, splitscreen, onehanded, shellTransitions, startingWindow,
recentTasks, launcherUnlockAnimationController, backAnimation, desktopMode,
unfoldTransition, dragAndDrop);
TouchInteractionService.this.initInputMonitor("TISBinder#onInitialize()");
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 796cd62..50a1dad 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -92,6 +92,7 @@
import com.android.quickstep.RecentsModel;
import com.android.quickstep.RemoteAnimationTargets;
import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
+import com.android.quickstep.TaskAnimationManager;
import com.android.quickstep.TaskIconCache;
import com.android.quickstep.TaskOverlayFactory;
import com.android.quickstep.TaskThumbnailCache;
@@ -802,6 +803,14 @@
recentsView.addSideTaskLaunchCallback(callbackList);
return callbackList;
}
+ if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
+ // If the recents transition is running (ie. in live tile mode), then the start
+ // of a new task will merge into the existing transition and it currently will
+ // not be run independently, so we need to rely on the onTaskAppeared() call
+ // for the new task to trigger the side launch callback to flush this runnable
+ // list (which is usually flushed when the app launch animation finishes)
+ recentsView.addSideTaskLaunchCallback(opts.onEndCallback);
+ }
return opts.onEndCallback;
} else {
notifyTaskLaunchFailed(TAG);
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
index 20466ad..2c16c15 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
@@ -16,8 +16,10 @@
package com.android.launcher3.taskbar
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController
+import com.android.launcher3.taskbar.bubbles.BubbleControllers
import com.android.launcher3.taskbar.overlay.TaskbarOverlayController
import com.android.systemui.shared.rotation.RotationButtonController
+import java.util.Optional
import org.junit.Before
import org.mockito.Mock
import org.mockito.MockitoAnnotations
@@ -54,6 +56,7 @@
@Mock lateinit var taskbarEduTooltipController: TaskbarEduTooltipController
@Mock lateinit var keyboardQuickSwitchController: KeyboardQuickSwitchController
@Mock lateinit var taskbarPinningController: TaskbarDividerPopupController
+ @Mock lateinit var optionalBubbleControllers: Optional<BubbleControllers>
lateinit var taskbarControllers: TaskbarControllers
@@ -94,6 +97,7 @@
taskbarEduTooltipController,
keyboardQuickSwitchController,
taskbarPinningController,
+ optionalBubbleControllers,
)
}
}
diff --git a/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt b/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
index acfd54c..65542cf 100644
--- a/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/util/SplitSelectStateControllerTest.kt
@@ -33,14 +33,10 @@
import com.android.launcher3.statemanager.StateManager
import com.android.launcher3.util.ComponentKey
import com.android.launcher3.util.SplitConfigurationOptions
-import com.android.launcher3.util.SplitConfigurationOptions.StagePosition
-import com.android.launcher3.util.mock
import com.android.launcher3.util.withArgCaptor
import com.android.quickstep.RecentsModel
import com.android.quickstep.SystemUiProxy
import com.android.systemui.shared.recents.model.Task
-import java.util.ArrayList
-import java.util.function.Consumer
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
@@ -50,7 +46,9 @@
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
+import java.util.function.Consumer
@RunWith(AndroidJUnit4::class)
class SplitSelectStateControllerTest {
@@ -355,6 +353,7 @@
@Test
fun secondPendingIntentSet() {
val itemInfo = ItemInfo()
+ `when`(pendingIntent.creatorUserHandle).thenReturn(primaryUserHandle)
splitSelectStateController.setInitialTaskSelect(null, 0, itemInfo, null, 1)
splitSelectStateController.setSecondTask(pendingIntent)
assertTrue(splitSelectStateController.isBothSplitAppsConfirmed)
diff --git a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
index 5fbd48c..f041ffb 100644
--- a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
+++ b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
@@ -16,8 +16,8 @@
import androidx.annotation.WorkerThread;
import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.model.DatabaseHelper;
import com.android.launcher3.model.LoaderTask;
-import com.android.launcher3.model.ModelDbController;
import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.pm.UserCache;
@@ -52,7 +52,7 @@
* Updates the app widgets whose id has changed during the restore process.
*/
@WorkerThread
- public static void restoreAppWidgetIds(Context context, ModelDbController controller,
+ public static void restoreAppWidgetIds(Context context, DatabaseHelper helper,
int[] oldWidgetIds, int[] newWidgetIds, @NonNull AppWidgetHost host) {
if (WidgetsModel.GO_DISABLE_WIDGETS) {
Log.e(TAG, "Skipping widget ID remap as widgets not supported");
@@ -92,12 +92,12 @@
final String where = "appWidgetId=? and (restored & 1) = 1 and profileId=?";
final String[] args = new String[] { oldWidgetId, Long.toString(mainProfileId) };
int result = new ContentWriter(context,
- new ContentWriter.CommitParams(controller, where, args))
+ new ContentWriter.CommitParams(helper, where, args))
.put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i])
.put(LauncherSettings.Favorites.RESTORED, state)
.commit();
if (result == 0) {
- Cursor cursor = controller.getDb().query(
+ Cursor cursor = helper.getWritableDatabase().query(
Favorites.TABLE_NAME,
new String[] {Favorites.APPWIDGET_ID},
"appWidgetId=?", new String[] { oldWidgetId }, null, null, null);
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 9abec50..0df4bd4 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -263,6 +263,18 @@
getModelDbController().refreshHotseatRestoreTable();
return null;
}
+ case LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER: {
+ Bundle result = new Bundle();
+ result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
+ getModelDbController().updateCurrentOpenHelper(arg /* dbFile */));
+ return result;
+ }
+ case LauncherSettings.Settings.METHOD_PREP_FOR_PREVIEW: {
+ Bundle result = new Bundle();
+ result.putBoolean(LauncherSettings.Settings.EXTRA_VALUE,
+ getModelDbController().prepareForPreview(arg /* dbFile */));
+ return result;
+ }
}
return null;
}
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 7fda326..b65e96b 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -148,6 +148,11 @@
public static final String HYBRID_HOTSEAT_BACKUP_TABLE = "hotseat_restore_backup";
/**
+ * Temporary table used specifically for grid migrations during wallpaper preview
+ */
+ public static final String PREVIEW_TABLE_NAME = "favorites_preview";
+
+ /**
* Temporary table used specifically for multi-db grid migrations
*/
public static final String TMP_TABLE = "favorites_tmp";
@@ -159,6 +164,18 @@
+ LauncherProvider.AUTHORITY + "/" + TABLE_NAME);
/**
+ * The content:// style URL for "favorites_preview" table
+ */
+ public static final Uri PREVIEW_CONTENT_URI = Uri.parse("content://"
+ + LauncherProvider.AUTHORITY + "/" + PREVIEW_TABLE_NAME);
+
+ /**
+ * The content:// style URL for "favorites_tmp" table
+ */
+ public static final Uri TMP_CONTENT_URI = Uri.parse("content://"
+ + LauncherProvider.AUTHORITY + "/" + TMP_TABLE);
+
+ /**
* The content:// style URL for a given row, identified by its id.
*
* @param id The row id.
@@ -359,6 +376,10 @@
public static final String METHOD_REFRESH_HOTSEAT_RESTORE_TABLE = "restore_hotseat_table";
+ public static final String METHOD_UPDATE_CURRENT_OPEN_HELPER = "update_current_open_helper";
+
+ public static final String METHOD_PREP_FOR_PREVIEW = "prep_for_preview";
+
public static final String EXTRA_VALUE = "value";
public static final String EXTRA_DB_NAME = "db_name";
@@ -372,8 +393,11 @@
}
public static Bundle call(ContentResolver cr, String method, String arg) {
- return cr.call(CONTENT_URI, method, arg, null);
+ return call(cr, method, arg, null /* extras */);
}
+ public static Bundle call(ContentResolver cr, String method, String arg, Bundle extras) {
+ return cr.call(CONTENT_URI, method, arg, extras);
+ }
}
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 7f04860..065122a 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -415,7 +415,7 @@
// TODO(Block 31)
public static final BooleanFlag ENABLE_SPLIT_LAUNCH_DATA_REFACTOR = getDebugFlag(279494325,
- "ENABLE_SPLIT_LAUNCH_DATA_REFACTOR", DISABLED,
+ "ENABLE_SPLIT_LAUNCH_DATA_REFACTOR", ENABLED,
"Use refactored split launching code path");
// TODO(Block 32): Empty block
diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
index 8f0b8ec..372e9bf 100644
--- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
+++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
@@ -16,7 +16,6 @@
package com.android.launcher3.graphics;
-import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
@@ -53,8 +52,6 @@
import com.android.launcher3.model.BgDataModel;
import com.android.launcher3.model.GridSizeMigrationUtil;
import com.android.launcher3.model.LoaderTask;
-import com.android.launcher3.model.ModelDbController;
-import com.android.launcher3.provider.LauncherDbUtils;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.Themes;
@@ -148,9 +145,7 @@
final String query = LauncherSettings.Favorites.ITEM_TYPE + " = "
+ LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET;
- ModelDbController mainController =
- LauncherAppState.getInstance(mContext).getModel().getModelDbController();
- try (Cursor c = mainController.query(TABLE_NAME,
+ try (Cursor c = context.getContentResolver().query(LauncherSettings.Favorites.CONTENT_URI,
new String[] {
LauncherSettings.Favorites.APPWIDGET_ID,
LauncherSettings.Favorites.SPANX,
@@ -195,6 +190,8 @@
@WorkerThread
private void loadModelData() {
+ final boolean migrated = doGridMigrationIfNecessary();
+
final Context inflationContext;
if (mWallpaperColors != null) {
// Create a themed context, without affecting the main application context
@@ -212,20 +209,8 @@
Themes.getActivityThemeRes(mContext));
}
- if (GridSizeMigrationUtil.needsToMigrate(inflationContext, mIdp)) {
- // Start the migration
+ if (migrated) {
PreviewContext previewContext = new PreviewContext(inflationContext, mIdp);
- // Copy existing data to preview DB
- LauncherDbUtils.copyTable(LauncherAppState.getInstance(mContext)
- .getModel().getModelDbController().getDb(),
- TABLE_NAME,
- LauncherAppState.getInstance(previewContext)
- .getModel().getModelDbController().getDb(),
- TABLE_NAME,
- mContext);
- LauncherAppState.getInstance(previewContext)
- .getModel().getModelDbController().clearEmptyDbFlag();
-
new LoaderTask(
LauncherAppState.getInstance(previewContext),
/* bgAllAppsList= */ null,
@@ -244,7 +229,8 @@
query += " or " + LauncherSettings.Favorites.SCREEN + " = "
+ Workspace.SECOND_SCREEN_ID;
}
- loadWorkspace(new ArrayList<>(), query, null);
+ loadWorkspaceForPreviewSurfaceRenderer(new ArrayList<>(),
+ LauncherSettings.Favorites.PREVIEW_CONTENT_URI, query);
final SparseArray<Size> spanInfo =
getLoadedLauncherWidgetInfo(previewContext.getBaseContext());
@@ -267,6 +253,14 @@
}
}
+ @WorkerThread
+ private boolean doGridMigrationIfNecessary() {
+ if (!GridSizeMigrationUtil.needsToMigrate(mContext, mIdp)) {
+ return false;
+ }
+ return GridSizeMigrationUtil.migrateGridIfNeeded(mContext, mIdp);
+ }
+
@UiThread
private void renderView(Context inflationContext, BgDataModel dataModel,
Map<ComponentKey, AppWidgetProviderInfo> widgetProviderInfoMap,
diff --git a/src/com/android/launcher3/model/DatabaseHelper.java b/src/com/android/launcher3/model/DatabaseHelper.java
index ecf5f67..dc5fcf7 100644
--- a/src/com/android/launcher3/model/DatabaseHelper.java
+++ b/src/com/android/launcher3/model/DatabaseHelper.java
@@ -15,8 +15,8 @@
*/
package com.android.launcher3.model;
-import static com.android.launcher3.LauncherSettings.Favorites.addTableToDb;
import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
+import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
import android.content.ContentValues;
import android.content.Context;
@@ -36,6 +36,9 @@
import com.android.launcher3.AutoInstallsLayout;
import com.android.launcher3.AutoInstallsLayout.LayoutParserCallback;
+import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherFiles;
+import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.Utilities;
@@ -55,7 +58,6 @@
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Locale;
-import java.util.function.ToLongFunction;
import java.util.stream.Collectors;
/**
@@ -74,23 +76,45 @@
private static final boolean LOGD = false;
private static final String DOWNGRADE_SCHEMA_FILE = "downgrade_schema.json";
+ public static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED";
private final Context mContext;
- private final ToLongFunction<UserHandle> mUserSerialProvider;
- private final Runnable mOnEmptyDbCreateCallback;
-
+ private final boolean mForMigration;
private int mMaxItemId = -1;
public boolean mHotseatRestoreTableExists;
+ public static DatabaseHelper createDatabaseHelper(Context context, boolean forMigration) {
+ return createDatabaseHelper(context, null, forMigration);
+ }
+
+ public static DatabaseHelper createDatabaseHelper(Context context, String dbName,
+ boolean forMigration) {
+ if (dbName == null) {
+ dbName = InvariantDeviceProfile.INSTANCE.get(context).dbFile;
+ }
+ DatabaseHelper databaseHelper = new DatabaseHelper(context, dbName, forMigration);
+ // Table creation sometimes fails silently, which leads to a crash loop.
+ // This way, we will try to create a table every time after crash, so the device
+ // would eventually be able to recover.
+ if (!tableExists(databaseHelper.getReadableDatabase(), Favorites.TABLE_NAME)) {
+ Log.e(TAG, "Tables are missing after onCreate has been called. Trying to recreate");
+ // This operation is a no-op if the table already exists.
+ databaseHelper.addFavoritesTable(databaseHelper.getWritableDatabase(), true);
+ }
+ databaseHelper.mHotseatRestoreTableExists = tableExists(
+ databaseHelper.getReadableDatabase(), Favorites.HYBRID_HOTSEAT_BACKUP_TABLE);
+
+ databaseHelper.initIds();
+ return databaseHelper;
+ }
+
/**
* Constructor used in tests and for restore.
*/
- public DatabaseHelper(Context context, String dbName,
- ToLongFunction<UserHandle> userSerialProvider, Runnable onEmptyDbCreateCallback) {
+ public DatabaseHelper(Context context, String dbName, boolean forMigration) {
super(context, dbName, SCHEMA_VERSION);
mContext = context;
- mUserSerialProvider = userSerialProvider;
- mOnEmptyDbCreateCallback = onEmptyDbCreateCallback;
+ mForMigration = forMigration;
}
protected void initIds() {
@@ -107,11 +131,13 @@
mMaxItemId = 1;
- addTableToDb(db, getDefaultUserSerial(), false /* optional */);
+ addFavoritesTable(db, false);
// Fresh and clean launcher DB.
mMaxItemId = initializeMaxItemId(db);
- mOnEmptyDbCreateCallback.run();
+ if (!mForMigration) {
+ onEmptyDbCreated();
+ }
}
public void onAddOrDeleteOp(SQLiteDatabase db) {
@@ -121,8 +147,38 @@
}
}
- private long getDefaultUserSerial() {
- return mUserSerialProvider.applyAsLong(Process.myUserHandle());
+ /**
+ * Re-composite given key in respect to database. If the current db is
+ * {@link LauncherFiles#LAUNCHER_DB}, return the key as-is. Otherwise append the db name to
+ * given key. e.g. consider key="EMPTY_DATABASE_CREATED", dbName="minimal.db", the returning
+ * string will be "EMPTY_DATABASE_CREATED@minimal.db".
+ */
+ public String getKey(final String key) {
+ if (TextUtils.equals(getDatabaseName(), LauncherFiles.LAUNCHER_DB)) {
+ return key;
+ }
+ return key + "@" + getDatabaseName();
+ }
+
+ /**
+ * Overridden in tests.
+ */
+ protected void onEmptyDbCreated() {
+ // Set the flag for empty DB
+ LauncherPrefs.getPrefs(mContext).edit().putBoolean(getKey(EMPTY_DATABASE_CREATED), true)
+ .commit();
+ }
+
+ public long getSerialNumberForUser(UserHandle user) {
+ return UserCache.INSTANCE.get(mContext).getSerialNumberForUser(user);
+ }
+
+ public long getDefaultUserSerial() {
+ return getSerialNumberForUser(Process.myUserHandle());
+ }
+
+ private void addFavoritesTable(SQLiteDatabase db, boolean optional) {
+ Favorites.addTableToDb(db, getDefaultUserSerial(), optional);
}
@Override
diff --git a/src/com/android/launcher3/model/GridSizeMigrationUtil.java b/src/com/android/launcher3/model/GridSizeMigrationUtil.java
index 9a6cde6..eded5ea 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationUtil.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationUtil.java
@@ -16,9 +16,6 @@
package com.android.launcher3.model;
-import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
-import static com.android.launcher3.LauncherSettings.Favorites.TMP_TABLE;
-import static com.android.launcher3.provider.LauncherDbUtils.copyTable;
import static com.android.launcher3.provider.LauncherDbUtils.dropTable;
import android.content.ComponentName;
@@ -37,15 +34,16 @@
import androidx.annotation.NonNull;
import com.android.launcher3.InvariantDeviceProfile;
+import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.graphics.LauncherPreviewRenderer;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.IntArray;
-import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetManagerHelper;
@@ -91,38 +89,81 @@
return needsToMigrate;
}
+ /** See {@link #migrateGridIfNeeded(Context, InvariantDeviceProfile)} */
+ public static boolean migrateGridIfNeeded(Context context) {
+ if (context instanceof LauncherPreviewRenderer.PreviewContext) {
+ return true;
+ }
+ return migrateGridIfNeeded(context, null);
+ }
+
/**
- * When migrating the grid, we copy the table
- * {@link LauncherSettings.Favorites#TABLE_NAME} from {@code source} into
- * {@link LauncherSettings.Favorites#TMP_TABLE}, run the grid size migration algorithm
+ * When migrating the grid for preview, we copy the table
+ * {@link LauncherSettings.Favorites#TABLE_NAME} into
+ * {@link LauncherSettings.Favorites#PREVIEW_TABLE_NAME}, run grid size migration from the
+ * former to the later, then use the later table for preview.
+ *
+ * Similarly when doing the actual grid migration, the former grid option's table
+ * {@link LauncherSettings.Favorites#TABLE_NAME} is copied into the new grid option's
+ * {@link LauncherSettings.Favorites#TMP_TABLE}, we then run the grid size migration algorithm
* to migrate the later to the former, and load the workspace from the default
* {@link LauncherSettings.Favorites#TABLE_NAME}.
*
* @return false if the migration failed.
*/
- public static boolean migrateGridIfNeeded(
- @NonNull Context context,
- @NonNull InvariantDeviceProfile idp,
- @NonNull DatabaseHelper target,
- @NonNull SQLiteDatabase source) {
+ public static boolean migrateGridIfNeeded(Context context, InvariantDeviceProfile idp) {
+ boolean migrateForPreview = idp != null;
+ if (!migrateForPreview) {
+ idp = LauncherAppState.getIDP(context);
+ }
DeviceGridState srcDeviceState = new DeviceGridState(context);
DeviceGridState destDeviceState = new DeviceGridState(idp);
if (!needsToMigrate(srcDeviceState, destDeviceState)) {
return true;
}
- copyTable(source, TABLE_NAME, target.getWritableDatabase(), TMP_TABLE, context);
HashSet<String> validPackages = getValidPackages(context);
+
+ if (migrateForPreview) {
+ if (!LauncherSettings.Settings.call(
+ context.getContentResolver(),
+ LauncherSettings.Settings.METHOD_PREP_FOR_PREVIEW,
+ destDeviceState.getDbFile()).getBoolean(
+ LauncherSettings.Settings.EXTRA_VALUE)) {
+ return false;
+ }
+ } else if (!LauncherSettings.Settings.call(
+ context.getContentResolver(),
+ LauncherSettings.Settings.METHOD_UPDATE_CURRENT_OPEN_HELPER,
+ destDeviceState.getDbFile()).getBoolean(
+ LauncherSettings.Settings.EXTRA_VALUE)) {
+ return false;
+ }
+
long migrationStartTime = System.currentTimeMillis();
- try (SQLiteTransaction t = new SQLiteTransaction(target.getWritableDatabase())) {
- DbReader srcReader = new DbReader(t.getDb(), TMP_TABLE, context, validPackages);
- DbReader destReader = new DbReader(t.getDb(), TABLE_NAME, context, validPackages);
+ try (SQLiteTransaction t = (SQLiteTransaction) LauncherSettings.Settings.call(
+ context.getContentResolver(),
+ LauncherSettings.Settings.METHOD_NEW_TRANSACTION).getBinder(
+ LauncherSettings.Settings.EXTRA_VALUE)) {
+
+ DbReader srcReader = new DbReader(t.getDb(),
+ migrateForPreview ? LauncherSettings.Favorites.TABLE_NAME
+ : LauncherSettings.Favorites.TMP_TABLE,
+ context, validPackages);
+ DbReader destReader = new DbReader(t.getDb(),
+ migrateForPreview ? LauncherSettings.Favorites.PREVIEW_TABLE_NAME
+ : LauncherSettings.Favorites.TABLE_NAME,
+ context, validPackages);
Point targetSize = new Point(destDeviceState.getColumns(), destDeviceState.getRows());
- migrate(target, srcReader, destReader, destDeviceState.getNumHotseat(),
+ migrate(context, t.getDb(), srcReader, destReader, destDeviceState.getNumHotseat(),
targetSize, srcDeviceState, destDeviceState);
- dropTable(t.getDb(), TMP_TABLE);
+
+ if (!migrateForPreview) {
+ dropTable(t.getDb(), LauncherSettings.Favorites.TMP_TABLE);
+ }
+
t.commit();
return true;
} catch (Exception e) {
@@ -133,7 +174,7 @@
Log.v(TAG, "Workspace migration completed in "
+ (System.currentTimeMillis() - migrationStartTime));
- if (!(context instanceof SandboxContext)) {
+ if (!migrateForPreview) {
// Save current configuration, so that the migration does not run again.
destDeviceState.writeToPrefs(context);
}
@@ -141,7 +182,7 @@
}
public static boolean migrate(
- @NonNull DatabaseHelper helper,
+ @NonNull final Context context, @NonNull final SQLiteDatabase db,
@NonNull final DbReader srcReader, @NonNull final DbReader destReader,
final int destHotseatSize, @NonNull final Point targetSize,
@NonNull final DeviceGridState srcDeviceState,
@@ -193,8 +234,8 @@
Collections.sort(workspaceToBeAdded);
// Migrate hotseat
- solveHotseatPlacement(helper, destHotseatSize,
- srcReader, destReader, dstHotseatItems, hotseatToBeAdded);
+ solveHotseatPlacement(db, srcReader,
+ destReader, context, destHotseatSize, dstHotseatItems, hotseatToBeAdded);
// Migrate workspace.
// First we create a collection of the screens
@@ -214,8 +255,8 @@
if (DEBUG) {
Log.d(TAG, "Migrating " + screenId);
}
- solveGridPlacement(helper, srcReader,
- destReader, screenId, trgX, trgY, workspaceToBeAdded, false);
+ solveGridPlacement(db, srcReader,
+ destReader, context, screenId, trgX, trgY, workspaceToBeAdded, false);
if (workspaceToBeAdded.isEmpty()) {
break;
}
@@ -225,8 +266,8 @@
// any of the screens, in this case we add them to new screens until all of them are placed.
int screenId = destReader.mLastScreenId + 1;
while (!workspaceToBeAdded.isEmpty()) {
- solveGridPlacement(helper, srcReader,
- destReader, screenId, trgX, trgY, workspaceToBeAdded, preservePages);
+ solveGridPlacement(db, srcReader,
+ destReader, context, screenId, trgX, trgY, workspaceToBeAdded, preservePages);
screenId++;
}
@@ -257,33 +298,33 @@
});
}
- private static void insertEntryInDb(DatabaseHelper helper, DbEntry entry,
+ private static void insertEntryInDb(SQLiteDatabase db, Context context, DbEntry entry,
String srcTableName, String destTableName) {
- int id = copyEntryAndUpdate(helper, entry, srcTableName, destTableName);
+ int id = copyEntryAndUpdate(db, context, entry, srcTableName, destTableName);
if (entry.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
for (Set<Integer> itemIds : entry.mFolderItems.values()) {
for (int itemId : itemIds) {
- copyEntryAndUpdate(helper, itemId, id, srcTableName, destTableName);
+ copyEntryAndUpdate(db, context, itemId, id, srcTableName, destTableName);
}
}
}
}
- private static int copyEntryAndUpdate(DatabaseHelper helper,
+ private static int copyEntryAndUpdate(SQLiteDatabase db, Context context,
DbEntry entry, String srcTableName, String destTableName) {
- return copyEntryAndUpdate(helper, entry, -1, -1, srcTableName, destTableName);
+ return copyEntryAndUpdate(db, context, entry, -1, -1, srcTableName, destTableName);
}
- private static int copyEntryAndUpdate(DatabaseHelper helper,
+ private static int copyEntryAndUpdate(SQLiteDatabase db, Context context,
int id, int folderId, String srcTableName, String destTableName) {
- return copyEntryAndUpdate(helper, null, id, folderId, srcTableName, destTableName);
+ return copyEntryAndUpdate(db, context, null, id, folderId, srcTableName, destTableName);
}
- private static int copyEntryAndUpdate(DatabaseHelper helper, DbEntry entry,
- int id, int folderId, String srcTableName, String destTableName) {
+ private static int copyEntryAndUpdate(SQLiteDatabase db, Context context,
+ DbEntry entry, int id, int folderId, String srcTableName, String destTableName) {
int newId = -1;
- Cursor c = helper.getWritableDatabase().query(srcTableName, null,
+ Cursor c = db.query(srcTableName, null,
LauncherSettings.Favorites._ID + " = '" + (entry != null ? entry.id : id) + "'",
null, null, null, null);
while (c.moveToNext()) {
@@ -294,9 +335,11 @@
} else {
values.put(LauncherSettings.Favorites.CONTAINER, folderId);
}
- newId = helper.generateNewItemId();
+ newId = LauncherSettings.Settings.call(context.getContentResolver(),
+ LauncherSettings.Settings.METHOD_NEW_ITEM_ID).getInt(
+ LauncherSettings.Settings.EXTRA_VALUE);
values.put(LauncherSettings.Favorites._ID, newId);
- helper.getWritableDatabase().insert(destTableName, null, values);
+ db.insert(destTableName, null, values);
}
c.close();
return newId;
@@ -324,9 +367,9 @@
return validPackages;
}
- private static void solveGridPlacement(@NonNull final DatabaseHelper helper,
+ private static void solveGridPlacement(@NonNull final SQLiteDatabase db,
@NonNull final DbReader srcReader, @NonNull final DbReader destReader,
- final int screenId, final int trgX, final int trgY,
+ @NonNull final Context context, final int screenId, final int trgX, final int trgY,
@NonNull final List<DbEntry> sortedItemsToPlace, final boolean matchingScreenIdOnly) {
final GridOccupancy occupied = new GridOccupancy(trgX, trgY);
final Point trg = new Point(trgX, trgY);
@@ -348,7 +391,7 @@
continue;
}
if (findPlacementForEntry(entry, next, trg, occupied, screenId)) {
- insertEntryInDb(helper, entry, srcReader.mTableName, destReader.mTableName);
+ insertEntryInDb(db, context, entry, srcReader.mTableName, destReader.mTableName);
iterator.remove();
}
}
@@ -385,9 +428,9 @@
return false;
}
- private static void solveHotseatPlacement(
- @NonNull final DatabaseHelper helper, final int hotseatSize,
+ private static void solveHotseatPlacement(@NonNull final SQLiteDatabase db,
@NonNull final DbReader srcReader, @NonNull final DbReader destReader,
+ @NonNull final Context context, final int hotseatSize,
@NonNull final List<DbEntry> placedHotseatItems,
@NonNull final List<DbEntry> itemsToPlace) {
@@ -404,7 +447,7 @@
// to something other than -1.
entry.cellX = i;
entry.cellY = 0;
- insertEntryInDb(helper, entry, srcReader.mTableName, destReader.mTableName);
+ insertEntryInDb(db, context, entry, srcReader.mTableName, destReader.mTableName);
occupied[entry.screenId] = true;
}
}
diff --git a/src/com/android/launcher3/model/LoaderCursor.java b/src/com/android/launcher3/model/LoaderCursor.java
index 2054d93..a5dccc1 100644
--- a/src/com/android/launcher3/model/LoaderCursor.java
+++ b/src/com/android/launcher3/model/LoaderCursor.java
@@ -16,16 +16,16 @@
package com.android.launcher3.model;
-import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
-
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
+import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.CursorWrapper;
+import android.net.Uri;
import android.os.UserHandle;
import android.provider.BaseColumns;
import android.text.TextUtils;
@@ -66,7 +66,9 @@
private final LongSparseArray<UserHandle> allUsers;
private final LauncherAppState mApp;
+ private final Uri mContentUri;
private final Context mContext;
+ private final PackageManager mPM;
private final IconCache mIconCache;
private final InvariantDeviceProfile mIDP;
@@ -106,14 +108,17 @@
public int itemType;
public int restoreFlag;
- public LoaderCursor(Cursor cursor, LauncherAppState app, UserManagerState userManagerState) {
+ public LoaderCursor(Cursor cursor, Uri contentUri, LauncherAppState app,
+ UserManagerState userManagerState) {
super(cursor);
mApp = app;
allUsers = userManagerState.allUsers;
+ mContentUri = contentUri;
mContext = app.getContext();
mIconCache = app.getIconCache();
mIDP = app.getInvariantDeviceProfile();
+ mPM = mContext.getPackageManager();
// Init column indices
mIconIndex = getColumnIndexOrThrow(Favorites.ICON);
@@ -385,7 +390,7 @@
*/
public ContentWriter updater() {
return new ContentWriter(mContext, new ContentWriter.CommitParams(
- mApp.getModel().getModelDbController(),
+ mApp.getModel().getModelDbController().getDatabaseHelper(),
BaseColumns._ID + "= ?", new String[]{Integer.toString(id)}));
}
@@ -404,8 +409,8 @@
public boolean commitDeleted() {
if (mItemsToRemove.size() > 0) {
// Remove dead items
- mApp.getModel().getModelDbController().delete(TABLE_NAME,
- Utilities.createDbSelectionQuery(Favorites._ID, mItemsToRemove), null);
+ mContext.getContentResolver().delete(mContentUri, Utilities.createDbSelectionQuery(
+ Favorites._ID, mItemsToRemove), null);
return true;
}
return false;
@@ -430,8 +435,9 @@
// Update restored items that no longer require special handling
ContentValues values = new ContentValues();
values.put(Favorites.RESTORED, 0);
- mApp.getModel().getModelDbController().update(TABLE_NAME, values,
- Utilities.createDbSelectionQuery(Favorites._ID, mRestoredRows), null);
+ mContext.getContentResolver().update(mContentUri, values,
+ Utilities.createDbSelectionQuery(
+ Favorites._ID, mRestoredRows), null);
}
}
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index d4eded5..9053d19 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -16,7 +16,6 @@
package com.android.launcher3.model;
-import static com.android.launcher3.LauncherSettings.Favorites.TABLE_NAME;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED;
@@ -42,6 +41,7 @@
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.graphics.Point;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Trace;
import android.os.UserHandle;
@@ -50,6 +50,7 @@
import android.util.ArrayMap;
import android.util.Log;
import android.util.LongSparseArray;
+import android.util.TimingLogger;
import androidx.annotation.Nullable;
@@ -199,10 +200,25 @@
}
Object traceToken = TraceHelper.INSTANCE.beginSection(TAG);
+ TimingLogger timingLogger = new TimingLogger(TAG, "run");
LoaderMemoryLogger memoryLogger = new LoaderMemoryLogger();
try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {
List<ShortcutInfo> allShortcuts = new ArrayList<>();
- loadWorkspace(allShortcuts, "", memoryLogger);
+ Trace.beginSection("LoadWorkspace");
+ try {
+ loadWorkspace(allShortcuts, memoryLogger);
+ } finally {
+ Trace.endSection();
+ }
+ logASplit(timingLogger, "loadWorkspace");
+
+ if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
+ verifyNotStopped();
+ mModelDelegate.loadAndBindWorkspaceItems(mUserManagerState,
+ mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
+ mModelDelegate.markActive();
+ logASplit(timingLogger, "workspaceDelegateItems");
+ }
// Sanitize data re-syncs widgets/shortcuts based on the workspace loaded from db.
// sanitizeData should not be invoked if the workspace is loaded from a db different
@@ -212,21 +228,21 @@
verifyNotStopped();
sanitizeFolders(mItemsDeleted);
sanitizeWidgetsShortcutsAndPackages();
- logASplit("sanitizeData");
+ logASplit(timingLogger, "sanitizeData");
}
verifyNotStopped();
mLauncherBinder.bindWorkspace(true /* incrementBindId */, /* isBindSync= */ false);
- logASplit("bindWorkspace");
+ logASplit(timingLogger, "bindWorkspace");
mModelDelegate.workspaceLoadComplete();
// Notify the installer packages of packages with active installs on the first screen.
sendFirstScreenActiveInstallsBroadcast();
- logASplit("sendFirstScreenActiveInstallsBroadcast");
+ logASplit(timingLogger, "sendFirstScreenActiveInstallsBroadcast");
// Take a break
waitForIdle();
- logASplit("step 1 complete");
+ logASplit(timingLogger, "step 1 complete");
verifyNotStopped();
// second step
@@ -237,16 +253,16 @@
} finally {
Trace.endSection();
}
- logASplit("loadAllApps");
+ logASplit(timingLogger, "loadAllApps");
if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
mModelDelegate.loadAndBindAllAppsItems(mUserManagerState,
mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
- logASplit("allAppsDelegateItems");
+ logASplit(timingLogger, "allAppsDelegateItems");
}
verifyNotStopped();
mLauncherBinder.bindAllApps();
- logASplit("bindAllApps");
+ logASplit(timingLogger, "bindAllApps");
verifyNotStopped();
IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler();
@@ -254,73 +270,75 @@
updateHandler.updateIcons(allActivityList,
LauncherActivityCachingLogic.newInstance(mApp.getContext()),
mApp.getModel()::onPackageIconsUpdated);
- logASplit("update icon cache");
+ logASplit(timingLogger, "update icon cache");
verifyNotStopped();
- logASplit("save shortcuts in icon cache");
+ logASplit(timingLogger, "save shortcuts in icon cache");
updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(),
mApp.getModel()::onPackageIconsUpdated);
// Take a break
waitForIdle();
- logASplit("step 2 complete");
+ logASplit(timingLogger, "step 2 complete");
verifyNotStopped();
// third step
List<ShortcutInfo> allDeepShortcuts = loadDeepShortcuts();
- logASplit("loadDeepShortcuts");
+ logASplit(timingLogger, "loadDeepShortcuts");
verifyNotStopped();
mLauncherBinder.bindDeepShortcuts();
- logASplit("bindDeepShortcuts");
+ logASplit(timingLogger, "bindDeepShortcuts");
verifyNotStopped();
- logASplit("save deep shortcuts in icon cache");
+ logASplit(timingLogger, "save deep shortcuts in icon cache");
updateHandler.updateIcons(allDeepShortcuts,
new ShortcutCachingLogic(), (pkgs, user) -> { });
// Take a break
waitForIdle();
- logASplit("step 3 complete");
+ logASplit(timingLogger, "step 3 complete");
verifyNotStopped();
// fourth step
List<ComponentWithLabelAndIcon> allWidgetsList =
mBgDataModel.widgetsModel.update(mApp, null);
- logASplit("load widgets");
+ logASplit(timingLogger, "load widgets");
verifyNotStopped();
mLauncherBinder.bindWidgets();
- logASplit("bindWidgets");
+ logASplit(timingLogger, "bindWidgets");
verifyNotStopped();
if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
mModelDelegate.loadAndBindOtherItems(mLauncherBinder.mCallbacksList);
- logASplit("otherDelegateItems");
+ logASplit(timingLogger, "otherDelegateItems");
verifyNotStopped();
}
updateHandler.updateIcons(allWidgetsList,
new ComponentWithIconCachingLogic(mApp.getContext(), true),
mApp.getModel()::onWidgetLabelsUpdated);
- logASplit("save widgets in icon cache");
+ logASplit(timingLogger, "save widgets in icon cache");
// fifth step
loadFolderNames();
verifyNotStopped();
updateHandler.finish();
- logASplit("finish icon update");
+ logASplit(timingLogger, "finish icon update");
mModelDelegate.modelLoadComplete();
transaction.commit();
memoryLogger.clearLogs();
} catch (CancellationException e) {
// Loader stopped, ignore
- logASplit("Cancelled");
+ logASplit(timingLogger, "Cancelled");
} catch (Exception e) {
memoryLogger.printLogs();
throw e;
+ } finally {
+ timingLogger.dumpToLog();
}
TraceHelper.INSTANCE.endSection(traceToken);
}
@@ -330,29 +348,25 @@
this.notify();
}
- protected void loadWorkspace(
- List<ShortcutInfo> allDeepShortcuts,
- String selection,
- LoaderMemoryLogger memoryLogger) {
- Trace.beginSection("LoadWorkspace");
- try {
- loadWorkspaceImpl(allDeepShortcuts, selection, memoryLogger);
- } finally {
- Trace.endSection();
- }
- logASplit("loadWorkspace");
+ private void loadWorkspace(
+ List<ShortcutInfo> allDeepShortcuts, LoaderMemoryLogger memoryLogger) {
+ loadWorkspace(allDeepShortcuts, Favorites.CONTENT_URI,
+ null /* selection */, memoryLogger);
+ }
+ protected void loadWorkspaceForPreviewSurfaceRenderer(
+ List<ShortcutInfo> allDeepShortcuts, Uri contentUri, String selection) {
+ loadWorkspace(allDeepShortcuts, contentUri, selection, null);
if (FeatureFlags.CHANGE_MODEL_DELEGATE_LOADING_ORDER.get()) {
- verifyNotStopped();
mModelDelegate.loadAndBindWorkspaceItems(mUserManagerState,
mLauncherBinder.mCallbacksList, mShortcutKeyToPinnedShortcuts);
mModelDelegate.markActive();
- logASplit("workspaceDelegateItems");
}
}
- private void loadWorkspaceImpl(
+ protected void loadWorkspace(
List<ShortcutInfo> allDeepShortcuts,
+ Uri contentUri,
String selection,
@Nullable LoaderMemoryLogger memoryLogger) {
final Context context = mApp.getContext();
@@ -363,7 +377,7 @@
final WidgetManagerHelper widgetHelper = new WidgetManagerHelper(context);
boolean clearDb = false;
- if (!mApp.getModel().getModelDbController().migrateGridIfNeeded()) {
+ if (!GridSizeMigrationUtil.migrateGridIfNeeded(context)) {
// Migration failed. Clear workspace.
clearDb = true;
}
@@ -388,9 +402,8 @@
mFirstScreenBroadcast = new FirstScreenBroadcast(installingPkgs);
mShortcutKeyToPinnedShortcuts = new HashMap<>();
- ModelDbController dbController = mApp.getModel().getModelDbController();
final LoaderCursor c = new LoaderCursor(
- dbController.query(TABLE_NAME, null, selection, null, null),
+ contentResolver.query(contentUri, null, selection, null, null), contentUri,
mApp, mUserManagerState);
final Bundle extras = c.getExtras();
mDbName = extras == null ? null : extras.getString(Settings.EXTRA_DB_NAME);
@@ -1099,9 +1112,12 @@
FileLog.d(TAG, widgetDimension.toString());
}
- private static void logASplit(String label) {
- if (DEBUG) {
- Log.d(TAG, label);
+ private static void logASplit(@Nullable TimingLogger timingLogger, String label) {
+ if (timingLogger != null) {
+ timingLogger.addSplit(label);
+ if (DEBUG) {
+ Log.d(TAG, label);
+ }
}
}
}
diff --git a/src/com/android/launcher3/model/ModelDbController.java b/src/com/android/launcher3/model/ModelDbController.java
index 43d8958..97bce8c 100644
--- a/src/com/android/launcher3/model/ModelDbController.java
+++ b/src/com/android/launcher3/model/ModelDbController.java
@@ -19,10 +19,11 @@
import static android.util.Base64.NO_WRAP;
import static com.android.launcher3.DefaultLayoutParser.RES_PARTNER_DEFAULT_LAYOUT;
-import static com.android.launcher3.LauncherSettings.Favorites.addTableToDb;
import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_KEY;
import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_LABEL;
import static com.android.launcher3.LauncherSettings.Settings.LAYOUT_DIGEST_TAG;
+import static com.android.launcher3.model.DatabaseHelper.EMPTY_DATABASE_CREATED;
+import static com.android.launcher3.provider.LauncherDbUtils.copyTable;
import static com.android.launcher3.provider.LauncherDbUtils.tableExists;
import android.app.blob.BlobHandle;
@@ -30,6 +31,7 @@
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
+import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.content.res.Resources;
@@ -41,7 +43,6 @@
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.Process;
-import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
@@ -53,22 +54,18 @@
import com.android.launcher3.AutoInstallsLayout;
import com.android.launcher3.AutoInstallsLayout.SourceResources;
-import com.android.launcher3.ConstantItem;
import com.android.launcher3.DefaultLayoutParser;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherFiles;
import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.Utilities;
-import com.android.launcher3.pm.UserCache;
import com.android.launcher3.provider.LauncherDbUtils;
import com.android.launcher3.provider.LauncherDbUtils.SQLiteTransaction;
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.util.IOUtils;
import com.android.launcher3.util.IntArray;
-import com.android.launcher3.util.MainThreadInitializedObject.SandboxContext;
import com.android.launcher3.util.Partner;
import com.android.launcher3.widget.LauncherWidgetHolder;
@@ -76,6 +73,7 @@
import java.io.InputStream;
import java.io.StringReader;
+import java.util.function.Supplier;
/**
* Utility class which maintains an instance of Launcher database and provides utility methods
@@ -84,8 +82,6 @@
public class ModelDbController {
private static final String TAG = "LauncherProvider";
- private static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED";
-
protected DatabaseHelper mOpenHelper;
private final Context mContext;
@@ -96,36 +92,26 @@
private synchronized void createDbIfNotExists() {
if (mOpenHelper == null) {
- mOpenHelper = createDatabaseHelper(false /* forMigration */);
- RestoreDbTask.restoreIfNeeded(mContext, this);
+ mOpenHelper = DatabaseHelper.createDatabaseHelper(
+ mContext, false /* forMigration */);
+
+ RestoreDbTask.restoreIfNeeded(mContext, mOpenHelper);
}
}
- protected DatabaseHelper createDatabaseHelper(boolean forMigration) {
- boolean isSandbox = mContext instanceof SandboxContext;
- String dbName = isSandbox ? null : InvariantDeviceProfile.INSTANCE.get(mContext).dbFile;
-
- // Set the flag for empty DB
- Runnable onEmptyDbCreateCallback = forMigration ? () -> { }
- : () -> LauncherPrefs.get(mContext).putSync(getEmptyDbCreatedKey(dbName).to(true));
-
- DatabaseHelper databaseHelper = new DatabaseHelper(mContext, dbName,
- this::getSerialNumberForUser, onEmptyDbCreateCallback);
- // Table creation sometimes fails silently, which leads to a crash loop.
- // This way, we will try to create a table every time after crash, so the device
- // would eventually be able to recover.
- if (!tableExists(databaseHelper.getReadableDatabase(), Favorites.TABLE_NAME)) {
- Log.e(TAG, "Tables are missing after onCreate has been called. Trying to recreate");
- // This operation is a no-op if the table already exists.
- addTableToDb(databaseHelper.getWritableDatabase(),
- getSerialNumberForUser(Process.myUserHandle()),
- true /* optional */);
+ private synchronized boolean prepForMigration(String dbFile, String targetTableName,
+ Supplier<DatabaseHelper> src, Supplier<DatabaseHelper> dst) {
+ if (TextUtils.equals(dbFile, mOpenHelper.getDatabaseName())) {
+ Log.e(TAG, "prepForMigration - target db is same as current: " + dbFile);
+ return false;
}
- databaseHelper.mHotseatRestoreTableExists = tableExists(
- databaseHelper.getReadableDatabase(), Favorites.HYBRID_HOTSEAT_BACKUP_TABLE);
- databaseHelper.initIds();
- return databaseHelper;
+ final DatabaseHelper helper = src.get();
+ mOpenHelper = dst.get();
+ copyTable(helper.getReadableDatabase(), Favorites.TABLE_NAME,
+ mOpenHelper.getWritableDatabase(), targetTableName, mContext);
+ helper.close();
+ return true;
}
/**
@@ -281,40 +267,42 @@
}
/**
- * Migrates the DB if needed, and returns false if the migration failed
- * and DB needs to be cleared.
- * @return true if migration was success or ignored, false if migration failed
- * and the DB should be reset.
+ * Updates the current DB and copies all the existing data to the temp table
+ * @param dbFile name of the target db file name
*/
- public boolean migrateGridIfNeeded() {
- InvariantDeviceProfile idp = LauncherAppState.getIDP(mContext);
- if (!GridSizeMigrationUtil.needsToMigrate(mContext, idp)) {
- return true;
- }
- String targetDbName = new DeviceGridState(idp).getDbFile();
- if (TextUtils.equals(targetDbName, mOpenHelper.getDatabaseName())) {
- Log.e(TAG, "migrateGridIfNeeded - target db is same as current: " + targetDbName);
- return false;
- }
- DatabaseHelper oldHelper = mOpenHelper;
- mOpenHelper = (mContext instanceof SandboxContext) ? oldHelper
- : createDatabaseHelper(true /* forMigration */);
- try {
- return GridSizeMigrationUtil.migrateGridIfNeeded(mContext, idp, mOpenHelper,
- oldHelper.getWritableDatabase());
- } finally {
- if (mOpenHelper != oldHelper) {
- oldHelper.close();
- }
- }
+ @WorkerThread
+ public boolean updateCurrentOpenHelper(String dbFile) {
+ createDbIfNotExists();
+ return prepForMigration(
+ dbFile,
+ Favorites.TMP_TABLE,
+ () -> mOpenHelper,
+ () -> DatabaseHelper.createDatabaseHelper(
+ mContext, true /* forMigration */));
}
/**
- * Returns the underlying model database
+ * Returns the current DatabaseHelper.
+ * Only for tests
*/
- public SQLiteDatabase getDb() {
+ @WorkerThread
+ public DatabaseHelper getDatabaseHelper() {
createDbIfNotExists();
- return mOpenHelper.getWritableDatabase();
+ return mOpenHelper;
+ }
+
+ /**
+ * Prepares the DB for preview by copying all existing data to preview table
+ */
+ @WorkerThread
+ public boolean prepareForPreview(String dbFile) {
+ createDbIfNotExists();
+ return prepForMigration(
+ dbFile,
+ Favorites.PREVIEW_TABLE_NAME,
+ () -> DatabaseHelper.createDatabaseHelper(
+ mContext, dbFile, true /* forMigration */),
+ () -> mOpenHelper);
}
private void onAddOrDeleteOp(SQLiteDatabase db) {
@@ -357,7 +345,8 @@
}
private void clearFlagEmptyDbCreated() {
- LauncherPrefs.get(mContext).removeSync(getEmptyDbCreatedKey(mOpenHelper.getDatabaseName()));
+ LauncherPrefs.getPrefs(mContext).edit()
+ .remove(mOpenHelper.getKey(EMPTY_DATABASE_CREATED)).commit();
}
/**
@@ -370,8 +359,9 @@
@WorkerThread
public synchronized void loadDefaultFavoritesIfNecessary() {
createDbIfNotExists();
+ SharedPreferences sp = LauncherPrefs.getPrefs(mContext);
- if (LauncherPrefs.get(mContext).get(getEmptyDbCreatedKey(mOpenHelper.getDatabaseName()))) {
+ if (sp.getBoolean(mOpenHelper.getKey(EMPTY_DATABASE_CREATED), false)) {
Log.d(TAG, "loading default workspace");
LauncherWidgetHolder widgetHolder = mOpenHelper.newLauncherWidgetHolder();
@@ -489,27 +479,4 @@
return new DefaultLayoutParser(mContext, widgetHolder,
mOpenHelper, mContext.getResources(), defaultLayout);
}
-
- /**
- * Re-composite given key in respect to database. If the current db is
- * {@link LauncherFiles#LAUNCHER_DB}, return the key as-is. Otherwise append the db name to
- * given key. e.g. consider key="EMPTY_DATABASE_CREATED", dbName="minimal.db", the returning
- * string will be "EMPTY_DATABASE_CREATED@minimal.db".
- */
- private ConstantItem<Boolean> getEmptyDbCreatedKey(String dbName) {
- if (mContext instanceof SandboxContext) {
- return LauncherPrefs.nonRestorableItem(EMPTY_DATABASE_CREATED,
- false /* default value */, false /* boot aware */);
- }
- String key = TextUtils.equals(dbName, LauncherFiles.LAUNCHER_DB)
- ? EMPTY_DATABASE_CREATED : EMPTY_DATABASE_CREATED + "@" + dbName;
- return LauncherPrefs.backedUpItem(key, false /* default value */, false /* boot aware */);
- }
-
- /**
- * Returns the serial number for the provided user
- */
- public long getSerialNumberForUser(UserHandle user) {
- return UserCache.INSTANCE.get(mContext).getSerialNumberForUser(user);
- }
}
diff --git a/src/com/android/launcher3/provider/LauncherDbUtils.java b/src/com/android/launcher3/provider/LauncherDbUtils.java
index c718dcc..48969fc 100644
--- a/src/com/android/launcher3/provider/LauncherDbUtils.java
+++ b/src/com/android/launcher3/provider/LauncherDbUtils.java
@@ -101,7 +101,7 @@
UserManagerState ums = new UserManagerState();
ums.init(UserCache.INSTANCE.get(context),
context.getSystemService(UserManager.class));
- LoaderCursor lc = new LoaderCursor(c, LauncherAppState.getInstance(context), ums);
+ LoaderCursor lc = new LoaderCursor(c, null, LauncherAppState.getInstance(context), ums);
IntSet deletedShortcuts = new IntSet();
while (lc.moveToNext()) {
diff --git a/src/com/android/launcher3/provider/RestoreDbTask.java b/src/com/android/launcher3/provider/RestoreDbTask.java
index a6e064a..ac72164 100644
--- a/src/com/android/launcher3/provider/RestoreDbTask.java
+++ b/src/com/android/launcher3/provider/RestoreDbTask.java
@@ -16,8 +16,6 @@
package com.android.launcher3.provider;
-import static android.os.Process.myUserHandle;
-
import static com.android.launcher3.InvariantDeviceProfile.TYPE_MULTI_DISPLAY;
import static com.android.launcher3.LauncherPrefs.APP_WIDGET_IDS;
import static com.android.launcher3.LauncherPrefs.OLD_APP_WIDGET_IDS;
@@ -49,8 +47,8 @@
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.Utilities;
import com.android.launcher3.logging.FileLog;
+import com.android.launcher3.model.DatabaseHelper;
import com.android.launcher3.model.DeviceGridState;
-import com.android.launcher3.model.ModelDbController;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -85,12 +83,12 @@
/**
* Tries to restore the backup DB if needed
*/
- public static void restoreIfNeeded(Context context, ModelDbController dbController) {
+ public static void restoreIfNeeded(Context context, DatabaseHelper helper) {
if (!isPending(context)) {
return;
}
- if (!performRestore(context, dbController)) {
- dbController.createEmptyDB();
+ if (!performRestore(context, helper)) {
+ helper.createEmptyDB(helper.getWritableDatabase());
}
// Obtain InvariantDeviceProfile first before setting pending to false, so
@@ -104,12 +102,12 @@
idp.reinitializeAfterRestore(context);
}
- private static boolean performRestore(Context context, ModelDbController controller) {
- SQLiteDatabase db = controller.getDb();
+ private static boolean performRestore(Context context, DatabaseHelper helper) {
+ SQLiteDatabase db = helper.getWritableDatabase();
try (SQLiteTransaction t = new SQLiteTransaction(db)) {
RestoreDbTask task = new RestoreDbTask();
- task.sanitizeDB(context, controller, db, new BackupManager(context));
- task.restoreAppWidgetIdsIfExists(context, controller);
+ task.sanitizeDB(context, helper, db, new BackupManager(context));
+ task.restoreAppWidgetIdsIfExists(context, helper);
t.commit();
return true;
} catch (Exception e) {
@@ -131,10 +129,10 @@
* @return number of items deleted.
*/
@VisibleForTesting
- protected int sanitizeDB(Context context, ModelDbController controller, SQLiteDatabase db,
+ protected int sanitizeDB(Context context, DatabaseHelper helper, SQLiteDatabase db,
BackupManager backupManager) throws Exception {
// Primary user ids
- long myProfileId = controller.getSerialNumberForUser(myUserHandle());
+ long myProfileId = helper.getDefaultUserSerial();
long oldProfileId = getDefaultProfileId(db);
LongSparseArray<Long> oldManagedProfileIds = getManagedProfileIds(db, oldProfileId);
LongSparseArray<Long> profileMapping = new LongSparseArray<>(oldManagedProfileIds.size()
@@ -146,7 +144,7 @@
long oldManagedProfileId = oldManagedProfileIds.keyAt(i);
UserHandle user = getUserForAncestralSerialNumber(backupManager, oldManagedProfileId);
if (user != null) {
- long newManagedProfileId = controller.getSerialNumberForUser(user);
+ long newManagedProfileId = helper.getSerialNumberForUser(user);
profileMapping.put(oldManagedProfileId, newManagedProfileId);
}
}
@@ -215,7 +213,7 @@
}
// Override shortcuts
- maybeOverrideShortcuts(context, controller, db, myProfileId);
+ maybeOverrideShortcuts(context, helper, db, myProfileId);
return itemsDeleted;
}
@@ -323,11 +321,11 @@
.putSync(RESTORE_DEVICE.to(new DeviceGridState(context).getDeviceType()));
}
- private void restoreAppWidgetIdsIfExists(Context context, ModelDbController controller) {
+ private void restoreAppWidgetIdsIfExists(Context context, DatabaseHelper helper) {
LauncherPrefs lp = LauncherPrefs.get(context);
if (lp.has(APP_WIDGET_IDS, OLD_APP_WIDGET_IDS)) {
AppWidgetHost host = new AppWidgetHost(context, APPWIDGET_HOST_ID);
- AppWidgetsRestoredReceiver.restoreAppWidgetIds(context, controller,
+ AppWidgetsRestoredReceiver.restoreAppWidgetIds(context, helper,
IntArray.fromConcatString(lp.get(OLD_APP_WIDGET_IDS)).toArray(),
IntArray.fromConcatString(lp.get(APP_WIDGET_IDS)).toArray(),
host);
@@ -345,7 +343,7 @@
APP_WIDGET_IDS.to(IntArray.wrap(newIds).toConcatString()));
}
- protected static void maybeOverrideShortcuts(Context context, ModelDbController controller,
+ protected static void maybeOverrideShortcuts(Context context, DatabaseHelper helper,
SQLiteDatabase db, long currentUser) {
Map<String, LauncherActivityInfo> activityOverrides = ApiWrapper.getActivityOverrides(
context);
@@ -369,7 +367,7 @@
if (override != null) {
ContentValues values = new ContentValues();
values.put(Favorites.PROFILE_ID,
- controller.getSerialNumberForUser(override.getUser()));
+ helper.getSerialNumberForUser(override.getUser()));
values.put(Favorites.INTENT, AppInfo.makeLaunchIntent(override).toUri(0));
db.update(Favorites.TABLE_NAME, values, String.format("%s=?", Favorites._ID),
new String[]{String.valueOf(c.getInt(idIndex))});
diff --git a/src/com/android/launcher3/util/ContentWriter.java b/src/com/android/launcher3/util/ContentWriter.java
index 7c5ef4d..e509235 100644
--- a/src/com/android/launcher3/util/ContentWriter.java
+++ b/src/com/android/launcher3/util/ContentWriter.java
@@ -26,7 +26,7 @@
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.GraphicsUtils;
-import com.android.launcher3.model.ModelDbController;
+import com.android.launcher3.model.DatabaseHelper;
import com.android.launcher3.pm.UserCache;
/**
@@ -106,7 +106,7 @@
public int commit() {
if (mCommitParams != null) {
- mCommitParams.mDbController.update(
+ mCommitParams.mDatabaseHelper.getWritableDatabase().update(
Favorites.TABLE_NAME, getValues(mContext),
mCommitParams.mWhere, mCommitParams.mSelectionArgs);
}
@@ -115,12 +115,12 @@
public static final class CommitParams {
- final ModelDbController mDbController;
+ final DatabaseHelper mDatabaseHelper;
final String mWhere;
final String[] mSelectionArgs;
- public CommitParams(ModelDbController controller, String where, String[] selectionArgs) {
- mDbController = controller;
+ public CommitParams(DatabaseHelper helper, String where, String[] selectionArgs) {
+ mDatabaseHelper = helper;
mWhere = where;
mSelectionArgs = selectionArgs;
}
diff --git a/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java b/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java
index cea95e5..0a1a9ba 100644
--- a/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java
+++ b/tests/src/com/android/launcher3/model/DbDowngradeHelperTest.java
@@ -39,7 +39,6 @@
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.R;
-import com.android.launcher3.pm.UserCache;
import org.junit.Before;
import org.junit.Test;
@@ -223,9 +222,7 @@
private class MyDatabaseHelper extends DatabaseHelper {
MyDatabaseHelper() {
- super(mContext, DB_FILE,
- UserCache.INSTANCE.get(mContext)::getSerialNumberForUser,
- () -> { });
+ super(mContext, DB_FILE, false);
}
@Override
diff --git a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
index 63dbaa7..f24f0da 100644
--- a/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
+++ b/tests/src/com/android/launcher3/model/GridSizeMigrationUtilTest.kt
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.model
-import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.database.Cursor
@@ -24,7 +23,6 @@
import android.os.Process
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import androidx.test.platform.app.InstrumentationRegistry
import com.android.launcher3.InvariantDeviceProfile
import com.android.launcher3.LauncherPrefs
import com.android.launcher3.LauncherPrefs.Companion.WORKSPACE_SIZE
@@ -33,7 +31,10 @@
import com.android.launcher3.model.GridSizeMigrationUtil.DbReader
import com.android.launcher3.pm.UserCache
import com.android.launcher3.provider.LauncherDbUtils
+import com.android.launcher3.util.LauncherModelHelper
+import com.android.launcher3.util.LauncherModelHelper.*
import com.google.common.truth.Truth.assertThat
+import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -42,12 +43,11 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class GridSizeMigrationUtilTest {
-
+ private lateinit var modelHelper: LauncherModelHelper
private lateinit var context: Context
+ private lateinit var db: SQLiteDatabase
private lateinit var validPackages: Set<String>
private lateinit var idp: InvariantDeviceProfile
- private lateinit var dbHelper: DatabaseHelper
- private lateinit var db: SQLiteDatabase
private val testPackage1 = "com.android.launcher3.validpackage1"
private val testPackage2 = "com.android.launcher3.validpackage2"
private val testPackage3 = "com.android.launcher3.validpackage3"
@@ -61,17 +61,13 @@
@Before
fun setUp() {
- context = InstrumentationRegistry.getInstrumentation().targetContext
- dbHelper =
- DatabaseHelper(
- context,
- null,
- UserCache.INSTANCE.get(context)::getSerialNumberForUser
- ) {}
- db = dbHelper.writableDatabase
+ modelHelper = LauncherModelHelper()
+ context = modelHelper.sandboxContext
+ db = modelHelper.provider.db
validPackages =
setOf(
+ TEST_PACKAGE,
testPackage1,
testPackage2,
testPackage3,
@@ -90,6 +86,11 @@
addTableToDb(db, userSerial, false, TMP_TABLE)
}
+ @After
+ fun tearDown() {
+ modelHelper.destroy()
+ }
+
/**
* Old migration logic, should be modified once [FeatureFlags.ENABLE_NEW_MIGRATION_LOGIC] is not
* needed anymore
@@ -98,26 +99,26 @@
@Throws(Exception::class)
fun testMigration() {
// Src Hotseat icons
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
+ modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI)
+ modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI)
+ modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
// Src grid icons
// _ _ _ _ _
// _ _ _ _ 5
// _ _ 6 _ 7
// _ _ 8 _ 9
// _ _ _ _ _
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 1, testPackage5, 5, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage6, 6, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 2, testPackage7, 7, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 3, testPackage8, 8, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 3, testPackage9, 9, TMP_TABLE)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 1, testPackage5, 5, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage6, 6, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 2, testPackage7, 7, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage8, 8, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 3, testPackage9, 9, TMP_CONTENT_URI)
// Dest hotseat icons
- addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2)
+ modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2)
// Dest grid icons
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage10)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage10)
idp.numDatabaseHotseatIcons = 4
idp.numColumns = 4
@@ -125,7 +126,8 @@
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
GridSizeMigrationUtil.migrate(
- dbHelper,
+ context,
+ db,
srcReader,
destReader,
idp.numDatabaseHotseatIcons,
@@ -136,13 +138,12 @@
// Check hotseat items
var c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(SCREEN, INTENT),
"container=$CONTAINER_HOTSEAT",
null,
SCREEN,
- null,
null
)
?: throw IllegalStateException()
@@ -167,13 +168,12 @@
// Check workspace items
c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(CELLX, CELLY, INTENT),
"container=$CONTAINER_DESKTOP",
null,
null,
- null,
null
)
?: throw IllegalStateException()
@@ -209,30 +209,30 @@
fun testMigrationBackAndForth() {
// Hotseat items in grid A
// 1 2 _ 3 4
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
+ modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI)
+ modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI)
+ modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
// Workspace items in grid A
// _ _ _ _ _
// _ _ _ _ 5
// _ _ 6 _ 7
// _ _ 8 _ _
// _ _ _ _ _
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 1, testPackage5, 5, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage6, 6, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 4, 2, testPackage7, 7, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 3, testPackage8, 8, TMP_TABLE)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 1, testPackage5, 5, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage6, 6, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 4, 2, testPackage7, 7, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage8, 8, TMP_CONTENT_URI)
// Hotseat items in grid B
// 2 _ _ _
- addItem(ITEM_TYPE_SHORTCUT, 0, CONTAINER_HOTSEAT, 0, 0, testPackage2)
+ modelHelper.addItem(SHORTCUT, 0, HOTSEAT, 0, 0, testPackage2)
// Workspace items in grid B
// _ _ _ _
// _ _ _ 10
// _ _ _ _
// _ _ _ _
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 1, 3, testPackage10)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 1, 3, testPackage10)
idp.numDatabaseHotseatIcons = 4
idp.numColumns = 4
@@ -241,7 +241,8 @@
val readerGridB = DbReader(db, TABLE_NAME, context, validPackages)
// migrate from A -> B
GridSizeMigrationUtil.migrate(
- dbHelper,
+ context,
+ db,
readerGridA,
readerGridB,
idp.numDatabaseHotseatIcons,
@@ -252,13 +253,12 @@
// Check hotseat items in grid B
var c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(SCREEN, INTENT),
"container=$CONTAINER_HOTSEAT",
null,
SCREEN,
- null,
null
)
?: throw IllegalStateException()
@@ -272,13 +272,12 @@
// Check workspace items in grid B
c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(SCREEN, CELLX, CELLY, INTENT),
"container=$CONTAINER_DESKTOP",
null,
null,
- null,
null
)
?: throw IllegalStateException()
@@ -295,11 +294,12 @@
assertThat(locMap[testPackage8]).isEqualTo(Triple(0, 3, 1))
// add item in B
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 0, 2, testPackage9)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 0, 2, testPackage9)
// migrate from B -> A
GridSizeMigrationUtil.migrate(
- dbHelper,
+ context,
+ db,
readerGridB,
readerGridA,
5,
@@ -309,13 +309,12 @@
)
// Check hotseat items in grid A
c =
- db.query(
- TMP_TABLE,
+ context.contentResolver.query(
+ TMP_CONTENT_URI,
arrayOf(SCREEN, INTENT),
"container=$CONTAINER_HOTSEAT",
null,
SCREEN,
- null,
null
)
?: throw IllegalStateException()
@@ -329,13 +328,12 @@
// Check workspace items in grid A
c =
- db.query(
- TMP_TABLE,
+ context.contentResolver.query(
+ TMP_CONTENT_URI,
arrayOf(SCREEN, CELLX, CELLY, INTENT),
"container=$CONTAINER_DESKTOP",
null,
null,
- null,
null
)
?: throw IllegalStateException()
@@ -356,11 +354,12 @@
assertThat(locMap[testPackage9]).isEqualTo(Triple(0, 0, 2))
// remove item from B
- db.delete(TMP_TABLE, "$_ID=7", null)
+ modelHelper.deleteItem(7, TMP_TABLE)
// migrate from A -> B
GridSizeMigrationUtil.migrate(
- dbHelper,
+ context,
+ db,
readerGridA,
readerGridB,
idp.numDatabaseHotseatIcons,
@@ -371,13 +370,12 @@
// Check hotseat items in grid B
c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(SCREEN, INTENT),
"container=$CONTAINER_HOTSEAT",
null,
SCREEN,
- null,
null
)
?: throw IllegalStateException()
@@ -391,13 +389,12 @@
// Check workspace items in grid B
c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(SCREEN, CELLX, CELLY, INTENT),
"container=$CONTAINER_DESKTOP",
null,
null,
- null,
null
)
?: throw IllegalStateException()
@@ -446,28 +443,10 @@
fun migrateToLargerHotseat() {
val srcHotseatItems =
intArrayOf(
- addItem(
- ITEM_TYPE_APPLICATION,
- 0,
- CONTAINER_HOTSEAT,
- 0,
- 0,
- testPackage1,
- 1,
- TMP_TABLE
- ),
- addItem(ITEM_TYPE_SHORTCUT, 1, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE),
- addItem(
- ITEM_TYPE_APPLICATION,
- 2,
- CONTAINER_HOTSEAT,
- 0,
- 0,
- testPackage3,
- 3,
- TMP_TABLE
- ),
- addItem(ITEM_TYPE_SHORTCUT, 3, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
+ modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI),
+ modelHelper.addItem(SHORTCUT, 1, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI),
+ modelHelper.addItem(APP_ICON, 2, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI),
+ modelHelper.addItem(SHORTCUT, 3, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
)
val numSrcDatabaseHotseatIcons = srcHotseatItems.size
idp.numDatabaseHotseatIcons = 6
@@ -476,7 +455,8 @@
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
GridSizeMigrationUtil.migrate(
- dbHelper,
+ context,
+ db,
srcReader,
destReader,
idp.numDatabaseHotseatIcons,
@@ -487,13 +467,12 @@
// Check hotseat items
val c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(SCREEN, INTENT),
"container=$CONTAINER_HOTSEAT",
null,
SCREEN,
- null,
null
)
?: throw IllegalStateException()
@@ -522,11 +501,11 @@
@Test
fun migrateFromLargerHotseat() {
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_HOTSEAT, 0, 0, testPackage1, 1, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 2, CONTAINER_HOTSEAT, 0, 0, testPackage2, 2, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 3, CONTAINER_HOTSEAT, 0, 0, testPackage3, 3, TMP_TABLE)
- addItem(ITEM_TYPE_SHORTCUT, 4, CONTAINER_HOTSEAT, 0, 0, testPackage4, 4, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 5, CONTAINER_HOTSEAT, 0, 0, testPackage5, 5, TMP_TABLE)
+ modelHelper.addItem(APP_ICON, 0, HOTSEAT, 0, 0, testPackage1, 1, TMP_CONTENT_URI)
+ modelHelper.addItem(SHORTCUT, 2, HOTSEAT, 0, 0, testPackage2, 2, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 3, HOTSEAT, 0, 0, testPackage3, 3, TMP_CONTENT_URI)
+ modelHelper.addItem(SHORTCUT, 4, HOTSEAT, 0, 0, testPackage4, 4, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 5, HOTSEAT, 0, 0, testPackage5, 5, TMP_CONTENT_URI)
idp.numDatabaseHotseatIcons = 4
idp.numColumns = 4
@@ -534,7 +513,8 @@
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
GridSizeMigrationUtil.migrate(
- dbHelper,
+ context,
+ db,
srcReader,
destReader,
idp.numDatabaseHotseatIcons,
@@ -545,13 +525,12 @@
// Check hotseat items
val c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(SCREEN, INTENT),
"container=$CONTAINER_HOTSEAT",
null,
SCREEN,
- null,
null
)
?: throw IllegalStateException()
@@ -589,11 +568,11 @@
enableNewMigrationLogic("4,4")
// Setup src grid
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 2, testPackage1, 5, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 2, 3, testPackage2, 6, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 3, 1, testPackage3, 7, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 3, 2, testPackage4, 8, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 2, CONTAINER_DESKTOP, 3, 3, testPackage5, 9, TMP_TABLE)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 2, testPackage1, 5, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 2, 3, testPackage2, 6, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 1, DESKTOP, 3, 1, testPackage3, 7, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 1, DESKTOP, 3, 2, testPackage4, 8, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 2, DESKTOP, 3, 3, testPackage5, 9, TMP_CONTENT_URI)
idp.numDatabaseHotseatIcons = 4
idp.numColumns = 6
@@ -602,7 +581,8 @@
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
GridSizeMigrationUtil.migrate(
- dbHelper,
+ context,
+ db,
srcReader,
destReader,
idp.numDatabaseHotseatIcons,
@@ -613,13 +593,12 @@
// Get workspace items
val c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(INTENT, SCREEN),
"container=$CONTAINER_DESKTOP",
null,
null,
- null,
null
)
?: throw IllegalStateException()
@@ -651,11 +630,11 @@
enableNewMigrationLogic("2,2")
// Setup src grid
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 0, 1, testPackage1, 5, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 1, 1, testPackage2, 6, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 0, 0, testPackage3, 7, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 1, 0, testPackage4, 8, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 2, CONTAINER_DESKTOP, 0, 0, testPackage5, 9, TMP_TABLE)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 0, 1, testPackage1, 5, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 1, 1, testPackage2, 6, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 1, DESKTOP, 0, 0, testPackage3, 7, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 1, DESKTOP, 1, 0, testPackage4, 8, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 2, DESKTOP, 0, 0, testPackage5, 9, TMP_CONTENT_URI)
idp.numDatabaseHotseatIcons = 4
idp.numColumns = 5
@@ -663,7 +642,8 @@
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
GridSizeMigrationUtil.migrate(
- dbHelper,
+ context,
+ db,
srcReader,
destReader,
idp.numDatabaseHotseatIcons,
@@ -674,13 +654,12 @@
// Get workspace items
val c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(INTENT, SCREEN),
"container=$CONTAINER_DESKTOP",
null,
null,
- null,
null
)
?: throw IllegalStateException()
@@ -712,11 +691,11 @@
enableNewMigrationLogic("5,5")
// Setup src grid
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 0, 1, testPackage1, 5, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 0, CONTAINER_DESKTOP, 1, 1, testPackage2, 6, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 0, 0, testPackage3, 7, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 1, CONTAINER_DESKTOP, 1, 0, testPackage4, 8, TMP_TABLE)
- addItem(ITEM_TYPE_APPLICATION, 2, CONTAINER_DESKTOP, 0, 0, testPackage5, 9, TMP_TABLE)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 0, 1, testPackage1, 5, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 0, DESKTOP, 1, 1, testPackage2, 6, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 1, DESKTOP, 0, 0, testPackage3, 7, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 1, DESKTOP, 1, 0, testPackage4, 8, TMP_CONTENT_URI)
+ modelHelper.addItem(APP_ICON, 2, DESKTOP, 0, 0, testPackage5, 9, TMP_CONTENT_URI)
idp.numDatabaseHotseatIcons = 4
idp.numColumns = 4
@@ -724,7 +703,8 @@
val srcReader = DbReader(db, TMP_TABLE, context, validPackages)
val destReader = DbReader(db, TABLE_NAME, context, validPackages)
GridSizeMigrationUtil.migrate(
- dbHelper,
+ context,
+ db,
srcReader,
destReader,
idp.numDatabaseHotseatIcons,
@@ -735,13 +715,12 @@
// Get workspace items
val c =
- db.query(
- TABLE_NAME,
+ context.contentResolver.query(
+ CONTENT_URI,
arrayOf(INTENT, SCREEN),
"container=$CONTAINER_DESKTOP",
null,
null,
- null,
null
)
?: throw IllegalStateException()
@@ -768,48 +747,4 @@
private fun enableNewMigrationLogic(srcGridSize: String) {
LauncherPrefs.get(context).putSync(WORKSPACE_SIZE.to(srcGridSize))
}
-
- private fun addItem(
- type: Int,
- screen: Int,
- container: Int,
- x: Int,
- y: Int,
- packageName: String?
- ): Int {
- return addItem(
- type,
- screen,
- container,
- x,
- y,
- packageName,
- dbHelper.generateNewItemId(),
- TABLE_NAME
- )
- }
-
- private fun addItem(
- type: Int,
- screen: Int,
- container: Int,
- x: Int,
- y: Int,
- packageName: String?,
- id: Int,
- tableName: String
- ): Int {
- val values = ContentValues()
- values.put(_ID, id)
- values.put(CONTAINER, container)
- values.put(SCREEN, screen)
- values.put(CELLX, x)
- values.put(CELLY, y)
- values.put(SPANX, 1)
- values.put(SPANY, 1)
- values.put(ITEM_TYPE, type)
- values.put(INTENT, Intent(Intent.ACTION_MAIN).setPackage(packageName).toUri(0))
- db.insert(tableName, null, values)
- return id
- }
}
diff --git a/tests/src/com/android/launcher3/model/LoaderCursorTest.java b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
index 78812c0..d192be4 100644
--- a/tests/src/com/android/launcher3/model/LoaderCursorTest.java
+++ b/tests/src/com/android/launcher3/model/LoaderCursorTest.java
@@ -59,6 +59,7 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
+import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.util.Executors;
@@ -101,7 +102,7 @@
});
UserManagerState ums = new UserManagerState();
- mLoaderCursor = new LoaderCursor(mCursor, mApp, ums);
+ mLoaderCursor = new LoaderCursor(mCursor, Favorites.CONTENT_URI, mApp, ums);
ums.allUsers.put(0, Process.myUserHandle());
}
diff --git a/tests/src/com/android/launcher3/provider/LauncherDbUtilsTest.java b/tests/src/com/android/launcher3/provider/LauncherDbUtilsTest.java
index 54b8489..2b6f9ff 100644
--- a/tests/src/com/android/launcher3/provider/LauncherDbUtilsTest.java
+++ b/tests/src/com/android/launcher3/provider/LauncherDbUtilsTest.java
@@ -45,7 +45,6 @@
import com.android.launcher3.R;
import com.android.launcher3.model.DatabaseHelper;
import com.android.launcher3.model.DbDowngradeHelper;
-import com.android.launcher3.pm.UserCache;
import com.android.launcher3.settings.SettingsActivity;
import com.android.launcher3.shortcuts.ShortcutKey;
import com.android.launcher3.util.IOUtils;
@@ -166,11 +165,12 @@
private class MyDatabaseHelper extends DatabaseHelper {
MyDatabaseHelper() {
- super(mContext, null, UserCache.INSTANCE.get(mContext)::getSerialNumberForUser,
- () -> { });
+ super(mContext, null, false);
}
@Override
protected void handleOneTimeDataUpgrade(SQLiteDatabase db) { }
+
+ protected void onEmptyDbCreated() { }
}
}
diff --git a/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java b/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
index 1b1b294..67de1f5 100644
--- a/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
+++ b/tests/src/com/android/launcher3/provider/RestoreDbTaskTest.java
@@ -46,7 +46,6 @@
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.model.DatabaseHelper;
-import com.android.launcher3.model.ModelDbController;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -64,13 +63,13 @@
@Test
public void testGetProfileId() throws Exception {
- SQLiteDatabase db = new MyModelDbController(23).getDb();
+ SQLiteDatabase db = new MyDatabaseHelper(23).getWritableDatabase();
assertEquals(23, new RestoreDbTask().getDefaultProfileId(db));
}
@Test
public void testMigrateProfileId() throws Exception {
- SQLiteDatabase db = new MyModelDbController(42).getDb();
+ SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase();
// Add some mock data
for (int i = 0; i < 5; i++) {
ContentValues values = new ContentValues();
@@ -90,7 +89,7 @@
@Test
public void testChangeDefaultColumn() throws Exception {
- SQLiteDatabase db = new MyModelDbController(42).getDb();
+ SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase();
// Add some mock data
for (int i = 0; i < 5; i++) {
ContentValues values = new ContentValues();
@@ -121,20 +120,20 @@
long workProfileId = myProfileId + 2;
long workProfileId_old = myProfileId + 3;
- MyModelDbController controller = new MyModelDbController(myProfileId);
- SQLiteDatabase db = controller.getDb();
+ MyDatabaseHelper helper = new MyDatabaseHelper(myProfileId);
+ SQLiteDatabase db = helper.getWritableDatabase();
BackupManager bm = spy(new BackupManager(context));
doReturn(myUserHandle()).when(bm).getUserForAncestralSerialNumber(eq(myProfileId_old));
doReturn(mWorkUser).when(bm).getUserForAncestralSerialNumber(eq(workProfileId_old));
- controller.users.put(workProfileId, mWorkUser);
+ helper.users.put(workProfileId, mWorkUser);
- addIconsBulk(controller, 10, 1, myProfileId_old);
- addIconsBulk(controller, 6, 2, workProfileId_old);
+ addIconsBulk(helper, 10, 1, myProfileId_old);
+ addIconsBulk(helper, 6, 2, workProfileId_old);
assertEquals(10, getItemCountForProfile(db, myProfileId_old));
assertEquals(6, getItemCountForProfile(db, workProfileId_old));
RestoreDbTask task = new RestoreDbTask();
- task.sanitizeDB(context, controller, controller.getDb(), bm);
+ task.sanitizeDB(context, helper, helper.getWritableDatabase(), bm);
// All the data has been migrated to the new user ids
assertEquals(0, getItemCountForProfile(db, myProfileId_old));
@@ -152,20 +151,20 @@
long myProfileId_old = myProfileId + 1;
long workProfileId_old = myProfileId + 3;
- MyModelDbController controller = new MyModelDbController(myProfileId);
- SQLiteDatabase db = controller.getDb();
+ MyDatabaseHelper helper = new MyDatabaseHelper(myProfileId);
+ SQLiteDatabase db = helper.getWritableDatabase();
BackupManager bm = spy(new BackupManager(context));
doReturn(myUserHandle()).when(bm).getUserForAncestralSerialNumber(eq(myProfileId_old));
// Work profile is not migrated
doReturn(null).when(bm).getUserForAncestralSerialNumber(eq(workProfileId_old));
- addIconsBulk(controller, 10, 1, myProfileId_old);
- addIconsBulk(controller, 6, 2, workProfileId_old);
+ addIconsBulk(helper, 10, 1, myProfileId_old);
+ addIconsBulk(helper, 6, 2, workProfileId_old);
assertEquals(10, getItemCountForProfile(db, myProfileId_old));
assertEquals(6, getItemCountForProfile(db, workProfileId_old));
RestoreDbTask task = new RestoreDbTask();
- task.sanitizeDB(context, controller, controller.getDb(), bm);
+ task.sanitizeDB(context, helper, helper.getWritableDatabase(), bm);
// All the data has been migrated to the new user ids
assertEquals(0, getItemCountForProfile(db, myProfileId_old));
@@ -174,13 +173,12 @@
assertEquals(10, getCount(db, "select * from favorites"));
}
- private void addIconsBulk(MyModelDbController controller,
- int count, int screen, long profileId) {
+ private void addIconsBulk(DatabaseHelper helper, int count, int screen, long profileId) {
int columns = LauncherAppState.getIDP(getInstrumentation().getTargetContext()).numColumns;
String packageName = getInstrumentation().getContext().getPackageName();
for (int i = 0; i < count; i++) {
ContentValues values = new ContentValues();
- values.put(LauncherSettings.Favorites._ID, controller.generateNewItemId());
+ values.put(LauncherSettings.Favorites._ID, helper.generateNewItemId());
values.put(LauncherSettings.Favorites.CONTAINER, CONTAINER_DESKTOP);
values.put(LauncherSettings.Favorites.SCREEN, screen);
values.put(LauncherSettings.Favorites.CELLX, i % columns);
@@ -191,11 +189,11 @@
values.put(LauncherSettings.Favorites.ITEM_TYPE, ITEM_TYPE_APPLICATION);
values.put(LauncherSettings.Favorites.INTENT,
new Intent(Intent.ACTION_MAIN).setPackage(packageName).toUri(0));
-
- controller.insert(TABLE_NAME, values);
+ helper.getWritableDatabase().insert(TABLE_NAME, null, values);
}
}
+
@Test
public void testRemoveScreenIdGaps_firstScreenEmpty() {
runRemoveScreenIdGapsTest(
@@ -218,7 +216,7 @@
}
private void runRemoveScreenIdGapsTest(int[] screenIds, int[] expectedScreenIds) {
- SQLiteDatabase db = new MyModelDbController(42).getDb();
+ SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase();
// Add some mock data
for (int i = 0; i < screenIds.length; i++) {
ContentValues values = new ContentValues();
@@ -256,15 +254,14 @@
}
}
- private class MyModelDbController extends ModelDbController {
+ private class MyDatabaseHelper extends DatabaseHelper {
- public final LongSparseArray<UserHandle> users = new LongSparseArray<>();
+ public final LongSparseArray<UserHandle> users;
- MyModelDbController(long profileId) {
- super(getInstrumentation().getTargetContext());
+ MyDatabaseHelper(long profileId) {
+ super(getInstrumentation().getTargetContext(), null, false);
+ users = new LongSparseArray<>();
users.put(profileId, myUserHandle());
- mOpenHelper = new DatabaseHelper(getInstrumentation().getTargetContext(), null,
- this::getSerialNumberForUser, () -> { });
}
@Override
@@ -272,5 +269,10 @@
int index = users.indexOfValue(user);
return index >= 0 ? users.keyAt(index) : -1;
}
+
+ @Override
+ protected void handleOneTimeDataUpgrade(SQLiteDatabase db) { }
+
+ protected void onEmptyDbCreated() { }
}
}
diff --git a/tests/src/com/android/launcher3/util/LauncherModelHelper.java b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
index 6fca965..bf31e39 100644
--- a/tests/src/com/android/launcher3/util/LauncherModelHelper.java
+++ b/tests/src/com/android/launcher3/util/LauncherModelHelper.java
@@ -363,6 +363,12 @@
sandboxContext.getContentResolver().insert(contentUri, values);
}
+ public void deleteItem(int itemId, @NonNull final String tableName) {
+ final Uri uri = Uri.parse("content://"
+ + LauncherProvider.AUTHORITY + "/" + tableName + "/" + itemId);
+ sandboxContext.getContentResolver().delete(uri, null, null);
+ }
+
/**
* Sets up a mock provider to load the provided layout by default, next time the layout loads
*/
@@ -420,7 +426,7 @@
}
public SQLiteDatabase getDb() {
- return getModelDbController().getDb();
+ return getModelDbController().getDatabaseHelper().getWritableDatabase();
}
}