summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/launcher3')
-rw-r--r--src/com/android/launcher3/Alarm.java4
-rw-r--r--src/com/android/launcher3/AppsCustomizePagedView.java14
-rw-r--r--src/com/android/launcher3/AppsCustomizeTabHost.java2
-rw-r--r--src/com/android/launcher3/BuildInfo.java32
-rw-r--r--src/com/android/launcher3/Cling.java79
-rw-r--r--src/com/android/launcher3/DeleteDropTarget.java10
-rw-r--r--src/com/android/launcher3/DeviceProfile.java10
-rw-r--r--src/com/android/launcher3/DragLayer.java3
-rw-r--r--src/com/android/launcher3/DynamicGrid.java2
-rw-r--r--src/com/android/launcher3/Folder.java19
-rw-r--r--src/com/android/launcher3/Hotseat.java8
-rw-r--r--src/com/android/launcher3/InstallShortcutReceiver.java2
-rw-r--r--src/com/android/launcher3/Launcher.java446
-rw-r--r--src/com/android/launcher3/LauncherAppState.java10
-rw-r--r--src/com/android/launcher3/LauncherBackupHelper.java4
-rw-r--r--src/com/android/launcher3/LauncherClings.java444
-rw-r--r--src/com/android/launcher3/LauncherModel.java47
-rw-r--r--src/com/android/launcher3/LauncherProvider.java226
-rw-r--r--src/com/android/launcher3/OnAlarmListener.java5
-rw-r--r--src/com/android/launcher3/WallpaperChangedReceiver.java1
-rw-r--r--src/com/android/launcher3/Workspace.java4
21 files changed, 1000 insertions, 372 deletions
diff --git a/src/com/android/launcher3/Alarm.java b/src/com/android/launcher3/Alarm.java
index 91f9bd091..e9f1fd963 100644
--- a/src/com/android/launcher3/Alarm.java
+++ b/src/com/android/launcher3/Alarm.java
@@ -78,7 +78,3 @@ public class Alarm implements Runnable{
return mAlarmPending;
}
}
-
-interface OnAlarmListener {
- public void onAlarm(Alarm alarm);
-}
diff --git a/src/com/android/launcher3/AppsCustomizePagedView.java b/src/com/android/launcher3/AppsCustomizePagedView.java
index 2865bc5d5..37cdb9e13 100644
--- a/src/com/android/launcher3/AppsCustomizePagedView.java
+++ b/src/com/android/launcher3/AppsCustomizePagedView.java
@@ -199,8 +199,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
private AccelerateInterpolator mAlphaInterpolator = new AccelerateInterpolator(0.9f);
private DecelerateInterpolator mLeftScreenAlphaInterpolator = new DecelerateInterpolator(4);
- public static boolean DISABLE_ALL_APPS = false;
-
// Previews & outlines
ArrayList<AppsCustomizeAsyncTask> mRunningTasks;
private static final int sPageSleepDelay = 200;
@@ -427,7 +425,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if (!isDataReady()) {
- if ((DISABLE_ALL_APPS || !mApps.isEmpty()) && !mWidgets.isEmpty()) {
+ if ((LauncherAppState.isDisableAllApps() || !mApps.isEmpty()) && !mWidgets.isEmpty()) {
setDataIsReady();
setMeasuredDimension(width, height);
onDataReady(width, height);
@@ -1558,7 +1556,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
public void setApps(ArrayList<AppInfo> list) {
- if (!DISABLE_ALL_APPS) {
+ if (!LauncherAppState.isDisableAllApps()) {
mApps = list;
Collections.sort(mApps, LauncherModel.getAppNameComparator());
updatePageCountsAndInvalidateData();
@@ -1576,7 +1574,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
}
public void addApps(ArrayList<AppInfo> list) {
- if (!DISABLE_ALL_APPS) {
+ if (!LauncherAppState.isDisableAllApps()) {
addAppsWithoutInvalidate(list);
updatePageCountsAndInvalidateData();
}
@@ -1604,7 +1602,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
}
public void removeApps(ArrayList<AppInfo> appInfos) {
- if (!DISABLE_ALL_APPS) {
+ if (!LauncherAppState.isDisableAllApps()) {
removeAppsWithoutInvalidate(appInfos);
updatePageCountsAndInvalidateData();
}
@@ -1613,7 +1611,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
// We remove and re-add the updated applications list because it's properties may have
// changed (ie. the title), and this will ensure that the items will be in their proper
// place in the list.
- if (!DISABLE_ALL_APPS) {
+ if (!LauncherAppState.isDisableAllApps()) {
removeAppsWithoutInvalidate(list);
addAppsWithoutInvalidate(list);
updatePageCountsAndInvalidateData();
@@ -1727,4 +1725,4 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
return String.format(getContext().getString(stringId), page + 1, count);
}
-}
+} \ No newline at end of file
diff --git a/src/com/android/launcher3/AppsCustomizeTabHost.java b/src/com/android/launcher3/AppsCustomizeTabHost.java
index 697bd7ecf..bb7f045ce 100644
--- a/src/com/android/launcher3/AppsCustomizeTabHost.java
+++ b/src/com/android/launcher3/AppsCustomizeTabHost.java
@@ -407,7 +407,7 @@ public class AppsCustomizeTabHost extends TabHost implements LauncherTransitiona
}
// Dismiss the workspace cling
- l.dismissWorkspaceCling(null);
+ l.getLauncherClings().dismissWorkspaceCling(null);
}
@Override
diff --git a/src/com/android/launcher3/BuildInfo.java b/src/com/android/launcher3/BuildInfo.java
new file mode 100644
index 000000000..b49ee0d9b
--- /dev/null
+++ b/src/com/android/launcher3/BuildInfo.java
@@ -0,0 +1,32 @@
+package com.android.launcher3;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+public class BuildInfo {
+ private static final boolean DBG = false;
+ private static final String TAG = "BuildInfo";
+
+ public boolean isDogfoodBuild() {
+ return false;
+ }
+
+ public static BuildInfo loadByName(String className) {
+ if (TextUtils.isEmpty(className)) return new BuildInfo();
+
+ if (DBG) Log.d(TAG, "Loading BuildInfo: " + className);
+ try {
+ Class<?> cls = Class.forName(className);
+ return (BuildInfo) cls.newInstance();
+ } catch (ClassNotFoundException e) {
+ Log.e(TAG, "Bad BuildInfo class", e);
+ } catch (InstantiationException e) {
+ Log.e(TAG, "Bad BuildInfo class", e);
+ } catch (IllegalAccessException e) {
+ Log.e(TAG, "Bad BuildInfo class", e);
+ } catch (ClassCastException e) {
+ Log.e(TAG, "Bad BuildInfo class", e);
+ }
+ return new BuildInfo();
+ }
+}
diff --git a/src/com/android/launcher3/Cling.java b/src/com/android/launcher3/Cling.java
index 3af427139..185b49b08 100644
--- a/src/com/android/launcher3/Cling.java
+++ b/src/com/android/launcher3/Cling.java
@@ -37,10 +37,6 @@ import android.widget.TextView;
public class Cling extends FrameLayout implements Insettable, View.OnClickListener,
View.OnLongClickListener, View.OnTouchListener {
- static final String FIRST_RUN_CLING_DISMISSED_KEY = "cling_gel.first_run.dismissed";
- static final String WORKSPACE_CLING_DISMISSED_KEY = "cling_gel.workspace.dismissed";
- static final String FOLDER_CLING_DISMISSED_KEY = "cling_gel.folder.dismissed";
-
private static String FIRST_RUN_PORTRAIT = "first_run_portrait";
private static String FIRST_RUN_LANDSCAPE = "first_run_landscape";
@@ -49,6 +45,12 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
private static String WORKSPACE_LARGE = "workspace_large";
private static String WORKSPACE_CUSTOM = "workspace_custom";
+ private static String MIGRATION_PORTRAIT = "migration_portrait";
+ private static String MIGRATION_LANDSCAPE = "migration_landscape";
+
+ private static String MIGRATION_WORKSPACE_PORTRAIT = "migration_workspace_portrait";
+ private static String MIGRATION_WORKSPACE_LANDSCAPE = "migration_workspace_landscape";
+
private static String FOLDER_PORTRAIT = "folder_portrait";
private static String FOLDER_LANDSCAPE = "folder_landscape";
private static String FOLDER_LARGE = "folder_large";
@@ -57,6 +59,8 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
private static float WORKSPACE_INNER_CIRCLE_RADIUS_DPS = 50;
private static float WORKSPACE_OUTER_CIRCLE_RADIUS_DPS = 60;
private static float WORKSPACE_CIRCLE_Y_OFFSET_DPS = 30;
+ private static float MIGRATION_WORKSPACE_INNER_CIRCLE_RADIUS_DPS = 42;
+ private static float MIGRATION_WORKSPACE_OUTER_CIRCLE_RADIUS_DPS = 46;
private Launcher mLauncher;
private boolean mIsInitialized;
@@ -70,6 +74,7 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
private Rect mFocusedHotseatAppBounds;
private Paint mErasePaint;
+ private Paint mBorderPaint;
private Paint mBubblePaint;
private Paint mDotPaint;
@@ -112,6 +117,10 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
mErasePaint.setAlpha(0);
mErasePaint.setAntiAlias(true);
+ mBorderPaint = new Paint();
+ mBorderPaint.setColor(0xFFFFFFFF);
+ mBorderPaint.setAntiAlias(true);
+
int circleColor = getResources().getColor(
R.color.first_run_cling_circle_background_color);
mBubblePaint = new Paint();
@@ -166,13 +175,30 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
}
}
+ void updateMigrationWorkspaceBubblePosition() {
+ DisplayMetrics metrics = new DisplayMetrics();
+ mLauncher.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+
+ // Get the page indicator bounds
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ Rect pageIndicatorBounds = grid.getWorkspacePageIndicatorBounds(mInsets);
+
+ View bubble = findViewById(R.id.migration_workspace_cling_bubble);
+ FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) bubble.getLayoutParams();
+ lp.bottomMargin = grid.heightPx - pageIndicatorBounds.top;
+ bubble.requestLayout();
+ }
+
void show(boolean animate, int duration) {
setVisibility(View.VISIBLE);
setLayerType(View.LAYER_TYPE_HARDWARE, null);
if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
mDrawIdentifier.equals(WORKSPACE_LARGE) ||
- mDrawIdentifier.equals(WORKSPACE_CUSTOM)) {
+ mDrawIdentifier.equals(WORKSPACE_CUSTOM) ||
+ mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) ||
+ mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) {
View content = getContent();
content.setAlpha(0f);
content.animate()
@@ -218,7 +244,9 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
void hide(final int duration, final Runnable postCb) {
if (mDrawIdentifier.equals(FIRST_RUN_PORTRAIT) ||
- mDrawIdentifier.equals(FIRST_RUN_LANDSCAPE)) {
+ mDrawIdentifier.equals(FIRST_RUN_LANDSCAPE) ||
+ mDrawIdentifier.equals(MIGRATION_PORTRAIT) ||
+ mDrawIdentifier.equals(MIGRATION_LANDSCAPE)) {
View content = getContent();
content.animate()
.alpha(0f)
@@ -340,7 +368,7 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
intent.setComponent(mFocusedHotseatAppComponent);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
mLauncher.startActivity(intent, null);
- mLauncher.dismissWorkspaceCling(this);
+ mLauncher.getLauncherClings().dismissWorkspaceCling(this);
}
}
}
@@ -350,7 +378,11 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
mDrawIdentifier.equals(WORKSPACE_LARGE)) {
- mLauncher.dismissWorkspaceCling(null);
+ mLauncher.getLauncherClings().dismissWorkspaceCling(null);
+ return true;
+ } else if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) ||
+ mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) {
+ mLauncher.getLauncherClings().dismissMigrationWorkspaceCling(null);
return true;
}
return false;
@@ -361,6 +393,11 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
if (mIsInitialized) {
canvas.save();
+ // Get the page indicator bounds
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ Rect pageIndicatorBounds = grid.getWorkspacePageIndicatorBounds(mInsets);
+
// Get the background override if there is one
if (mBackground == null) {
if (mDrawIdentifier.equals(WORKSPACE_CUSTOM)) {
@@ -378,7 +415,9 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
mBackground.draw(canvas);
} else if (mDrawIdentifier.equals(WORKSPACE_PORTRAIT) ||
mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
- mDrawIdentifier.equals(WORKSPACE_LARGE)) {
+ mDrawIdentifier.equals(WORKSPACE_LARGE) ||
+ mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) ||
+ mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) {
// Initialize the draw buffer (to allow punching through)
eraseBg = Bitmap.createBitmap(getMeasuredWidth(), getMeasuredHeight(),
Bitmap.Config.ARGB_8888);
@@ -412,11 +451,13 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
mDrawIdentifier.equals(WORKSPACE_LANDSCAPE) ||
mDrawIdentifier.equals(WORKSPACE_LARGE)) {
int offset = DynamicGrid.pxFromDp(WORKSPACE_CIRCLE_Y_OFFSET_DPS, metrics);
- mErasePaint.setAlpha((int) (128));
+ // Draw the outer circle
+ mErasePaint.setAlpha(128);
eraseCanvas.drawCircle(metrics.widthPixels / 2,
metrics.heightPixels / 2 - offset,
DynamicGrid.pxFromDp(WORKSPACE_OUTER_CIRCLE_RADIUS_DPS, metrics),
mErasePaint);
+ // Draw the inner circle
mErasePaint.setAlpha(0);
eraseCanvas.drawCircle(metrics.widthPixels / 2,
metrics.heightPixels / 2 - offset,
@@ -434,8 +475,24 @@ public class Cling extends FrameLayout implements Insettable, View.OnClickListen
mFocusedHotseatApp.setAlpha((int) (255 * alpha));
mFocusedHotseatApp.draw(canvas);
}
+ } else if (mDrawIdentifier.equals(MIGRATION_WORKSPACE_PORTRAIT) ||
+ mDrawIdentifier.equals(MIGRATION_WORKSPACE_LANDSCAPE)) {
+ int offset = DynamicGrid.pxFromDp(WORKSPACE_CIRCLE_Y_OFFSET_DPS, metrics);
+ // Draw the outer circle
+ eraseCanvas.drawCircle(pageIndicatorBounds.centerX(),
+ pageIndicatorBounds.centerY(),
+ DynamicGrid.pxFromDp(MIGRATION_WORKSPACE_OUTER_CIRCLE_RADIUS_DPS, metrics),
+ mBorderPaint);
+ // Draw the inner circle
+ mErasePaint.setAlpha(0);
+ eraseCanvas.drawCircle(pageIndicatorBounds.centerX(),
+ pageIndicatorBounds.centerY(),
+ DynamicGrid.pxFromDp(MIGRATION_WORKSPACE_INNER_CIRCLE_RADIUS_DPS, metrics),
+ mErasePaint);
+ canvas.drawBitmap(eraseBg, 0, 0, null);
+ eraseCanvas.setBitmap(null);
+ eraseBg = null;
}
-
canvas.restore();
}
diff --git a/src/com/android/launcher3/DeleteDropTarget.java b/src/com/android/launcher3/DeleteDropTarget.java
index c76425a5e..75d906bc2 100644
--- a/src/com/android/launcher3/DeleteDropTarget.java
+++ b/src/com/android/launcher3/DeleteDropTarget.java
@@ -146,12 +146,12 @@ public class DeleteDropTarget extends ButtonDropTarget {
return true;
}
- if (!AppsCustomizePagedView.DISABLE_ALL_APPS &&
+ if (!LauncherAppState.isDisableAllApps() &&
item.itemType == LauncherSettings.Favorites.ITEM_TYPE_FOLDER) {
return true;
}
- if (!AppsCustomizePagedView.DISABLE_ALL_APPS &&
+ if (!LauncherAppState.isDisableAllApps() &&
item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
item instanceof AppInfo) {
AppInfo appInfo = (AppInfo) info;
@@ -160,7 +160,7 @@ public class DeleteDropTarget extends ButtonDropTarget {
if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
item instanceof ShortcutInfo) {
- if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+ if (LauncherAppState.isDisableAllApps()) {
ShortcutInfo shortcutInfo = (ShortcutInfo) info;
return (shortcutInfo.flags & AppInfo.DOWNLOADED_FLAG) != 0;
} else {
@@ -174,7 +174,7 @@ public class DeleteDropTarget extends ButtonDropTarget {
@Override
public void onDragStart(DragSource source, Object info, int dragAction) {
boolean isVisible = true;
- boolean useUninstallLabel = !AppsCustomizePagedView.DISABLE_ALL_APPS &&
+ boolean useUninstallLabel = !LauncherAppState.isDisableAllApps() &&
isAllAppsApplication(source, info);
boolean useDeleteLabel = !useUninstallLabel && source.supportsDeleteDropTarget();
@@ -264,7 +264,7 @@ public class DeleteDropTarget extends ButtonDropTarget {
}
private boolean isUninstallFromWorkspace(DragObject d) {
- if (AppsCustomizePagedView.DISABLE_ALL_APPS && isWorkspaceOrFolderApplication(d)) {
+ if (LauncherAppState.isDisableAllApps() && isWorkspaceOrFolderApplication(d)) {
ShortcutInfo shortcut = (ShortcutInfo) d.dragInfo;
// Only allow manifest shortcuts to initiate an un-install.
return !InstallShortcutReceiver.isValidShortcutLaunchIntent(shortcut.intent);
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 67b0933c9..a64d5e403 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -126,7 +126,7 @@ public class DeviceProfile {
DeviceProfile(String n, float w, float h, float r, float c,
float is, float its, float hs, float his) {
// Ensure that we have an odd number of hotseat items (since we need to place all apps)
- if (!AppsCustomizePagedView.DISABLE_ALL_APPS && hs % 2 == 0) {
+ if (!LauncherAppState.isDisableAllApps() && hs % 2 == 0) {
throw new RuntimeException("All Device Profiles must have an odd number of hotseat spaces");
}
@@ -475,6 +475,14 @@ public class DeviceProfile {
return bounds;
}
+ /** Returns the bounds of the workspace page indicators. */
+ Rect getWorkspacePageIndicatorBounds(Rect insets) {
+ Rect workspacePadding = getWorkspacePadding();
+ int pageIndicatorTop = heightPx - insets.bottom - workspacePadding.bottom;
+ return new Rect(workspacePadding.left, pageIndicatorTop,
+ widthPx - workspacePadding.right, pageIndicatorTop + pageIndicatorHeightPx);
+ }
+
/** Returns the workspace padding in the specified orientation */
Rect getWorkspacePadding() {
return getWorkspacePadding(isLandscape ? CellLayout.LANDSCAPE : CellLayout.PORTRAIT);
diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java
index 8726f30c1..ab0469d53 100644
--- a/src/com/android/launcher3/DragLayer.java
+++ b/src/com/android/launcher3/DragLayer.java
@@ -168,7 +168,8 @@ public class DragLayer extends FrameLayout implements ViewGroup.OnHierarchyChang
}
Folder currentFolder = mLauncher.getWorkspace().getOpenFolder();
- if (currentFolder != null && !mLauncher.isFolderClingVisible() && intercept) {
+ if (currentFolder != null && !mLauncher.getLauncherClings().isFolderClingVisible() &&
+ intercept) {
if (currentFolder.isEditingName()) {
if (!isEventOverFolderTextRegion(currentFolder, ev)) {
currentFolder.dismissEditingName();
diff --git a/src/com/android/launcher3/DynamicGrid.java b/src/com/android/launcher3/DynamicGrid.java
index 22928ccf3..3aced1fae 100644
--- a/src/com/android/launcher3/DynamicGrid.java
+++ b/src/com/android/launcher3/DynamicGrid.java
@@ -56,7 +56,7 @@ public class DynamicGrid {
DisplayMetrics dm = resources.getDisplayMetrics();
ArrayList<DeviceProfile> deviceProfiles =
new ArrayList<DeviceProfile>();
- boolean hasAA = !AppsCustomizePagedView.DISABLE_ALL_APPS;
+ boolean hasAA = !LauncherAppState.isDisableAllApps();
DEFAULT_ICON_SIZE_PX = pxFromDp(DEFAULT_ICON_SIZE_DP, dm);
// Our phone profiles include the bar sizes in each orientation
deviceProfiles.add(new DeviceProfile("Super Short Stubby",
diff --git a/src/com/android/launcher3/Folder.java b/src/com/android/launcher3/Folder.java
index ca82bd1a7..a9134e105 100644
--- a/src/com/android/launcher3/Folder.java
+++ b/src/com/android/launcher3/Folder.java
@@ -146,7 +146,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
Resources res = getResources();
mMaxCountX = (int) grid.numColumns;
// Allow scrolling folders when DISABLE_ALL_APPS is true.
- if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+ if (LauncherAppState.isDisableAllApps()) {
mMaxCountY = mMaxNumItems = Integer.MAX_VALUE;
} else {
mMaxCountY = (int) grid.numRows;
@@ -238,7 +238,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
return false;
}
- mLauncher.dismissFolderCling(null);
+ mLauncher.getLauncherClings().dismissFolderCling(null);
mLauncher.getWorkspace().onDragStartedWithItem(v);
mLauncher.getWorkspace().beginDragShared(v, this);
@@ -466,7 +466,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
public void onAnimationEnd(Animator animation) {
mState = STATE_OPEN;
setLayerType(LAYER_TYPE_NONE, null);
- Cling cling = mLauncher.showFirstRunFoldersCling();
+ Cling cling = mLauncher.getLauncherClings().showFoldersCling();
if (cling != null) {
cling.bringScrimToFront();
bringToFront();
@@ -773,7 +773,11 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
}
completeDragExit();
}
- } else {
+ }
+
+ // This is kind of hacky, but in general, dropping on the workspace handles removing
+ // the extra screen, but dropping elsewhere (back to self, or onto delete) doesn't.
+ if (target != mLauncher.getWorkspace()) {
mLauncher.getWorkspace().removeExtraEmptyScreen(true, null);
}
@@ -1014,7 +1018,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
int contentAreaHeightSpec = MeasureSpec.makeMeasureSpec(getContentAreaHeight(),
MeasureSpec.EXACTLY);
- if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+ if (LauncherAppState.isDisableAllApps()) {
// Don't cap the height of the content to allow scrolling.
mContent.setFixedSize(getContentAreaWidth(), mContent.getDesiredHeight());
} else {
@@ -1103,7 +1107,10 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList
if (getItemCount() <= 1) {
// Remove the folder
LauncherModel.deleteItemFromDatabase(mLauncher, mInfo);
- cellLayout.removeView(mFolderIcon);
+ if (cellLayout != null) {
+ // b/12446428 -- sometimes the cell layout has already gone away?
+ cellLayout.removeView(mFolderIcon);
+ }
if (mFolderIcon instanceof DropTarget) {
mDragController.removeDropTarget((DropTarget) mFolderIcon);
}
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 094e188c7..59d60e381 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -95,7 +95,7 @@ public class Hotseat extends FrameLayout {
return hasVerticalHotseat() ? (mContent.getCountY() - (rank + 1)) : 0;
}
public boolean isAllAppsButtonRank(int rank) {
- if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+ if (LauncherAppState.isDisableAllApps()) {
return false;
} else {
return rank == mAllAppsButtonRank;
@@ -142,7 +142,7 @@ public class Hotseat extends FrameLayout {
void resetLayout() {
mContent.removeAllViewsInLayout();
- if (!AppsCustomizePagedView.DISABLE_ALL_APPS) {
+ if (!LauncherAppState.isDisableAllApps()) {
// Add the Apps button
Context context = getContext();
@@ -189,7 +189,7 @@ public class Hotseat extends FrameLayout {
void addAllAppsFolder(IconCache iconCache,
ArrayList<AppInfo> allApps, ArrayList<ComponentName> onWorkspace,
Launcher launcher, Workspace workspace) {
- if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+ if (LauncherAppState.isDisableAllApps()) {
FolderInfo fi = new FolderInfo();
fi.cellX = getCellXFromOrder(mAllAppsButtonRank);
@@ -219,7 +219,7 @@ public class Hotseat extends FrameLayout {
}
void addAppsToAllAppsFolder(ArrayList<AppInfo> apps) {
- if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+ if (LauncherAppState.isDisableAllApps()) {
View v = mContent.getChildAt(getCellXFromOrder(mAllAppsButtonRank), getCellYFromOrder(mAllAppsButtonRank));
FolderIcon fi = null;
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index 1ff94720b..7ab4e0477 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -272,7 +272,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
final Intent intent = pendingInfo.launchIntent;
final String name = pendingInfo.name;
- if (AppsCustomizePagedView.DISABLE_ALL_APPS && !isValidShortcutLaunchIntent(intent)) {
+ if (LauncherAppState.isDisableAllApps() && !isValidShortcutLaunchIntent(intent)) {
if (DBG) Log.d(TAG, "Ignoring shortcut with launchIntent:" + intent);
continue;
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index c05769cfa..765fca499 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -17,8 +17,6 @@
package com.android.launcher3;
-import android.accounts.Account;
-import android.accounts.AccountManager;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@@ -87,7 +85,6 @@ import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.inputmethod.InputMethodManager;
@@ -115,6 +112,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
+
/**
* Default launcher application.
*/
@@ -130,6 +128,8 @@ public class Launcher extends Activity
static final boolean DEBUG_RESUME_TIME = false;
static final boolean DEBUG_DUMP_LOG = false;
+ static final boolean ENABLE_DEBUG_INTENTS = false; // allow DebugIntents to run
+
private static final int REQUEST_CREATE_SHORTCUT = 1;
private static final int REQUEST_CREATE_APPWIDGET = 5;
private static final int REQUEST_PICK_APPLICATION = 6;
@@ -155,6 +155,7 @@ public class Launcher extends Activity
// adb shell setprop log.tag.PROPERTY_NAME [VERBOSE | SUPPRESS]
static final String FORCE_ENABLE_ROTATION_PROPERTY = "launcher_force_rotate";
static final String DUMP_STATE_PROPERTY = "launcher_dump_state";
+ static final String DISABLE_ALL_APPS_PROPERTY = "launcher_noallapps";
// The Intent extra that defines whether to ignore the launch animation
static final String INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION =
@@ -187,6 +188,9 @@ public class Launcher extends Activity
// Type: int[]
private static final String RUNTIME_STATE_VIEW_IDS = "launcher.view_ids";
+
+ static final String FIRST_RUN_ACTIVITY_DISPLAYED = "launcher.first_run_activity_displayed";
+
private static final String TOOLBAR_ICON_METADATA_NAME = "com.android.launcher.toolbar_icon";
private static final String TOOLBAR_SEARCH_ICON_METADATA_NAME =
"com.android.launcher.toolbar_search_icon";
@@ -196,6 +200,8 @@ public class Launcher extends Activity
public static final String SHOW_WEIGHT_WATCHER = "debug.show_mem";
public static final boolean SHOW_WEIGHT_WATCHER_DEFAULT = false;
+ public static final String USER_HAS_MIGRATED = "launcher.user_migrated_from_old_data";
+
/** The different states that Launcher can be in. */
private enum State { NONE, WORKSPACE, APPS_CUSTOMIZE, APPS_CUSTOMIZE_SPRING_LOADED };
private State mState = State.WORKSPACE;
@@ -204,8 +210,6 @@ public class Launcher extends Activity
static final int APPWIDGET_HOST_ID = 1024;
public static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 300;
private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500;
- private static final int SHOW_CLING_DURATION = 250;
- private static final int DISMISS_CLING_DURATION = 200;
private static final Object sLock = new Object();
private static int sScreen = DEFAULT_SCREEN;
@@ -226,9 +230,11 @@ public class Launcher extends Activity
private Workspace mWorkspace;
private View mLauncherView;
+ private View mPageIndicators;
private DragLayer mDragLayer;
private DragController mDragController;
private View mWeightWatcher;
+ private LauncherClings mLauncherClings;
private AppWidgetManager mAppWidgetManager;
private LauncherAppWidgetHost mAppWidgetHost;
@@ -281,8 +287,6 @@ public class Launcher extends Activity
private boolean mVisible = false;
private boolean mHasFocus = false;
private boolean mAttached = false;
- private static final boolean DISABLE_CLINGS = false;
- private static final boolean DISABLE_CUSTOM_CLINGS = true;
private static LocaleConfiguration sLocaleConfiguration = null;
@@ -338,9 +342,6 @@ public class Launcher extends Activity
private BubbleTextView mWaitingForResume;
- private HideFromAccessibilityHelper mHideFromAccessibilityHelper
- = new HideFromAccessibilityHelper();
-
private Runnable mBuildLayersRunnable = new Runnable() {
public void run() {
if (mWorkspace != null) {
@@ -365,7 +366,7 @@ public class Launcher extends Activity
private Stats mStats;
- private static boolean isPropertyEnabled(String propertyName) {
+ static boolean isPropertyEnabled(String propertyName) {
return Log.isLoggable(propertyName, Log.VERBOSE);
}
@@ -415,6 +416,7 @@ public class Launcher extends Activity
mIconCache = app.getIconCache();
mIconCache.flushInvalidIcons(grid);
mDragController = new DragController(this);
+ mLauncherClings = new LauncherClings(this);
mInflater = getLayoutInflater();
mStats = new Stats(this);
@@ -476,7 +478,12 @@ public class Launcher extends Activity
// On large interfaces, we want the screen to auto-rotate based on the current orientation
unlockScreenOrientation(true);
- showFirstRunCling();
+ showFirstRunActivity();
+ if (mModel.canMigrateFromOldLauncherDb()) {
+ mLauncherClings.showMigrationCling();
+ } else {
+ mLauncherClings.showFirstRunCling();
+ }
}
protected void onUserLeaveHint() {
@@ -498,6 +505,21 @@ public class Launcher extends Activity
}
/**
+ * To be overridden by subclasses to indicate that there is an activity to launch
+ * before showing the standard launcher experience.
+ */
+ protected boolean hasFirstRunActivity() {
+ return false;
+ }
+
+ /**
+ * To be overridden by subclasses to launch any first run activity
+ */
+ protected Intent getFirstRunActivity() {
+ return null;
+ }
+
+ /**
* Invoked by subclasses to signal a change to the {@link #addCustomContentToLeft} value to
* ensure the custom content page is added or removed if necessary.
*/
@@ -654,10 +676,6 @@ public class Launcher extends Activity
return mInflater;
}
- public DragLayer getDragLayer() {
- return mDragLayer;
- }
-
boolean isDraggingEnabled() {
// We prevent dragging when we are loading the workspace as it is possible to pick up a view
// that is subsequently removed from the workspace in startBinding().
@@ -1208,6 +1226,7 @@ public class Launcher extends Activity
mLauncherView = findViewById(R.id.launcher);
mDragLayer = (DragLayer) findViewById(R.id.drag_layer);
mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace);
+ mPageIndicators = mDragLayer.findViewById(R.id.page_indicator);
mLauncherView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
@@ -1551,6 +1570,15 @@ public class Launcher extends Activity
} else if (Intent.ACTION_USER_PRESENT.equals(action)) {
mUserPresent = true;
updateRunning();
+ } else if (ENABLE_DEBUG_INTENTS && DebugIntents.DELETE_DATABASE.equals(action)) {
+ mModel.resetLoadedState(false, true);
+ mModel.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
+ LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE);
+ } else if (ENABLE_DEBUG_INTENTS && DebugIntents.MIGRATE_DATABASE.equals(action)) {
+ mModel.resetLoadedState(false, true);
+ mModel.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
+ LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE
+ | LauncherModel.LOADER_FLAG_MIGRATE_SHORTCUTS);
}
}
};
@@ -1563,6 +1591,10 @@ public class Launcher extends Activity
final IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);
+ if (ENABLE_DEBUG_INTENTS) {
+ filter.addAction(DebugIntents.DELETE_DATABASE);
+ filter.addAction(DebugIntents.MIGRATE_DATABASE);
+ }
registerReceiver(mReceiver, filter);
FirstFrameAnimatorHelper.initializeDrawListener(getWindow().getDecorView());
mAttached = true;
@@ -1702,6 +1734,26 @@ public class Launcher extends Activity
Toast.makeText(this, getString(strId), Toast.LENGTH_SHORT).show();
}
+ public DragLayer getDragLayer() {
+ return mDragLayer;
+ }
+
+ public Workspace getWorkspace() {
+ return mWorkspace;
+ }
+
+ public Hotseat getHotseat() {
+ return mHotseat;
+ }
+
+ public View getOverviewPanel() {
+ return mOverviewPanel;
+ }
+
+ public SearchDropTargetBar getSearchBar() {
+ return mSearchDropTargetBar;
+ }
+
public LauncherAppWidgetHost getAppWidgetHost() {
return mAppWidgetHost;
}
@@ -1710,6 +1762,14 @@ public class Launcher extends Activity
return mModel;
}
+ public LauncherClings getLauncherClings() {
+ return mLauncherClings;
+ }
+
+ protected SharedPreferences getSharedPrefs() {
+ return mSharedPrefs;
+ }
+
public void closeSystemDialogs() {
getWindow().closeAllPanels();
@@ -2671,7 +2731,7 @@ public class Launcher extends Activity
closeFolder(folder);
// Dismiss the folder cling
- dismissFolderCling(null);
+ mLauncherClings.dismissFolderCling(null);
}
}
@@ -2747,15 +2807,6 @@ public class Launcher extends Activity
return mHotseat != null && layout != null &&
(layout instanceof CellLayout) && (layout == mHotseat.getLayout());
}
- Hotseat getHotseat() {
- return mHotseat;
- }
- View getOverviewPanel() {
- return mOverviewPanel;
- }
- SearchDropTargetBar getSearchBar() {
- return mSearchDropTargetBar;
- }
/**
* Returns the CellLayout of the specified container at the specified screen.
@@ -2772,10 +2823,6 @@ public class Launcher extends Activity
}
}
- Workspace getWorkspace() {
- return mWorkspace;
- }
-
public boolean isAllAppsVisible() {
return (mState == State.APPS_CUSTOMIZE) || (mOnResumeState == State.APPS_CUSTOMIZE);
}
@@ -2906,7 +2953,7 @@ public class Launcher extends Activity
// Shrink workspaces away if going to AppsCustomize from workspace
Animator workspaceAnim =
mWorkspace.getChangeStateAnimation(Workspace.State.SMALL, animated);
- if (!AppsCustomizePagedView.DISABLE_ALL_APPS
+ if (!LauncherAppState.isDisableAllApps()
|| contentType == AppsCustomizePagedView.ContentType.Widgets) {
// Set the content type for the all apps/widgets space
mAppsCustomizeTabHost.setContentTypeImmediate(contentType);
@@ -3777,7 +3824,7 @@ public class Launcher extends Activity
// Remove the extra empty screen
mWorkspace.removeExtraEmptyScreen(false, null);
- if (!AppsCustomizePagedView.DISABLE_ALL_APPS &&
+ if (!LauncherAppState.isDisableAllApps() &&
addedApps != null && mAppsCustomizeContent != null) {
mAppsCustomizeContent.addApps(addedApps);
}
@@ -4044,7 +4091,7 @@ public class Launcher extends Activity
* Implementation of the method from LauncherModel.Callbacks.
*/
public void bindAllApplications(final ArrayList<AppInfo> apps) {
- if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+ if (LauncherAppState.isDisableAllApps()) {
if (mIntentsOnWorkspaceFromUpgradePath != null) {
if (LauncherModel.UPGRADE_USE_MORE_APPS_FOLDER) {
getHotseat().addAllAppsFolder(mIconCache, apps,
@@ -4084,7 +4131,7 @@ public class Launcher extends Activity
mWorkspace.updateShortcuts(apps);
}
- if (!AppsCustomizePagedView.DISABLE_ALL_APPS &&
+ if (!LauncherAppState.isDisableAllApps() &&
mAppsCustomizeContent != null) {
mAppsCustomizeContent.updateApps(apps);
}
@@ -4121,7 +4168,7 @@ public class Launcher extends Activity
mDragController.onAppsRemoved(packageNames, appInfos);
// Update AllApps
- if (!AppsCustomizePagedView.DISABLE_ALL_APPS &&
+ if (!LauncherAppState.isDisableAllApps() &&
mAppsCustomizeContent != null) {
mAppsCustomizeContent.removeApps(appInfos);
}
@@ -4206,228 +4253,13 @@ public class Launcher extends Activity
}
}
- /* Cling related */
- private boolean isClingsEnabled() {
- if (DISABLE_CLINGS) {
- return false;
- }
-
- // For now, limit only to phones
- LauncherAppState app = LauncherAppState.getInstance();
- DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- if (grid.isTablet()) {
- return false;
- }
- if (grid.isLandscape) {
- return false;
- }
-
- // disable clings when running in a test harness
- if(ActivityManager.isRunningInTestHarness()) return false;
-
- // Disable clings for accessibility when explore by touch is enabled
- final AccessibilityManager a11yManager = (AccessibilityManager) getSystemService(
- ACCESSIBILITY_SERVICE);
- if (a11yManager.isTouchExplorationEnabled()) {
- return false;
- }
-
- // Restricted secondary users (child mode) will potentially have very few apps
- // seeded when they start up for the first time. Clings won't work well with that
-// boolean supportsLimitedUsers =
-// android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
-// Account[] accounts = AccountManager.get(this).getAccounts();
-// if (supportsLimitedUsers && accounts.length == 0) {
-// UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
-// Bundle restrictions = um.getUserRestrictions();
-// if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
-// return false;
-// }
-// }
- return true;
- }
-
- private Cling initCling(int clingId, int scrimId, boolean animate,
- boolean dimNavBarVisibilty) {
- Cling cling = (Cling) findViewById(clingId);
- View scrim = null;
- if (scrimId > 0) {
- scrim = findViewById(R.id.cling_scrim);
- }
- if (cling != null) {
- cling.init(this, scrim);
- cling.show(animate, SHOW_CLING_DURATION);
-
- if (dimNavBarVisibilty) {
- cling.setSystemUiVisibility(cling.getSystemUiVisibility() |
- View.SYSTEM_UI_FLAG_LOW_PROFILE);
- }
- }
- return cling;
- }
-
- private void dismissCling(final Cling cling, final Runnable postAnimationCb,
- final String flag, int duration, boolean restoreNavBarVisibilty) {
- // To catch cases where siblings of top-level views are made invisible, just check whether
- // the cling is directly set to GONE before dismissing it.
- if (cling != null && cling.getVisibility() != View.GONE) {
- final Runnable cleanUpClingCb = new Runnable() {
- public void run() {
- cling.cleanup();
- // We should update the shared preferences on a background thread
- new AsyncTask<Void, Void, Void>() {
- public Void doInBackground(Void ... args) {
- SharedPreferences.Editor editor = mSharedPrefs.edit();
- editor.putBoolean(flag, true);
- editor.commit();
- return null;
- }
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
- if (postAnimationCb != null) {
- postAnimationCb.run();
- }
- }
- };
- if (duration <= 0) {
- cleanUpClingCb.run();
- } else {
- cling.hide(duration, cleanUpClingCb);
- }
- mHideFromAccessibilityHelper.restoreImportantForAccessibility(mDragLayer);
-
- if (restoreNavBarVisibilty) {
- cling.setSystemUiVisibility(cling.getSystemUiVisibility() &
- ~View.SYSTEM_UI_FLAG_LOW_PROFILE);
- }
- }
- }
-
- private void removeCling(int id) {
- final View cling = findViewById(id);
- if (cling != null) {
- final ViewGroup parent = (ViewGroup) cling.getParent();
- parent.post(new Runnable() {
- @Override
- public void run() {
- parent.removeView(cling);
- }
- });
- mHideFromAccessibilityHelper.restoreImportantForAccessibility(mDragLayer);
- }
- }
-
- private boolean skipCustomClingIfNoAccounts() {
- Cling cling = (Cling) findViewById(R.id.workspace_cling);
- boolean customCling = cling.getDrawIdentifier().equals("workspace_custom");
- if (customCling) {
- AccountManager am = AccountManager.get(this);
- if (am == null) return false;
- Account[] accounts = am.getAccountsByType("com.google");
- return accounts.length == 0;
- }
- return false;
- }
-
- public void updateCustomContentHintVisibility() {
- Cling cling = (Cling) findViewById(R.id.first_run_cling);
- String ccHintStr = getFirstRunCustomContentHint();
-
- if (mWorkspace.hasCustomContent()) {
- // Show the custom content hint if ccHintStr is not empty
- if (cling != null) {
- setCustomContentHintVisibility(cling, ccHintStr, true, true);
- }
- } else {
- // Hide the custom content hint
- if (cling != null) {
- setCustomContentHintVisibility(cling, ccHintStr, false, true);
- }
- }
- }
-
- private void setCustomContentHintVisibility(Cling cling, String ccHintStr, boolean visible,
- boolean animate) {
- final TextView ccHint = (TextView) cling.findViewById(R.id.custom_content_hint);
- if (ccHint != null) {
- if (visible && !ccHintStr.isEmpty()) {
- ccHint.setText(ccHintStr);
- ccHint.setVisibility(View.VISIBLE);
- if (animate) {
- ccHint.setAlpha(0f);
- ccHint.animate().alpha(1f)
- .setDuration(SHOW_CLING_DURATION)
- .start();
- } else {
- ccHint.setAlpha(1f);
- }
- } else {
- if (animate) {
- ccHint.animate().alpha(0f)
- .setDuration(SHOW_CLING_DURATION)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- ccHint.setVisibility(View.GONE);
- }
- })
- .start();
- } else {
- ccHint.setAlpha(0f);
- ccHint.setVisibility(View.GONE);
- }
- }
- }
- }
-
- public void showFirstRunCling() {
- if (isClingsEnabled() &&
- !mSharedPrefs.getBoolean(Cling.FIRST_RUN_CLING_DISMISSED_KEY, false) &&
- !skipCustomClingIfNoAccounts() ) {
- // If we're not using the default workspace layout, replace workspace cling
- // with a custom workspace cling (usually specified in an overlay)
- // For now, only do this on tablets
- if (!DISABLE_CUSTOM_CLINGS) {
- if (mSharedPrefs.getInt(LauncherProvider.DEFAULT_WORKSPACE_RESOURCE_ID, 0) != 0 &&
- getResources().getBoolean(R.bool.config_useCustomClings)) {
- // Use a custom cling
- View cling = findViewById(R.id.workspace_cling);
- ViewGroup clingParent = (ViewGroup) cling.getParent();
- int clingIndex = clingParent.indexOfChild(cling);
- clingParent.removeViewAt(clingIndex);
- View customCling = mInflater.inflate(R.layout.custom_workspace_cling, clingParent, false);
- clingParent.addView(customCling, clingIndex);
- customCling.setId(R.id.workspace_cling);
- }
- }
- Cling cling = (Cling) findViewById(R.id.first_run_cling);
- if (cling != null) {
- String sbHintStr = getFirstRunClingSearchBarHint();
- String ccHintStr = getFirstRunCustomContentHint();
- if (!sbHintStr.isEmpty()) {
- TextView sbHint = (TextView) cling.findViewById(R.id.search_bar_hint);
- sbHint.setText(sbHintStr);
- sbHint.setVisibility(View.VISIBLE);
- }
- setCustomContentHintVisibility(cling, ccHintStr, true, false);
- }
- initCling(R.id.first_run_cling, 0, false, true);
- } else {
- removeCling(R.id.first_run_cling);
- }
- }
-
/**
* Called when the SearchBar hint should be changed.
*
* @param hint the hint to be displayed in the search bar.
*/
protected void onSearchBarHintChanged(String hint) {
- Cling cling = (Cling) findViewById(R.id.first_run_cling);
- if (cling != null && cling.getVisibility() == View.VISIBLE && !hint.isEmpty()) {
- TextView sbHint = (TextView) cling.findViewById(R.id.search_bar_hint);
- sbHint.setText(hint);
- sbHint.setVisibility(View.VISIBLE);
- }
+ mLauncherClings.updateSearchBarHint(hint);
}
protected String getFirstRunClingSearchBarHint() {
@@ -4452,80 +4284,61 @@ public class Launcher extends Activity
return "";
}
- public void showFirstRunWorkspaceCling() {
- // Enable the clings only if they have not been dismissed before
- if (isClingsEnabled() &&
- !mSharedPrefs.getBoolean(Cling.WORKSPACE_CLING_DISMISSED_KEY, false)) {
- Cling c = initCling(R.id.workspace_cling, 0, false, true);
-
- // Set the focused hotseat app if there is one
- c.setFocusedHotseatApp(getFirstRunFocusedHotseatAppDrawableId(),
- getFirstRunFocusedHotseatAppRank(),
- getFirstRunFocusedHotseatAppComponentName(),
- getFirstRunFocusedHotseatAppBubbleTitle(),
- getFirstRunFocusedHotseatAppBubbleDescription());
- } else {
- removeCling(R.id.workspace_cling);
- }
+ public void dismissFirstRunCling(View v) {
+ mLauncherClings.dismissFirstRunCling(v);
}
- public Cling showFirstRunFoldersCling() {
- // Enable the clings only if they have not been dismissed before
- if (isClingsEnabled() &&
- !mSharedPrefs.getBoolean(Cling.FOLDER_CLING_DISMISSED_KEY, false)) {
- Cling cling = initCling(R.id.folder_cling, R.id.cling_scrim,
- true, true);
- return cling;
- } else {
- removeCling(R.id.folder_cling);
- return null;
- }
+ public void dismissMigrationClingCopyApps(View v) {
+ mLauncherClings.dismissMigrationClingCopyApps(v);
}
- protected SharedPreferences getSharedPrefs() {
- return mSharedPrefs;
+ public void dismissMigrationClingUseDefault(View v) {
+ mLauncherClings.dismissMigrationClingUseDefault(v);
}
- public boolean isFolderClingVisible() {
- Cling cling = (Cling) findViewById(R.id.folder_cling);
- if (cling != null) {
- return cling.getVisibility() == View.VISIBLE;
- }
- return false;
+ public void dismissMigrationWorkspaceCling(View v) {
+ mLauncherClings.dismissMigrationWorkspaceCling(v);
+ }
+ public void dismissWorkspaceCling(View v) {
+ mLauncherClings.dismissWorkspaceCling(v);
+ }
+ public void dismissFolderCling(View v) {
+ mLauncherClings.dismissFolderCling(v);
}
- public void dismissFirstRunCling(View v) {
- Cling cling = (Cling) findViewById(R.id.first_run_cling);
- Runnable cb = new Runnable() {
- public void run() {
- // Show the workspace cling next
- showFirstRunWorkspaceCling();
- }
- };
- dismissCling(cling, cb, Cling.FIRST_RUN_CLING_DISMISSED_KEY,
- DISMISS_CLING_DURATION, false);
- // Fade out the search bar for the workspace cling coming up
- mSearchDropTargetBar.hideSearchBar(true);
+ private boolean shouldRunFirstRunActivity() {
+ return !ActivityManager.isRunningInTestHarness();
}
- public void dismissWorkspaceCling(View v) {
- Cling cling = (Cling) findViewById(R.id.workspace_cling);
- Runnable cb = null;
- if (v == null) {
- cb = new Runnable() {
- public void run() {
- mWorkspace.enterOverviewMode();
- }
- };
+
+ public void showFirstRunActivity() {
+ if (shouldRunFirstRunActivity() && hasFirstRunActivity()
+ && !mSharedPrefs.getBoolean(FIRST_RUN_ACTIVITY_DISPLAYED, false)) {
+ Intent firstRunIntent = getFirstRunActivity();
+ if (firstRunIntent != null) {
+ startActivity(firstRunIntent);
+ markFirstRunActivityShown();
+ }
}
- dismissCling(cling, cb, Cling.WORKSPACE_CLING_DISMISSED_KEY,
- DISMISS_CLING_DURATION, true);
+ }
- // Fade in the search bar
- mSearchDropTargetBar.showSearchBar(true);
+ private void markFirstRunActivityShown() {
+ SharedPreferences.Editor editor = mSharedPrefs.edit();
+ editor.putBoolean(FIRST_RUN_ACTIVITY_DISPLAYED, true);
+ editor.apply();
}
- public void dismissFolderCling(View v) {
- Cling cling = (Cling) findViewById(R.id.folder_cling);
- dismissCling(cling, null, Cling.FOLDER_CLING_DISMISSED_KEY,
- DISMISS_CLING_DURATION, true);
+
+ void showWorkspaceSearchAndHotseat() {
+ mWorkspace.setAlpha(1f);
+ mHotseat.setAlpha(1f);
+ mPageIndicators.setAlpha(1f);
+ mSearchDropTargetBar.showSearchBar(false);
}
+ void hideWorkspaceSearchAndHotseat() {
+ mWorkspace.setAlpha(0f);
+ mHotseat.setAlpha(0f);
+ mPageIndicators.setAlpha(0f);
+ mSearchDropTargetBar.hideSearchBar(false);
+ }
+
+
public ItemInfo createAppDragInfo(Intent appLaunchIntent) {
ResolveInfo ri = getPackageManager().resolveActivity(appLaunchIntent, 0);
if (ri == null) {
@@ -4667,3 +4480,8 @@ interface LauncherTransitionable {
void onLauncherTransitionStep(Launcher l, float t);
void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace);
}
+
+interface DebugIntents {
+ static final String DELETE_DATABASE = "com.android.launcher3.action.DELETE_DATABASE";
+ static final String MIGRATE_DATABASE = "com.android.launcher3.action.MIGRATE_DATABASE";
+}
diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java
index d27cedcfc..156befbe0 100644
--- a/src/com/android/launcher3/LauncherAppState.java
+++ b/src/com/android/launcher3/LauncherAppState.java
@@ -30,9 +30,10 @@ public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
private static final String TAG = "LauncherAppState";
private static final String SHARED_PREFERENCES_KEY = "com.android.launcher3.prefs";
+ private final AppFilter mAppFilter;
+ private final BuildInfo mBuildInfo;
private LauncherModel mModel;
private IconCache mIconCache;
- private AppFilter mAppFilter;
private WidgetPreviewLoader.CacheDb mWidgetPreviewCacheDb;
private boolean mIsScreenLarge;
private float mScreenDensity;
@@ -87,6 +88,7 @@ public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
mIconCache = new IconCache(sContext);
mAppFilter = AppFilter.loadByName(sContext.getString(R.string.app_filter_class));
+ mBuildInfo = BuildInfo.loadByName(sContext.getString(R.string.build_info_class));
mModel = new LauncherModel(this, mIconCache, mAppFilter);
// Register intent receivers
@@ -237,4 +239,10 @@ public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
public void onAvailableSizeChanged(DeviceProfile grid) {
Utilities.setIconSize(grid.iconSizePx);
}
+
+ public static boolean isDisableAllApps() {
+ // Returns false on non-dogfood builds.
+ return getInstance().mBuildInfo.isDogfoodBuild() &&
+ Launcher.isPropertyEnabled(Launcher.DISABLE_ALL_APPS_PROPERTY);
+ }
}
diff --git a/src/com/android/launcher3/LauncherBackupHelper.java b/src/com/android/launcher3/LauncherBackupHelper.java
index 2a5ed6961..a081c2191 100644
--- a/src/com/android/launcher3/LauncherBackupHelper.java
+++ b/src/com/android/launcher3/LauncherBackupHelper.java
@@ -297,7 +297,7 @@ public class LauncherBackupHelper implements BackupHelper {
Key key = getKey(Key.FAVORITE, id);
keys.add(key);
currentIds.add(keyToBackupKey(key));
- if (updateTime > in.t) {
+ if (updateTime >= in.t) {
byte[] blob = packFavorite(cursor);
writeRowToBackup(key, blob, out, data);
}
@@ -365,7 +365,7 @@ public class LauncherBackupHelper implements BackupHelper {
Key key = getKey(Key.SCREEN, id);
keys.add(key);
currentIds.add(keyToBackupKey(key));
- if (updateTime > in.t) {
+ if (updateTime >= in.t) {
byte[] blob = packScreen(cursor);
writeRowToBackup(key, blob, out, data);
}
diff --git a/src/com/android/launcher3/LauncherClings.java b/src/com/android/launcher3/LauncherClings.java
new file mode 100644
index 000000000..541eaddd0
--- /dev/null
+++ b/src/com/android/launcher3/LauncherClings.java
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.os.UserManager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.TextView;
+
+class LauncherClings {
+ private static final String FIRST_RUN_CLING_DISMISSED_KEY = "cling_gel.first_run.dismissed";
+ private static final String MIGRATION_CLING_DISMISSED_KEY = "cling_gel.migration.dismissed";
+ private static final String MIGRATION_WORKSPACE_CLING_DISMISSED_KEY = "cling_gel.migration.dismissed";
+ private static final String WORKSPACE_CLING_DISMISSED_KEY = "cling_gel.workspace.dismissed";
+ private static final String FOLDER_CLING_DISMISSED_KEY = "cling_gel.folder.dismissed";
+
+ private static final boolean DISABLE_CLINGS = false;
+ private static final boolean DISABLE_CUSTOM_CLINGS = true;
+
+ private static final int SHOW_CLING_DURATION = 250;
+ private static final int DISMISS_CLING_DURATION = 200;
+
+ private Launcher mLauncher;
+ private LayoutInflater mInflater;
+ private HideFromAccessibilityHelper mHideFromAccessibilityHelper
+ = new HideFromAccessibilityHelper();
+
+ /** Ctor */
+ public LauncherClings(Launcher launcher) {
+ mLauncher = launcher;
+ mInflater = mLauncher.getLayoutInflater();
+ }
+
+ /** Initializes a cling */
+ private Cling initCling(int clingId, int scrimId, boolean animate,
+ boolean dimNavBarVisibilty) {
+ Cling cling = (Cling) mLauncher.findViewById(clingId);
+ View scrim = null;
+ if (scrimId > 0) {
+ scrim = mLauncher.findViewById(R.id.cling_scrim);
+ }
+ if (cling != null) {
+ cling.init(mLauncher, scrim);
+ cling.show(animate, SHOW_CLING_DURATION);
+
+ if (dimNavBarVisibilty) {
+ cling.setSystemUiVisibility(cling.getSystemUiVisibility() |
+ View.SYSTEM_UI_FLAG_LOW_PROFILE);
+ }
+ }
+ return cling;
+ }
+
+ /** Returns whether the clings are enabled or should be shown */
+ private boolean isClingsEnabled() {
+ if (DISABLE_CLINGS) {
+ return false;
+ }
+
+ // For now, limit only to phones
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ if (grid.isTablet()) {
+ return false;
+ }
+ if (grid.isLandscape) {
+ return false;
+ }
+
+ // disable clings when running in a test harness
+ if(ActivityManager.isRunningInTestHarness()) return false;
+
+ // Disable clings for accessibility when explore by touch is enabled
+ final AccessibilityManager a11yManager = (AccessibilityManager) mLauncher.getSystemService(
+ Launcher.ACCESSIBILITY_SERVICE);
+ if (a11yManager.isTouchExplorationEnabled()) {
+ return false;
+ }
+
+ // Restricted secondary users (child mode) will potentially have very few apps
+ // seeded when they start up for the first time. Clings won't work well with that
+ boolean supportsLimitedUsers =
+ android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
+ Account[] accounts = AccountManager.get(mLauncher).getAccounts();
+ if (supportsLimitedUsers && accounts.length == 0) {
+ UserManager um = (UserManager) mLauncher.getSystemService(Context.USER_SERVICE);
+ Bundle restrictions = um.getUserRestrictions();
+ if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /** Returns whether the folder cling is visible. */
+ public boolean isFolderClingVisible() {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.folder_cling);
+ if (cling != null) {
+ return cling.getVisibility() == View.VISIBLE;
+ }
+ return false;
+ }
+
+ private boolean skipCustomClingIfNoAccounts() {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.workspace_cling);
+ boolean customCling = cling.getDrawIdentifier().equals("workspace_custom");
+ if (customCling) {
+ AccountManager am = AccountManager.get(mLauncher);
+ if (am == null) return false;
+ Account[] accounts = am.getAccountsByType("com.google");
+ return accounts.length == 0;
+ }
+ return false;
+ }
+
+ /** Updates the first run cling custom content hint */
+ private void setCustomContentHintVisibility(Cling cling, String ccHintStr, boolean visible,
+ boolean animate) {
+ final TextView ccHint = (TextView) cling.findViewById(R.id.custom_content_hint);
+ if (ccHint != null) {
+ if (visible && !ccHintStr.isEmpty()) {
+ ccHint.setText(ccHintStr);
+ ccHint.setVisibility(View.VISIBLE);
+ if (animate) {
+ ccHint.setAlpha(0f);
+ ccHint.animate().alpha(1f)
+ .setDuration(SHOW_CLING_DURATION)
+ .start();
+ } else {
+ ccHint.setAlpha(1f);
+ }
+ } else {
+ if (animate) {
+ ccHint.animate().alpha(0f)
+ .setDuration(SHOW_CLING_DURATION)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ ccHint.setVisibility(View.GONE);
+ }
+ })
+ .start();
+ } else {
+ ccHint.setAlpha(0f);
+ ccHint.setVisibility(View.GONE);
+ }
+ }
+ }
+ }
+
+ /** Updates the first run cling custom content hint */
+ public void updateCustomContentHintVisibility() {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.first_run_cling);
+ String ccHintStr = mLauncher.getFirstRunCustomContentHint();
+
+ if (mLauncher.getWorkspace().hasCustomContent()) {
+ // Show the custom content hint if ccHintStr is not empty
+ if (cling != null) {
+ setCustomContentHintVisibility(cling, ccHintStr, true, true);
+ }
+ } else {
+ // Hide the custom content hint
+ if (cling != null) {
+ setCustomContentHintVisibility(cling, ccHintStr, false, true);
+ }
+ }
+ }
+
+ /** Updates the first run cling search bar hint. */
+ public void updateSearchBarHint(String hint) {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.first_run_cling);
+ if (cling != null && cling.getVisibility() == View.VISIBLE && !hint.isEmpty()) {
+ TextView sbHint = (TextView) cling.findViewById(R.id.search_bar_hint);
+ sbHint.setText(hint);
+ sbHint.setVisibility(View.VISIBLE);
+ }
+ }
+
+ /** Shows the first run cling */
+ public void showFirstRunCling() {
+ SharedPreferences sharedPrefs = mLauncher.getSharedPrefs();
+ if (isClingsEnabled() &&
+ !sharedPrefs.getBoolean(FIRST_RUN_CLING_DISMISSED_KEY, false) &&
+ !skipCustomClingIfNoAccounts() ) {
+
+
+ // If we're not using the default workspace layout, replace workspace cling
+ // with a custom workspace cling (usually specified in an overlay)
+ // For now, only do this on tablets
+ if (!DISABLE_CUSTOM_CLINGS) {
+ if (sharedPrefs.getInt(LauncherProvider.DEFAULT_WORKSPACE_RESOURCE_ID, 0) != 0 &&
+ mLauncher.getResources().getBoolean(R.bool.config_useCustomClings)) {
+ // Use a custom cling
+ View cling = mLauncher.findViewById(R.id.workspace_cling);
+ ViewGroup clingParent = (ViewGroup) cling.getParent();
+ int clingIndex = clingParent.indexOfChild(cling);
+ clingParent.removeViewAt(clingIndex);
+ View customCling = mInflater.inflate(R.layout.custom_workspace_cling,
+ clingParent, false);
+ clingParent.addView(customCling, clingIndex);
+ customCling.setId(R.id.workspace_cling);
+ }
+ }
+ Cling cling = (Cling) mLauncher.findViewById(R.id.first_run_cling);
+ if (cling != null) {
+ String sbHintStr = mLauncher.getFirstRunClingSearchBarHint();
+ String ccHintStr = mLauncher.getFirstRunCustomContentHint();
+ if (!sbHintStr.isEmpty()) {
+ TextView sbHint = (TextView) cling.findViewById(R.id.search_bar_hint);
+ sbHint.setText(sbHintStr);
+ sbHint.setVisibility(View.VISIBLE);
+ }
+ setCustomContentHintVisibility(cling, ccHintStr, true, false);
+ }
+ initCling(R.id.first_run_cling, 0, false, true);
+ } else {
+ removeCling(R.id.first_run_cling);
+ }
+ }
+
+ public void showMigrationCling() {
+ // Enable the clings only if they have not been dismissed before
+ if (isClingsEnabled() && !mLauncher.getSharedPrefs().getBoolean(
+ MIGRATION_CLING_DISMISSED_KEY, false)) {
+ mLauncher.hideWorkspaceSearchAndHotseat();
+
+ Cling c = initCling(R.id.migration_cling, 0, false, true);
+ c.bringScrimToFront();
+ c.bringToFront();
+ } else {
+ removeCling(R.id.migration_cling);
+ }
+ }
+
+ public void showMigrationWorkspaceCling() {
+ // Enable the clings only if they have not been dismissed before
+ if (isClingsEnabled() && !mLauncher.getSharedPrefs().getBoolean(
+ MIGRATION_WORKSPACE_CLING_DISMISSED_KEY, false)) {
+ Cling c = initCling(R.id.migration_workspace_cling, 0, false, true);
+ c.updateMigrationWorkspaceBubblePosition();
+ c.bringScrimToFront();
+ c.bringToFront();
+ } else {
+ removeCling(R.id.migration_workspace_cling);
+ }
+ }
+
+ public void showWorkspaceCling() {
+ // Enable the clings only if they have not been dismissed before
+ if (isClingsEnabled() && !mLauncher.getSharedPrefs().getBoolean(
+ WORKSPACE_CLING_DISMISSED_KEY, false)) {
+ Cling c = initCling(R.id.workspace_cling, 0, false, true);
+
+ // Set the focused hotseat app if there is one
+ c.setFocusedHotseatApp(mLauncher.getFirstRunFocusedHotseatAppDrawableId(),
+ mLauncher.getFirstRunFocusedHotseatAppRank(),
+ mLauncher.getFirstRunFocusedHotseatAppComponentName(),
+ mLauncher.getFirstRunFocusedHotseatAppBubbleTitle(),
+ mLauncher.getFirstRunFocusedHotseatAppBubbleDescription());
+ } else {
+ removeCling(R.id.workspace_cling);
+ }
+ }
+ public Cling showFoldersCling() {
+ SharedPreferences sharedPrefs = mLauncher.getSharedPrefs();
+ // Enable the clings only if they have not been dismissed before
+ if (isClingsEnabled() &&
+ !sharedPrefs.getBoolean(FOLDER_CLING_DISMISSED_KEY, false) &&
+ !sharedPrefs.getBoolean(Launcher.USER_HAS_MIGRATED, false)) {
+ Cling cling = initCling(R.id.folder_cling, R.id.cling_scrim,
+ true, true);
+ return cling;
+ } else {
+ removeCling(R.id.folder_cling);
+ return null;
+ }
+ }
+
+
+ /** Removes the cling outright from the DragLayer */
+ private void removeCling(int id) {
+ final View cling = mLauncher.findViewById(id);
+ if (cling != null) {
+ final ViewGroup parent = (ViewGroup) cling.getParent();
+ parent.post(new Runnable() {
+ @Override
+ public void run() {
+ parent.removeView(cling);
+ }
+ });
+ mHideFromAccessibilityHelper.restoreImportantForAccessibility(mLauncher.getDragLayer());
+ }
+ }
+
+ /** Hides the specified Cling */
+ private void dismissCling(final Cling cling, final Runnable postAnimationCb,
+ final String flag, int duration, boolean restoreNavBarVisibilty) {
+ // To catch cases where siblings of top-level views are made invisible, just check whether
+ // the cling is directly set to GONE before dismissing it.
+ if (cling != null && cling.getVisibility() != View.GONE) {
+ final Runnable cleanUpClingCb = new Runnable() {
+ public void run() {
+ cling.cleanup();
+ SharedPreferences.Editor editor = mLauncher.getSharedPrefs().edit();
+ editor.putBoolean(flag, true);
+ editor.apply();
+ if (postAnimationCb != null) {
+ postAnimationCb.run();
+ }
+ }
+ };
+ if (duration <= 0) {
+ cleanUpClingCb.run();
+ } else {
+ cling.hide(duration, cleanUpClingCb);
+ }
+ mHideFromAccessibilityHelper.restoreImportantForAccessibility(mLauncher.getDragLayer());
+
+ if (restoreNavBarVisibilty) {
+ cling.setSystemUiVisibility(cling.getSystemUiVisibility() &
+ ~View.SYSTEM_UI_FLAG_LOW_PROFILE);
+ }
+ }
+ }
+
+ public void dismissFirstRunCling(View v) {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.first_run_cling);
+ Runnable cb = new Runnable() {
+ public void run() {
+ // Show the workspace cling next
+ showWorkspaceCling();
+ }
+ };
+ dismissCling(cling, cb, FIRST_RUN_CLING_DISMISSED_KEY,
+ DISMISS_CLING_DURATION, false);
+
+ // Fade out the search bar for the workspace cling coming up
+ mLauncher.getSearchBar().hideSearchBar(true);
+ }
+
+ private void dismissMigrationCling() {
+ mLauncher.showWorkspaceSearchAndHotseat();
+ Runnable dismissCb = new Runnable() {
+ public void run() {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.migration_cling);
+ Runnable cb = new Runnable() {
+ public void run() {
+ // Show the migration workspace cling next
+ showMigrationWorkspaceCling();
+ }
+ };
+ dismissCling(cling, cb, WORKSPACE_CLING_DISMISSED_KEY,
+ DISMISS_CLING_DURATION, true);
+ }
+ };
+ mLauncher.getWorkspace().post(dismissCb);
+ }
+
+ private void dismissAnyWorkspaceCling(Cling cling, View v) {
+ Runnable cb = null;
+ if (v == null) {
+ cb = new Runnable() {
+ public void run() {
+ mLauncher.getWorkspace().enterOverviewMode();
+ }
+ };
+ }
+ dismissCling(cling, cb, WORKSPACE_CLING_DISMISSED_KEY,
+ DISMISS_CLING_DURATION, true);
+
+ // Fade in the search bar
+ mLauncher.getSearchBar().showSearchBar(true);
+ }
+
+ public void dismissMigrationClingCopyApps(View v) {
+ // Copy the shortcuts from the old database
+ LauncherModel model = mLauncher.getModel();
+ model.resetLoadedState(false, true);
+ model.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
+ LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE
+ | LauncherModel.LOADER_FLAG_MIGRATE_SHORTCUTS);
+
+ // Set the flag to skip the folder cling
+ String spKey = LauncherAppState.getSharedPreferencesKey();
+ SharedPreferences sp = mLauncher.getSharedPreferences(spKey, Context.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sp.edit();
+ editor.putBoolean(Launcher.USER_HAS_MIGRATED, true);
+ editor.apply();
+
+ // Disable the migration cling
+ dismissMigrationCling();
+ }
+
+ public void dismissMigrationClingUseDefault(View v) {
+ // Clear the workspace
+ LauncherModel model = mLauncher.getModel();
+ model.resetLoadedState(false, true);
+ model.startLoader(false, PagedView.INVALID_RESTORE_PAGE,
+ LauncherModel.LOADER_FLAG_CLEAR_WORKSPACE);
+
+ // Disable the migration cling
+ dismissMigrationCling();
+ }
+
+ public void dismissMigrationWorkspaceCling(View v) {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.migration_workspace_cling);
+ dismissAnyWorkspaceCling(cling, v);
+ }
+
+ public void dismissWorkspaceCling(View v) {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.workspace_cling);
+ dismissAnyWorkspaceCling(cling, v);
+ }
+
+ public void dismissFolderCling(View v) {
+ Cling cling = (Cling) mLauncher.findViewById(R.id.folder_cling);
+ dismissCling(cling, null, FOLDER_CLING_DISMISSED_KEY,
+ DISMISS_CLING_DURATION, true);
+ }
+} \ No newline at end of file
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index b2cfb2456..d271976a7 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -75,9 +75,15 @@ public class LauncherModel extends BroadcastReceiver {
// false = strew non-workspace apps across the workspace on upgrade
public static final boolean UPGRADE_USE_MORE_APPS_FOLDER = false;
+ public static final int LOADER_FLAG_NONE = 0;
+ public static final int LOADER_FLAG_CLEAR_WORKSPACE = 1 << 0;
+ public static final int LOADER_FLAG_MIGRATE_SHORTCUTS = 1 << 1;
+
private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons
private static final long INVALID_SCREEN_ID = -1L;
+
private final boolean mAppsCanBeOnRemoveableStorage;
+ private final boolean mOldContentProviderExists;
private final LauncherAppState mApp;
private final Object mLock = new Object();
@@ -181,9 +187,12 @@ public class LauncherModel extends BroadcastReceiver {
}
LauncherModel(LauncherAppState app, IconCache iconCache, AppFilter appFilter) {
- final Context context = app.getContext();
+ Context context = app.getContext();
+ ContentResolver contentResolver = context.getContentResolver();
mAppsCanBeOnRemoveableStorage = Environment.isExternalStorageRemovable();
+ mOldContentProviderExists = (contentResolver.acquireContentProviderClient(
+ LauncherSettings.Favorites.OLD_CONTENT_URI) != null);
mApp = app;
mBgAllAppsList = new AllAppsList(iconCache, appFilter);
mIconCache = iconCache;
@@ -218,6 +227,10 @@ public class LauncherModel extends BroadcastReceiver {
}
}
+ boolean canMigrateFromOldLauncherDb() {
+ return mOldContentProviderExists;
+ }
+
static boolean findNextAvailableIconSpaceInScreen(ArrayList<ItemInfo> items, int[] xy,
long screen) {
LauncherAppState app = LauncherAppState.getInstance();
@@ -1193,6 +1206,10 @@ public class LauncherModel extends BroadcastReceiver {
}
public void startLoader(boolean isLaunching, int synchronousBindPage) {
+ startLoader(isLaunching, synchronousBindPage, LOADER_FLAG_NONE);
+ }
+
+ public void startLoader(boolean isLaunching, int synchronousBindPage, int loadFlags) {
synchronized (mLock) {
if (DEBUG_LOADERS) {
Log.d(TAG, "startLoader isLaunching=" + isLaunching);
@@ -1207,7 +1224,7 @@ public class LauncherModel extends BroadcastReceiver {
// If there is already one running, tell it to stop.
// also, don't downgrade isLaunching if we're already running
isLaunching = isLaunching || stopLoaderLocked();
- mLoaderTask = new LoaderTask(mApp.getContext(), isLaunching);
+ mLoaderTask = new LoaderTask(mApp.getContext(), isLaunching, loadFlags);
if (synchronousBindPage != PagedView.INVALID_RESTORE_PAGE
&& mAllAppsLoaded && mWorkspaceLoaded) {
mLoaderTask.runBindSynchronousPage(synchronousBindPage);
@@ -1298,13 +1315,15 @@ public class LauncherModel extends BroadcastReceiver {
private boolean mIsLoadingAndBindingWorkspace;
private boolean mStopped;
private boolean mLoadAndBindStepFinished;
+ private int mFlags;
private HashMap<Object, CharSequence> mLabelCache;
- LoaderTask(Context context, boolean isLaunching) {
+ LoaderTask(Context context, boolean isLaunching, int flags) {
mContext = context;
mIsLaunching = isLaunching;
mLabelCache = new HashMap<Object, CharSequence>();
+ mFlags = flags;
}
boolean isLaunching() {
@@ -1466,7 +1485,7 @@ public class LauncherModel extends BroadcastReceiver {
sBgDbIconCache.clear();
}
- if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+ if (LauncherAppState.isDisableAllApps()) {
// Ensure that all the applications that are in the system are
// represented on the home screen.
if (!UPGRADE_USE_MORE_APPS_FOLDER || !isUpgrade) {
@@ -1651,7 +1670,7 @@ public class LauncherModel extends BroadcastReceiver {
}
}
- /** Returns whether this is an upgradge path */
+ /** Returns whether this is an upgrade path */
private boolean loadWorkspace() {
// Log to disk
Launcher.addDumpLog(TAG, "11683562 - loadWorkspace()", true);
@@ -1669,8 +1688,20 @@ public class LauncherModel extends BroadcastReceiver {
int countX = (int) grid.numColumns;
int countY = (int) grid.numRows;
- // Make sure the default workspace is loaded, if needed
- LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary(0);
+ if ((mFlags & LOADER_FLAG_CLEAR_WORKSPACE) != 0) {
+ Launcher.addDumpLog(TAG, "loadWorkspace: resetting launcher database", true);
+ LauncherAppState.getLauncherProvider().deleteDatabase();
+ }
+
+ if ((mFlags & LOADER_FLAG_MIGRATE_SHORTCUTS) != 0) {
+ // append the user's Launcher2 shortcuts
+ Launcher.addDumpLog(TAG, "loadWorkspace: migrating from launcher2", true);
+ LauncherAppState.getLauncherProvider().migrateLauncher2Shortcuts();
+ } else {
+ // Make sure the default workspace is loaded
+ Launcher.addDumpLog(TAG, "loadWorkspace: loading default favorites", false);
+ LauncherAppState.getLauncherProvider().loadDefaultFavoritesIfNecessary(0);
+ }
// Check if we need to do any upgrade-path logic
// (Includes having just imported default favorites)
@@ -2564,7 +2595,7 @@ public class LauncherModel extends BroadcastReceiver {
if (added != null) {
// Ensure that we add all the workspace applications to the db
Callbacks cb = mCallbacks != null ? mCallbacks.get() : null;
- if (!AppsCustomizePagedView.DISABLE_ALL_APPS) {
+ if (!LauncherAppState.isDisableAllApps()) {
addAndBindAddedApps(context, new ArrayList<ItemInfo>(), cb, added);
} else {
final ArrayList<ItemInfo> addedInfos = new ArrayList<ItemInfo>(added);
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 28efd0148..7adbadea1 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -55,9 +55,11 @@ import com.android.launcher3.config.ProviderConfig;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
public class LauncherProvider extends ContentProvider {
@@ -72,7 +74,7 @@ public class LauncherProvider extends ContentProvider {
static final String AUTHORITY = ProviderConfig.AUTHORITY;
// Should we attempt to load anything from the com.android.launcher2 provider?
- static final boolean IMPORT_LAUNCHER2_DATABASE = true;
+ static final boolean IMPORT_LAUNCHER2_DATABASE = false;
static final String TABLE_FAVORITES = "favorites";
static final String TABLE_WORKSPACE_SCREENS = "workspaceScreens";
@@ -133,6 +135,9 @@ public class LauncherProvider extends ContentProvider {
private static long dbInsertAndCheck(DatabaseHelper helper,
SQLiteDatabase db, String table, String nullColumnHack, ContentValues values) {
+ if (values == null) {
+ throw new RuntimeException("Error: attempting to insert null values");
+ }
if (!values.containsKey(LauncherSettings.Favorites._ID)) {
throw new RuntimeException("Error: attempting to add item without specifying an id");
}
@@ -287,8 +292,13 @@ public class LauncherProvider extends ContentProvider {
}
}
+ public void migrateLauncher2Shortcuts() {
+ mOpenHelper.migrateLauncher2Shortcuts(mOpenHelper.getWritableDatabase(),
+ LauncherSettings.Favorites.OLD_CONTENT_URI);
+ }
+
private static int getDefaultWorkspaceResourceId() {
- if (AppsCustomizePagedView.DISABLE_ALL_APPS) {
+ if (LauncherAppState.isDisableAllApps()) {
return R.xml.default_workspace_no_all_apps;
} else {
return R.xml.default_workspace;
@@ -306,6 +316,15 @@ public class LauncherProvider extends ContentProvider {
return !isTablet && IMPORT_LAUNCHER2_DATABASE;
}
+ public void deleteDatabase() {
+ // Are you sure? (y/n)
+ final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
+ final String dbFile = db.getPath();
+ mOpenHelper.close();
+ SQLiteDatabase.deleteDatabase(new File(dbFile));
+ mOpenHelper = new DatabaseHelper(getContext());
+ }
+
private static class DatabaseHelper extends SQLiteOpenHelper {
private static final String TAG_FAVORITES = "favorites";
private static final String TAG_FAVORITE = "favorite";
@@ -1431,6 +1450,209 @@ public class LauncherProvider extends ContentProvider {
}
return id;
}
+
+ public void migrateLauncher2Shortcuts(SQLiteDatabase db, Uri uri) {
+ final ContentResolver resolver = mContext.getContentResolver();
+ Cursor c = null;
+ int count = 0;
+ int curScreen = 0;
+
+ try {
+ c = resolver.query(uri, null, null, null, "title ASC");
+ } catch (Exception e) {
+ // Ignore
+ }
+
+
+ // We already have a favorites database in the old provider
+ if (c != null) {
+ try {
+ if (c.getCount() > 0) {
+ final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
+ final int intentIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
+ final int titleIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
+ final int iconTypeIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_TYPE);
+ final int iconIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
+ final int iconPackageIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_PACKAGE);
+ final int iconResourceIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_RESOURCE);
+ final int containerIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
+ final int itemTypeIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
+ final int screenIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
+ final int cellXIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
+ final int cellYIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
+ final int uriIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);
+ final int displayModeIndex
+ = c.getColumnIndexOrThrow(LauncherSettings.Favorites.DISPLAY_MODE);
+
+ int i = 0;
+ int curX = 0;
+ int curY = 0;
+
+ final LauncherAppState app = LauncherAppState.getInstance();
+ final DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+ final int width = (int) grid.numColumns;
+ final int height = (int) grid.numRows;
+ final int hotseatWidth = (int) grid.numHotseatIcons;
+
+ final HashSet<String> seenIntents = new HashSet<String>(c.getCount());
+
+ final ContentValues[] rows = new ContentValues[c.getCount()];
+
+ while (c.moveToNext()) {
+ final int itemType = c.getInt(itemTypeIndex);
+ if (itemType != Favorites.ITEM_TYPE_APPLICATION
+ && itemType != Favorites.ITEM_TYPE_SHORTCUT
+ && itemType != Favorites.ITEM_TYPE_FOLDER) {
+ continue;
+ }
+
+ final int cellX = c.getInt(cellXIndex);
+ final int cellY = c.getInt(cellYIndex);
+ final int screen = c.getInt(screenIndex);
+ int container = c.getInt(containerIndex);
+ final String intentStr = c.getString(intentIndex);
+ Launcher.addDumpLog(TAG, "migrating \""
+ + c.getString(titleIndex) + "\": " + intentStr, true);
+
+ if (itemType != Favorites.ITEM_TYPE_FOLDER) {
+ if (TextUtils.isEmpty(intentStr)) {
+ // no intent? no icon
+ Launcher.addDumpLog(TAG, "skipping empty intent", true);
+ continue;
+ } else {
+ try {
+ // Canonicalize
+ final Intent intent = Intent.parseUri(intentStr, 0);
+ // the Play Store sets the package parameter, but Launcher
+ // does not, so we clear that out to keep them the same
+ intent.setPackage(null);
+ final String key = intent.toUri(0);
+ if (seenIntents.contains(key)) {
+ Launcher.addDumpLog(TAG, "skipping duplicate", true);
+ continue;
+ } else {
+ seenIntents.add(key);
+ }
+ } catch (URISyntaxException e) {
+ // bogus intent?
+ Launcher.addDumpLog(TAG,
+ "skipping invalid intent uri", true);
+ continue;
+ }
+ }
+ }
+
+ ContentValues values = new ContentValues(c.getColumnCount());
+ values.put(LauncherSettings.Favorites._ID, c.getInt(idIndex));
+ values.put(LauncherSettings.Favorites.INTENT, intentStr);
+ values.put(LauncherSettings.Favorites.TITLE, c.getString(titleIndex));
+ values.put(LauncherSettings.Favorites.ICON_TYPE,
+ c.getInt(iconTypeIndex));
+ values.put(LauncherSettings.Favorites.ICON, c.getBlob(iconIndex));
+ values.put(LauncherSettings.Favorites.ICON_PACKAGE,
+ c.getString(iconPackageIndex));
+ values.put(LauncherSettings.Favorites.ICON_RESOURCE,
+ c.getString(iconResourceIndex));
+ values.put(LauncherSettings.Favorites.ITEM_TYPE, itemType);
+ values.put(LauncherSettings.Favorites.APPWIDGET_ID, -1);
+ values.put(LauncherSettings.Favorites.URI, c.getString(uriIndex));
+ values.put(LauncherSettings.Favorites.DISPLAY_MODE,
+ c.getInt(displayModeIndex));
+
+ if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT
+ && screen >= hotseatWidth) {
+ // no room for you in the hotseat? it's off to the desktop with you
+ container = Favorites.CONTAINER_DESKTOP;
+ }
+
+ if (container != LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+ // In a folder or in the hotseat, preserve position
+ values.put(LauncherSettings.Favorites.SCREEN, screen);
+ values.put(LauncherSettings.Favorites.CELLX, cellX);
+ values.put(LauncherSettings.Favorites.CELLY, cellY);
+ } else {
+ values.put(LauncherSettings.Favorites.SCREEN, curScreen);
+ values.put(LauncherSettings.Favorites.CELLX, curX);
+ values.put(LauncherSettings.Favorites.CELLY, curY);
+ curX = (curX + 1) % width;
+ if (curX == 0) {
+ curY = (curY + 1);
+ }
+ // Leave the last row of icons blank on screen 0
+ if (curScreen == 0 && curY == height - 1 || curY == height) {
+ curScreen = (int) generateNewScreenId();
+ curY = 0;
+ }
+ }
+
+ values.put(LauncherSettings.Favorites.CONTAINER, container);
+
+ rows[i++] = values;
+ }
+
+ if (i > 0) {
+ db.beginTransaction();
+ try {
+ final int N = rows.length;
+ for (i = 0; i < N; i++) {
+ if (rows[i] == null) continue;
+ if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, rows[i])
+ < 0) {
+ return;
+ } else {
+ count++;
+ }
+ }
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ }
+
+ db.beginTransaction();
+ try {
+ for (i=0; i<=curScreen; i++) {
+ final ContentValues values = new ContentValues();
+ values.put(LauncherSettings.WorkspaceScreens._ID, i);
+ values.put(LauncherSettings.WorkspaceScreens.SCREEN_RANK, i);
+ if (dbInsertAndCheck(this, db, TABLE_WORKSPACE_SCREENS, null, values)
+ < 0) {
+ return;
+ }
+ }
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ }
+ } finally {
+ c.close();
+ }
+ }
+
+ Launcher.addDumpLog(TAG, "migrated " + count + " icons from Launcher2 into "
+ + (curScreen+1) + " screens", true);
+
+ // ensure that new screens are created to hold these icons
+ setFlagJustLoadedOldDb();
+
+ // Update max IDs; very important since we just grabbed IDs from another database
+ mMaxItemId = initializeMaxItemId(db);
+ mMaxScreenId = initializeMaxScreenId(db);
+ if (LOGD) Log.d(TAG, "mMaxItemId: " + mMaxItemId + " mMaxScreenId: " + mMaxScreenId);
+ }
}
/**
diff --git a/src/com/android/launcher3/OnAlarmListener.java b/src/com/android/launcher3/OnAlarmListener.java
new file mode 100644
index 000000000..b5ef83e83
--- /dev/null
+++ b/src/com/android/launcher3/OnAlarmListener.java
@@ -0,0 +1,5 @@
+package com.android.launcher3;
+
+public interface OnAlarmListener {
+ public void onAlarm(Alarm alarm);
+}
diff --git a/src/com/android/launcher3/WallpaperChangedReceiver.java b/src/com/android/launcher3/WallpaperChangedReceiver.java
index 28e41d8a5..2d5612f12 100644
--- a/src/com/android/launcher3/WallpaperChangedReceiver.java
+++ b/src/com/android/launcher3/WallpaperChangedReceiver.java
@@ -22,6 +22,7 @@ import android.content.Intent;
public class WallpaperChangedReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent data) {
+ LauncherAppState.setApplicationContext(context.getApplicationContext());
LauncherAppState appState = LauncherAppState.getInstance();
appState.onWallpaperChanged();
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index b6276c0f2..2ce9eb3ad 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -579,7 +579,7 @@ public class Workspace extends SmoothPagedView
mDefaultPage = mOriginalDefaultPage + 1;
// Update the custom content hint
- mLauncher.updateCustomContentHintVisibility();
+ mLauncher.getLauncherClings().updateCustomContentHintVisibility();
if (mRestorePage != INVALID_RESTORE_PAGE) {
mRestorePage = mRestorePage + 1;
} else {
@@ -608,7 +608,7 @@ public class Workspace extends SmoothPagedView
mDefaultPage = mOriginalDefaultPage - 1;
// Update the custom content hint
- mLauncher.updateCustomContentHintVisibility();
+ mLauncher.getLauncherClings().updateCustomContentHintVisibility();
if (mRestorePage != INVALID_RESTORE_PAGE) {
mRestorePage = mRestorePage - 1;
} else {