diff options
Diffstat (limited to 'src/com/android')
-rw-r--r-- | src/com/android/launcher3/AppWidgetsRestoredReceiver.java | 12 | ||||
-rw-r--r-- | src/com/android/launcher3/AppsCustomizePagedView.java | 99 | ||||
-rw-r--r-- | src/com/android/launcher3/AppsCustomizeTabHost.java | 22 | ||||
-rw-r--r-- | src/com/android/launcher3/DeviceProfile.java | 19 | ||||
-rw-r--r-- | src/com/android/launcher3/ItemInfo.java | 8 | ||||
-rw-r--r-- | src/com/android/launcher3/Launcher.java | 498 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherAppWidgetHostView.java | 33 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherAppWidgetInfo.java | 18 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherBackupHelper.java | 21 | ||||
-rw-r--r-- | src/com/android/launcher3/LauncherModel.java | 62 | ||||
-rw-r--r-- | src/com/android/launcher3/PagedView.java | 16 | ||||
-rw-r--r-- | src/com/android/launcher3/PagedViewGridLayout.java | 12 | ||||
-rw-r--r-- | src/com/android/launcher3/PendingAppWidgetHostView.java | 78 | ||||
-rw-r--r-- | src/com/android/launcher3/Workspace.java | 76 | ||||
-rw-r--r-- | src/com/android/launcher3/compat/UserManagerCompatVL.java | 7 |
15 files changed, 553 insertions, 428 deletions
diff --git a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java index 80cb52da9..880aaf1ec 100644 --- a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java +++ b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java @@ -46,17 +46,21 @@ public class AppWidgetsRestoredReceiver extends BroadcastReceiver { Log.i(TAG, "Widget state restore id " + oldWidgetIds[i] + " => " + newWidgetIds[i]); final AppWidgetProviderInfo provider = widgets.getAppWidgetInfo(newWidgetIds[i]); + final int state; + if (LauncherModel.isValidProvider(provider)) { + state = LauncherAppWidgetInfo.RESTORE_COMPLETED; + } else { + state = LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY; + } ContentValues values = new ContentValues(); values.put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i]); - values.put(LauncherSettings.Favorites.RESTORED, LauncherModel.isValidProvider(provider) - ? LauncherAppWidgetInfo.RESTORE_COMPLETED - : LauncherAppWidgetInfo.RESTORE_PROVIDER_PENDING); + values.put(LauncherSettings.Favorites.RESTORED, state); String[] widgetIdParams = new String[] { Integer.toString(oldWidgetIds[i]) }; int result = cr.update(Favorites.CONTENT_URI, values, - "appWidgetId=? and restored=1", widgetIdParams); + "appWidgetId=? and (restored & 1) = 1", widgetIdParams); if (result == 0) { Cursor cursor = cr.query(Favorites.CONTENT_URI, new String[] {Favorites.APPWIDGET_ID}, diff --git a/src/com/android/launcher3/AppsCustomizePagedView.java b/src/com/android/launcher3/AppsCustomizePagedView.java index 0e9969697..e0543ceb6 100644 --- a/src/com/android/launcher3/AppsCustomizePagedView.java +++ b/src/com/android/launcher3/AppsCustomizePagedView.java @@ -148,6 +148,8 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen LauncherTransitionable { static final String TAG = "AppsCustomizePagedView"; + private static Rect sTmpRect = new Rect(); + /** * The different content types that this paged view can show. */ @@ -183,7 +185,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen // Dimens private int mContentWidth, mContentHeight; private int mWidgetCountX, mWidgetCountY; - private int mWidgetWidthGap, mWidgetHeightGap; private PagedViewCellLayout mWidgetSpacingLayout; private int mNumAppsPages; private int mNumWidgetPages; @@ -195,7 +196,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen private static float TRANSITION_SCALE_FACTOR = 0.74f; private static float TRANSITION_PIVOT = 0.65f; private static float TRANSITION_MAX_ROTATION = 22; - private static final boolean PERFORM_OVERSCROLL_ROTATION = true; + private static final boolean PERFORM_OVERSCROLL_ROTATION = false; private AccelerateInterpolator mAlphaInterpolator = new AccelerateInterpolator(0.9f); private DecelerateInterpolator mLeftScreenAlphaInterpolator = new DecelerateInterpolator(4); @@ -213,6 +214,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen int mWidgetLoadingId = -1; PendingAddWidgetInfo mCreateWidgetInfo = null; private boolean mDraggingWidget = false; + boolean mPageBackgroundsVisible; private Toast mWidgetInstructionToast; @@ -223,8 +225,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen private ArrayList<Runnable> mDeferredPrepareLoadWidgetPreviewsTasks = new ArrayList<Runnable>(); - private Rect mTmpRect = new Rect(); - WidgetPreviewLoader mWidgetPreviewLoader; private boolean mInBulkBind; @@ -244,7 +244,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AppsCustomizePagedView, 0, 0); LauncherAppState app = LauncherAppState.getInstance(); DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); - mWidgetWidthGap = mWidgetHeightGap = grid.edgeMarginPx; mWidgetCountX = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountX, 2); mWidgetCountY = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountY, 2); mClingFocusedX = a.getInt(R.styleable.AppsCustomizePagedView_clingFocusedX, 0); @@ -284,8 +283,9 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen void setAllAppsPadding(Rect r) { mAllAppsPadding.set(r); } + void setWidgetsPageIndicatorPadding(int pageIndicatorHeight) { - mPageLayoutPaddingBottom = pageIndicatorHeight; + setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), pageIndicatorHeight); } WidgetPreviewLoader getWidgetPreviewLoader() { @@ -364,8 +364,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen // use for each page LauncherAppState app = LauncherAppState.getInstance(); DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); - mWidgetSpacingLayout.setPadding(mPageLayoutPaddingLeft, mPageLayoutPaddingTop, - mPageLayoutPaddingRight, mPageLayoutPaddingBottom); mCellCountX = (int) grid.allAppsNumCols; mCellCountY = (int) grid.allAppsNumRows; updatePageCounts(); @@ -540,26 +538,26 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen mLauncher.getWorkspace().beginDragShared(v, this); } - Bundle getDefaultOptionsForWidget(Launcher launcher, PendingAddWidgetInfo info) { + static Bundle getDefaultOptionsForWidget(Launcher launcher, PendingAddWidgetInfo info) { Bundle options = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - AppWidgetResizeFrame.getWidgetSizeRanges(mLauncher, info.spanX, info.spanY, mTmpRect); - Rect padding = AppWidgetHostView.getDefaultPaddingForWidget(mLauncher, + AppWidgetResizeFrame.getWidgetSizeRanges(launcher, info.spanX, info.spanY, sTmpRect); + Rect padding = AppWidgetHostView.getDefaultPaddingForWidget(launcher, info.componentName, null); - float density = getResources().getDisplayMetrics().density; + float density = launcher.getResources().getDisplayMetrics().density; int xPaddingDips = (int) ((padding.left + padding.right) / density); int yPaddingDips = (int) ((padding.top + padding.bottom) / density); options = new Bundle(); options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, - mTmpRect.left - xPaddingDips); + sTmpRect.left - xPaddingDips); options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, - mTmpRect.top - yPaddingDips); + sTmpRect.top - yPaddingDips); options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, - mTmpRect.right - xPaddingDips); + sTmpRect.right - xPaddingDips); options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, - mTmpRect.bottom - yPaddingDips); + sTmpRect.bottom - yPaddingDips); } return options; } @@ -1001,14 +999,26 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen setVisibilityOnChildren(layout, View.GONE); int widthSpec = MeasureSpec.makeMeasureSpec(mContentWidth, MeasureSpec.AT_MOST); int heightSpec = MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.AT_MOST); - layout.setMinimumWidth(getPageContentWidth()); layout.measure(widthSpec, heightSpec); - layout.setPadding(mAllAppsPadding.left, mAllAppsPadding.top, mAllAppsPadding.right, - mAllAppsPadding.bottom); + + Drawable bg = getContext().getResources().getDrawable(R.drawable.quantum_panel); + if (bg != null) { + layout.setBackground(bg); + bg.setVisible(mPageBackgroundsVisible, false); + } + setVisibilityOnChildren(layout, View.VISIBLE); + } - Resources res = getContext().getResources(); - layout.setBackground(res.getDrawable(R.drawable.quantum_panel)); + public void setPageBackgroundsVisible(boolean visible) { + mPageBackgroundsVisible = visible; + int childCount = getChildCount(); + for (int i = 0; i < childCount; ++i) { + Drawable bg = getChildAt(i).getBackground(); + if (bg != null) { + bg.setVisible(visible, false); + } + } } public void syncAppsPageItems(int page, boolean immediate) { @@ -1153,21 +1163,23 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen // immediately after syncing, we don't have a proper width. int widthSpec = MeasureSpec.makeMeasureSpec(mContentWidth, MeasureSpec.AT_MOST); int heightSpec = MeasureSpec.makeMeasureSpec(mContentHeight, MeasureSpec.AT_MOST); - layout.setMinimumWidth(getPageContentWidth()); + layout.setBackground(getContext().getResources().getDrawable(R.drawable.quantum_panel_dark)); layout.measure(widthSpec, heightSpec); } public void syncWidgetPageItems(final int page, final boolean immediate) { int numItemsPerPage = mWidgetCountX * mWidgetCountY; + final PagedViewGridLayout layout = (PagedViewGridLayout) getPageAt(page); + // Calculate the dimensions of each cell we are giving to each widget final ArrayList<Object> items = new ArrayList<Object>(); - int contentWidth = mContentWidth; - final int cellWidth = ((contentWidth - mPageLayoutPaddingLeft - mPageLayoutPaddingRight - - ((mWidgetCountX - 1) * mWidgetWidthGap)) / mWidgetCountX); - int contentHeight = mContentHeight; - final int cellHeight = ((contentHeight - mPageLayoutPaddingTop - mPageLayoutPaddingBottom - - ((mWidgetCountY - 1) * mWidgetHeightGap)) / mWidgetCountY); + int contentWidth = mContentWidth - getPaddingLeft() - getPaddingRight() + - layout.getPaddingLeft() - layout.getPaddingRight(); + final int cellWidth = contentWidth / mWidgetCountX; + int contentHeight = mContentHeight - getPaddingTop() - getPaddingBottom() + - layout.getPaddingTop() - layout.getPaddingBottom(); + final int cellHeight = contentHeight / mWidgetCountY; // Prepare the set of widgets to load previews for in the background int offset = page * numItemsPerPage; @@ -1176,7 +1188,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen } // Prepopulate the pages with the other widget info, and fill in the previews later - final PagedViewGridLayout layout = (PagedViewGridLayout) getPageAt(page); layout.setColumnCount(layout.getCellCountX()); for (int i = 0; i < items.size(); ++i) { Object rawInfo = items.get(i); @@ -1217,14 +1228,22 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen // Layout each widget int ix = i % mWidgetCountX; int iy = i / mWidgetCountX; + + if (ix > 0) { + View border = widget.findViewById(R.id.left_border); + border.setVisibility(View.VISIBLE); + } + if (ix < mWidgetCountX - 1) { + View border = widget.findViewById(R.id.right_border); + border.setVisibility(View.VISIBLE); + } + GridLayout.LayoutParams lp = new GridLayout.LayoutParams( GridLayout.spec(iy, GridLayout.START), GridLayout.spec(ix, GridLayout.TOP)); lp.width = cellWidth; lp.height = cellHeight; lp.setGravity(Gravity.TOP | Gravity.START); - if (ix > 0) lp.leftMargin = mWidgetWidthGap; - if (iy > 0) lp.topMargin = mWidgetHeightGap; layout.addView(widget, lp); } @@ -1438,24 +1457,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen v.setRotationY(0f); } } - - // TODO: clean this up - alpha = 1; - translationX = 0; - scale = 1; - - v.setTranslationX(translationX); - v.setScaleX(scale); - v.setScaleY(scale); - v.setAlpha(alpha); - - // If the view has 0 alpha, we set it to be invisible so as to prevent - // it from accepting touches - if (alpha == 0) { - v.setVisibility(INVISIBLE); - } else if (v.getVisibility() != VISIBLE) { - v.setVisibility(VISIBLE); - } } } diff --git a/src/com/android/launcher3/AppsCustomizeTabHost.java b/src/com/android/launcher3/AppsCustomizeTabHost.java index 283f4ed2f..629bcdb1d 100644 --- a/src/com/android/launcher3/AppsCustomizeTabHost.java +++ b/src/com/android/launcher3/AppsCustomizeTabHost.java @@ -181,9 +181,6 @@ public class AppsCustomizeTabHost extends FrameLayout implements LauncherTransit @Override public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) { mPagedView.onLauncherTransitionStart(l, animated, toWorkspace); - if (animated && !Utilities.isLmp()) { - enableAndBuildHardwareLayer(); - } } @Override @@ -195,9 +192,6 @@ public class AppsCustomizeTabHost extends FrameLayout implements LauncherTransit public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) { mPagedView.onLauncherTransitionEnd(l, animated, toWorkspace); mInTransition = false; - if (animated && !Utilities.isLmp()) { - setLayerType(LAYER_TYPE_NONE, null); - } if (!toWorkspace) { // Make sure adjacent pages are loaded (we wait until after the transition to @@ -241,20 +235,4 @@ public class AppsCustomizeTabHost extends FrameLayout implements LauncherTransit throw new RuntimeException("Failed; can't get z-order of views"); } } - - private void enableAndBuildHardwareLayer() { - // isHardwareAccelerated() checks if we're attached to a window and if that - // window is HW accelerated-- we were sometimes not attached to a window - // and buildLayer was throwing an IllegalStateException - if (isHardwareAccelerated()) { - // Turn on hardware layers for performance - setLayerType(LAYER_TYPE_HARDWARE, null); - - // force building the layer, so you don't get a blip early in an animation - // when the layer is created layer - buildLayer(); - } - } - - } diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index c0f505481..018fcfcbc 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -775,6 +775,11 @@ public class DeviceProfile { AppsCustomizePagedView pagedView = (AppsCustomizePagedView) host.findViewById(R.id.apps_customize_pane_content); + + FrameLayout fakePageContainer = (FrameLayout) + host.findViewById(R.id.fake_page_container); + FrameLayout fakePage = (FrameLayout) host.findViewById(R.id.fake_page); + padding = new Rect(); if (pagedView != null) { // Constrain the dimensions of all apps so that it does not span the full width @@ -790,16 +795,24 @@ public class DeviceProfile { if ((isTablet() || isLandscape) && gridPaddingLR > (allAppsCellWidthPx / 4)) { padding.left = padding.right = gridPaddingLR; } + // The icons are centered, so we can't just offset by the page indicator height // because the empty space will actually be pageIndicatorHeight + paddingTB padding.bottom = Math.max(0, pageIndicatorHeight - paddingTB); - pagedView.setAllAppsPadding(padding); + pagedView.setWidgetsPageIndicatorPadding(pageIndicatorHeight); + fakePage.setBackground(res.getDrawable(R.drawable.quantum_panel)); // Horizontal padding for the whole paged view - int pagedViewPadding = + int pagedFixedViewPadding = res.getDimensionPixelSize(R.dimen.apps_customize_horizontal_padding); - pagedView.setPadding(pagedViewPadding, 0, pagedViewPadding, 0); + + padding.left += pagedFixedViewPadding; + padding.right += pagedFixedViewPadding; + + pagedView.setPadding(padding.left, padding.top, padding.right, padding.bottom); + fakePageContainer.setPadding(padding.left, padding.top, padding.right, padding.bottom); + } } diff --git a/src/com/android/launcher3/ItemInfo.java b/src/com/android/launcher3/ItemInfo.java index c726fb43f..8f96f74eb 100644 --- a/src/com/android/launcher3/ItemInfo.java +++ b/src/com/android/launcher3/ItemInfo.java @@ -124,6 +124,12 @@ public class ItemInfo { } ItemInfo(ItemInfo info) { + copyFrom(info); + // tempdebug: + LauncherModel.checkItemInfo(this); + } + + public void copyFrom(ItemInfo info) { id = info.id; cellX = info.cellX; cellY = info.cellY; @@ -134,8 +140,6 @@ public class ItemInfo { container = info.container; user = info.user; contentDescription = info.contentDescription; - // tempdebug: - LauncherModel.checkItemInfo(this); } public Intent getIntent() { diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 0ab665d74..5eedc8a3a 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -65,7 +65,6 @@ import android.os.Handler; import android.os.Message; import android.os.StrictMode; import android.os.SystemClock; -import android.provider.Settings; import android.speech.RecognizerIntent; import android.text.Selection; import android.text.SpannableStringBuilder; @@ -92,7 +91,9 @@ import android.view.Window; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; +import android.view.animation.LinearInterpolator; import android.view.inputmethod.InputMethodManager; import android.widget.Advanceable; import android.widget.FrameLayout; @@ -153,6 +154,7 @@ public class Launcher extends Activity private static final int REQUEST_PICK_WALLPAPER = 10; private static final int REQUEST_BIND_APPWIDGET = 11; + private static final int REQUEST_RECONFIGURE_APPWIDGET = 12; /** * IntentStarter uses request codes starting with this. This must be greater than all activity @@ -752,6 +754,9 @@ public class Launcher extends Activity case REQUEST_CREATE_APPWIDGET: completeAddAppWidget(args.appWidgetId, args.container, screenId, null, null); break; + case REQUEST_RECONFIGURE_APPWIDGET: + completeRestoreAppWidget(args.appWidgetId); + break; } // Before adding this resetAddInfo(), after a shortcut was added to a workspace screen, // if you turned the screen off and then back while in All Apps, Launcher would not @@ -854,6 +859,21 @@ public class Launcher extends Activity return; } + if (requestCode == REQUEST_RECONFIGURE_APPWIDGET) { + if (resultCode == RESULT_OK) { + // Update the widget view. + PendingAddArguments args = preparePendingAddArgs(requestCode, data, + pendingAddWidgetId, mPendingAddInfo); + if (workspaceLocked) { + sPendingAddItem = args; + } else { + completeAdd(args); + } + } + // Leave the widget in the pending state if the user canceled the configure. + return; + } + // The pattern used here is that a user PICKs a specific application, // which, depending on the target, might need to CREATE the actual target. @@ -2446,6 +2466,10 @@ public class Launcher extends Activity } } else if (v == mAllAppsButton) { onClickAllAppsButton(v); + } else if (tag instanceof LauncherAppWidgetInfo) { + if (v instanceof PendingAppWidgetHostView) { + onClickPendingWidget((PendingAppWidgetHostView) v); + } } } @@ -2454,6 +2478,27 @@ public class Launcher extends Activity } /** + * Event handler for the app widget view which has not fully restored. + */ + public void onClickPendingWidget(PendingAppWidgetHostView v) { + if (v.isReadyForClickSetup()) { + LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) v.getTag(); + int widgetId = info.appWidgetId; + AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(widgetId); + if (appWidgetInfo != null) { + mPendingAddWidgetInfo = appWidgetInfo; + mPendingAddInfo.copyFrom(info); + mPendingAddWidgetId = widgetId; + + Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE); + intent.setComponent(appWidgetInfo.configure); + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, info.appWidgetId); + Utilities.startActivityForResultSafely(this, intent, REQUEST_RECONFIGURE_APPWIDGET); + } + } + } + + /** * Event handler for the search button * * @param v The view that was clicked. @@ -3065,16 +3110,6 @@ public class Launcher extends Activity return (mState == State.APPS_CUSTOMIZE) || (mOnResumeState == State.APPS_CUSTOMIZE); } - /** - * Helper method for the cameraZoomIn/cameraZoomOut animations - * @param view The view being animated - * @param scaleFactor The scale factor used for the zoom - */ - private void setPivotsForZoom(View view, float scaleFactor) { - view.setPivotX(view.getWidth() / 2.0f); - view.setPivotY(view.getHeight() / 2.0f); - } - private void setWorkspaceBackground(boolean workspace) { mLauncherView.setBackground(workspace ? mWorkspaceBackgroundDrawable : null); @@ -3185,6 +3220,8 @@ public class Launcher extends Activity final int duration = res.getInteger(R.integer.config_appsCustomizeZoomInTime); final int fadeDuration = res.getInteger(R.integer.config_appsCustomizeFadeInTime); final int revealDuration = res.getInteger(R.integer.config_appsCustomizeRevealTime); + final int itemsAlphaStagger = + res.getInteger(R.integer.config_appsCustomizeItemsAlphaStagger); final float scale = (float) res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor); final View fromView = mWorkspace; @@ -3192,8 +3229,6 @@ public class Launcher extends Activity final int startDelay = res.getInteger(R.integer.config_workspaceAppsCustomizeAnimationStagger); - setPivotsForZoom(toView, scale); - Workspace.State workspaceState = contentType == AppsCustomizePagedView.ContentType.Widgets ? Workspace.State.OVERVIEW_HIDDEN : Workspace.State.NORMAL_HIDDEN; Animator workspaceAnim = @@ -3205,146 +3240,103 @@ public class Launcher extends Activity } if (animated) { - if (!material) { - toView.setScaleX(scale); - toView.setScaleY(scale); - final LauncherViewPropertyAnimator scaleAnim = - new LauncherViewPropertyAnimator(toView); - scaleAnim. - scaleX(1f).scaleY(1f). - setDuration(duration). - setInterpolator(new Workspace.ZoomOutInterpolator()); + mStateAnimation = LauncherAnimUtils.createAnimatorSet(); - toView.setVisibility(View.VISIBLE); - toView.setAlpha(0f); - final ObjectAnimator alphaAnim = LauncherAnimUtils - .ofFloat(toView, "alpha", 0f, 1f) - .setDuration(fadeDuration); - alphaAnim.setInterpolator(new DecelerateInterpolator(1.5f)); - alphaAnim.addUpdateListener(new AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - if (animation == null) { - throw new RuntimeException("animation is null"); - } - float t = (Float) animation.getAnimatedValue(); - dispatchOnLauncherTransitionStep(fromView, t); - dispatchOnLauncherTransitionStep(toView, t); - } - }); + final AppsCustomizePagedView content = (AppsCustomizePagedView) + toView.findViewById(R.id.apps_customize_pane_content); - // toView should appear right at the end of the workspace shrink - // animation - mStateAnimation = LauncherAnimUtils.createAnimatorSet(); - mStateAnimation.play(scaleAnim).after(startDelay); - mStateAnimation.play(alphaAnim).after(startDelay); + final View page = content.getPageAt(content.getCurrentPage()); + final View revealView = toView.findViewById(R.id.fake_page); - mStateAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - // Prepare the position - toView.setTranslationX(0.0f); - toView.setTranslationY(0.0f); - toView.setVisibility(View.VISIBLE); - toView.bringToFront(); - } - @Override - public void onAnimationEnd(Animator animation) { - dispatchOnLauncherTransitionEnd(fromView, animated, false); - dispatchOnLauncherTransitionEnd(toView, animated, false); - - // Hide the search bar - if (mSearchDropTargetBar != null) { - mSearchDropTargetBar.hideSearchBar(false); - } - } - }); + if (contentType == AppsCustomizePagedView.ContentType.Widgets) { + revealView.setBackground(res.getDrawable(R.drawable.quantum_panel_dark)); } else { - int width = toView.getMeasuredWidth(); - int height = toView.getMeasuredHeight(); - float revealRadius = (float) Math.sqrt((width * width) / 4 + height * height); - - mStateAnimation = LauncherAnimUtils.createAnimatorSet(); - - AppsCustomizePagedView content = (AppsCustomizePagedView) - toView.findViewById(R.id.apps_customize_pane_content); - - View page = content.getPageAt(content.getCurrentPage()); - View revealView = content; - - float yDrift = height / 2f - 400; - - LauncherViewPropertyAnimator panelAlphaAndDrift = - new LauncherViewPropertyAnimator(revealView); - revealView.setTranslationY(yDrift); - revealView.setAlpha(0.3f); - panelAlphaAndDrift.alpha(1) - .translationY(0) - .setDuration(revealDuration) - .setInterpolator(new LogDecelerateInterpolator(100, 0)); - - mStateAnimation.play(panelAlphaAndDrift); - - if (page instanceof CellLayout) { - CellLayout cellLayout = (CellLayout) page; - cellLayout.enableHardwareLayer(true); - - View iconsView = cellLayout.getShortcutsAndWidgets(); - iconsView.setAlpha(0f); - - LauncherViewPropertyAnimator iconsAlpha = - new LauncherViewPropertyAnimator(iconsView); - iconsAlpha.alpha(1f) - .setDuration(revealDuration - 100) - .setInterpolator(new LogDecelerateInterpolator(100, 0)); - mStateAnimation.play(iconsAlpha); - } + revealView.setBackground(res.getDrawable(R.drawable.quantum_panel)); + } - View pageIndicators = toView.findViewById(R.id.apps_customize_page_indicator); - pageIndicators.setAlpha(0f); - final LauncherViewPropertyAnimator indicatorsAlpha = - new LauncherViewPropertyAnimator(pageIndicators); - indicatorsAlpha.alpha(1f); - indicatorsAlpha.setDuration(revealDuration); - mStateAnimation.play(indicatorsAlpha); + // Hide the real page background, and swap in the fake one + revealView.setVisibility(View.VISIBLE); + content.setPageBackgroundsVisible(false); + + int width = revealView.getMeasuredWidth(); + int height = revealView.getMeasuredHeight(); + + float revealRadius = (float) Math.sqrt((width * width) / 4 + (height * height) / 4); + float yDrift = height / 2f; + + revealView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + PropertyValuesHolder panelAlpha = PropertyValuesHolder.ofFloat("alpha", 0.4f, 1f); + PropertyValuesHolder panelDrift = + PropertyValuesHolder.ofFloat("translationY", yDrift, 0f); + + ObjectAnimator panelAlphaAndDrift = + ObjectAnimator.ofPropertyValuesHolder(revealView, panelAlpha, panelDrift); + panelAlphaAndDrift.setDuration(revealDuration); + panelAlphaAndDrift.setInterpolator(new LogDecelerateInterpolator(100, 0)); + + mStateAnimation.play(panelAlphaAndDrift); + + if (page != null) { + page.setVisibility(View.VISIBLE); + page.setLayerType(View.LAYER_TYPE_HARDWARE, null); + + ObjectAnimator pageDrift = ObjectAnimator.ofFloat(page, "translationY", yDrift, 0); + pageDrift.setDuration(revealDuration); + pageDrift.setInterpolator(new LogDecelerateInterpolator(100, 0)); + mStateAnimation.play(pageDrift); + + // TODO (adamcohen): remove this 0.01f hack once fw is fixed + // it's there to work around a framework bug (16918357) + page.setAlpha(0.01f); + ObjectAnimator itemsAlpha = ObjectAnimator.ofFloat(page, "alpha", 0.01f, 1f); + itemsAlpha.setDuration(revealDuration); + itemsAlpha.setInterpolator(new AccelerateInterpolator(1.5f)); + itemsAlpha.setStartDelay(itemsAlphaStagger); + mStateAnimation.play(itemsAlpha); + } - width = revealView.getMeasuredWidth(); + View pageIndicators = toView.findViewById(R.id.apps_customize_page_indicator); + pageIndicators.setAlpha(0.01f); + ObjectAnimator indicatorsAlpha = + ObjectAnimator.ofFloat(pageIndicators, "alpha", 1f); + indicatorsAlpha.setDuration(revealDuration); + mStateAnimation.play(indicatorsAlpha); - Animator reveal = + if (material) { + ValueAnimator reveal = (ValueAnimator) ViewAnimationUtils.createCircularReveal(revealView, width / 2, - height / 2 + 100, 0f, revealRadius); + height / 2, 0f, revealRadius); reveal.setDuration(revealDuration); reveal.setInterpolator(new LogDecelerateInterpolator(100, 0)); - - toView.setTranslationX(0); - toView.setTranslationY(0); - toView.setAlpha(1f); - // toView should appear right at the end of the workspace shrink - // animation mStateAnimation.play(reveal); + } - reveal.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationStart(Animator animation) { - // Prepare the position - toView.bringToFront(); - toView.setVisibility(View.VISIBLE); - } - }); + mStateAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + dispatchOnLauncherTransitionEnd(fromView, animated, false); + dispatchOnLauncherTransitionEnd(toView, animated, false); - mStateAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - dispatchOnLauncherTransitionEnd(fromView, animated, false); - dispatchOnLauncherTransitionEnd(toView, animated, false); + revealView.setVisibility(View.INVISIBLE); + revealView.setLayerType(View.LAYER_TYPE_NONE, null); + if (page != null) { + page.setLayerType(View.LAYER_TYPE_NONE, null); + } + content.setPageBackgroundsVisible(true); - // Hide the search bar - if (mSearchDropTargetBar != null) { - mSearchDropTargetBar.hideSearchBar(false); - } + // Hide the search bar + if (mSearchDropTargetBar != null) { + mSearchDropTargetBar.hideSearchBar(false); } - }); - } + } + + @Override + public void onAnimationStart(Animator animation) { + // Prepare the position + toView.bringToFront(); + toView.setVisibility(View.VISIBLE); + } + }); boolean delayAnim = false; if (workspaceAnim != null) { @@ -3368,13 +3360,14 @@ public class Launcher extends Activity // we waited for a layout/draw pass if (mStateAnimation != stateAnimation) return; - setPivotsForZoom(toView, scale); dispatchOnLauncherTransitionStart(fromView, animated, false); dispatchOnLauncherTransitionStart(toView, animated, false); LauncherAnimUtils.startAnimationAfterNextDraw(mStateAnimation, toView); } }; if (delayAnim) { + toView.bringToFront(); + toView.setVisibility(View.VISIBLE); final ViewTreeObserver observer = toView.getViewTreeObserver(); observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { public void onGlobalLayout() { @@ -3429,6 +3422,8 @@ public class Launcher extends Activity final int duration = res.getInteger(R.integer.config_appsCustomizeZoomOutTime); final int fadeOutDuration = res.getInteger(R.integer.config_appsCustomizeFadeOutTime); final int revealDuration = res.getInteger(R.integer.config_appsCustomizeRevealTime); + final int itemsAlphaStagger = + res.getInteger(R.integer.config_appsCustomizeItemsAlphaStagger); final float scaleFactor = (float) res.getInteger(R.integer.config_appsCustomizeZoomScaleFactor); @@ -3445,116 +3440,94 @@ public class Launcher extends Activity toState, animated); } - setPivotsForZoom(fromView, scaleFactor); showHotseat(animated); if (animated) { - if (!material) { - final LauncherViewPropertyAnimator scaleAnim = - new LauncherViewPropertyAnimator(fromView); - scaleAnim. - scaleX(scaleFactor).scaleY(scaleFactor). - setDuration(duration). - setInterpolator(new Workspace.ZoomInInterpolator()); - - final ObjectAnimator alphaAnim = LauncherAnimUtils - .ofFloat(fromView, "alpha", 1f, 0f) - .setDuration(fadeOutDuration); - alphaAnim.setInterpolator(new AccelerateDecelerateInterpolator()); - alphaAnim.addUpdateListener(new AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - float t = 1f - (Float) animation.getAnimatedValue(); - dispatchOnLauncherTransitionStep(fromView, t); - dispatchOnLauncherTransitionStep(toView, t); - } - }); + mStateAnimation = LauncherAnimUtils.createAnimatorSet(); - mStateAnimation = LauncherAnimUtils.createAnimatorSet(); + final AppsCustomizePagedView content = (AppsCustomizePagedView) + fromView.findViewById(R.id.apps_customize_pane_content); - dispatchOnLauncherTransitionPrepare(fromView, animated, true); - dispatchOnLauncherTransitionPrepare(toView, animated, true); - mAppsCustomizeContent.stopScrolling(); + final View page = content.getPageAt(content.getNextPage()); + final View revealView = fromView.findViewById(R.id.fake_page); - mStateAnimation.playTogether(scaleAnim, alphaAnim); + AppsCustomizePagedView.ContentType contentType = content.getContentType(); + if (contentType == AppsCustomizePagedView.ContentType.Widgets) { + revealView.setBackground(res.getDrawable(R.drawable.quantum_panel_dark)); } else { - mStateAnimation = LauncherAnimUtils.createAnimatorSet(); - - int width = fromView.getMeasuredWidth(); - int height = fromView.getMeasuredHeight(); - float revealRadius = (float) Math.sqrt((width * width) / 4 + height * height); + revealView.setBackground(res.getDrawable(R.drawable.quantum_panel)); + } - AppsCustomizePagedView content = (AppsCustomizePagedView) - fromView.findViewById(R.id.apps_customize_pane_content); + int width = revealView.getMeasuredWidth(); + int height = revealView.getMeasuredHeight(); + float revealRadius = (float) Math.sqrt((width * width) / 4 + (height * height) / 4); - final View page = content.getPageAt(content.getNextPage()); - View revealView = page; + // Hide the real page background, and swap in the fake one + revealView.setVisibility(View.VISIBLE); + content.setPageBackgroundsVisible(false); - float yDrift = height / 2f - 400; + float yDrift = height / 2f; - LauncherViewPropertyAnimator panelAlphaAndDrift = - new LauncherViewPropertyAnimator(revealView); - revealView.setTranslationY(0); - revealView.setAlpha(1); - panelAlphaAndDrift.alpha(0) - .translationY(yDrift) - .setDuration(revealDuration) - .setInterpolator(new LogDecelerateInterpolator(100, 0)); + revealView.setLayerType(View.LAYER_TYPE_HARDWARE, null); - mStateAnimation.play(panelAlphaAndDrift); + PropertyValuesHolder panelAlpha = PropertyValuesHolder.ofFloat(View.ALPHA, 1f, 0f); + PropertyValuesHolder panelDrift = + PropertyValuesHolder.ofFloat("translationY", 0, yDrift); + ObjectAnimator panelAlphaAndDrift = + ObjectAnimator.ofPropertyValuesHolder(revealView, panelAlpha, panelDrift); + panelAlphaAndDrift.setDuration(revealDuration); - if (page instanceof CellLayout) { - final CellLayout cellLayout = (CellLayout) page; - cellLayout.enableHardwareLayer(true); + panelAlphaAndDrift.setInterpolator(new LogDecelerateInterpolator(100, 0)); + panelAlphaAndDrift.setStartDelay(itemsAlphaStagger); - final View iconsView = cellLayout.getShortcutsAndWidgets(); + mStateAnimation.play(panelAlphaAndDrift); - LauncherViewPropertyAnimator iconsAlpha = - new LauncherViewPropertyAnimator(iconsView); - iconsAlpha.alpha(0f) - .setDuration(revealDuration - 100) - .setInterpolator(new LogDecelerateInterpolator(100, 0)); + if (page != null) { + page.setLayerType(View.LAYER_TYPE_HARDWARE, null); - mStateAnimation.play(iconsAlpha); + ObjectAnimator pageDrift = ObjectAnimator.ofFloat(page, "translationY", 0, yDrift); + pageDrift.setDuration(revealDuration); + pageDrift.setInterpolator(new LogDecelerateInterpolator(100, 0)); + pageDrift.setStartDelay(itemsAlphaStagger); + mStateAnimation.play(pageDrift); - mStateAnimation.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - cellLayout.setTranslationY(0); - cellLayout.setAlpha(1f); - iconsView.setAlpha(1f); - } - }); - } + page.setAlpha(1f); + ObjectAnimator itemsAlpha = ObjectAnimator.ofFloat(page, View.ALPHA, 1f, 0f); + itemsAlpha.setDuration(revealDuration); + itemsAlpha.setInterpolator(new LogDecelerateInterpolator(100, 0)); + mStateAnimation.play(itemsAlpha); + } - View pageIndicators = fromView.findViewById(R.id.apps_customize_page_indicator); - final LauncherViewPropertyAnimator indicatorsAlpha = - new LauncherViewPropertyAnimator(pageIndicators); - indicatorsAlpha.alpha(0f); - indicatorsAlpha.setDuration(revealDuration); - indicatorsAlpha.setInterpolator(new DecelerateInterpolator(1.5f)); - mStateAnimation.play(indicatorsAlpha); + View pageIndicators = fromView.findViewById(R.id.apps_customize_page_indicator); + pageIndicators.setAlpha(1f); + ObjectAnimator indicatorsAlpha = + ObjectAnimator.ofFloat(pageIndicators, "alpha", 0f); + indicatorsAlpha.setDuration(revealDuration); + indicatorsAlpha.setInterpolator(new DecelerateInterpolator(1.5f)); + mStateAnimation.play(indicatorsAlpha); - width = revealView.getMeasuredWidth(); + width = revealView.getMeasuredWidth(); + if (material) { Animator reveal = ViewAnimationUtils.createCircularReveal(revealView, width / 2, height / 2 + 100, revealRadius, 0f); reveal.setInterpolator(new LogDecelerateInterpolator(100, 0)); reveal.setDuration(revealDuration); + reveal.setStartDelay(itemsAlphaStagger); reveal.addListener(new AnimatorListenerAdapter() { - @Override public void onAnimationEnd(Animator animation) { - fromView.setVisibility(View.GONE); + revealView.setVisibility(View.INVISIBLE); } }); - dispatchOnLauncherTransitionPrepare(fromView, animated, true); - dispatchOnLauncherTransitionPrepare(toView, animated, true); - mAppsCustomizeContent.stopScrolling(); - mStateAnimation.play(reveal); } + + dispatchOnLauncherTransitionPrepare(fromView, animated, true); + dispatchOnLauncherTransitionPrepare(toView, animated, true); + mAppsCustomizeContent.stopScrolling(); + if (workspaceAnim != null) { mStateAnimation.play(workspaceAnim); } @@ -3568,6 +3541,12 @@ public class Launcher extends Activity if (onCompleteRunnable != null) { onCompleteRunnable.run(); } + + revealView.setLayerType(View.LAYER_TYPE_NONE, null); + if (page != null) { + page.setLayerType(View.LAYER_TYPE_NONE, null); + } + content.setPageBackgroundsVisible(true); mAppsCustomizeContent.updateCurrentPageScroll(); } }); @@ -4398,7 +4377,64 @@ public class Launcher extends Activity } final Workspace workspace = mWorkspace; - final AppWidgetProviderInfo appWidgetInfo; + AppWidgetProviderInfo appWidgetInfo; + if (((item.restoreStatus & LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0) && + ((item.restoreStatus & LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) != 0)) { + + appWidgetInfo = mModel.findAppWidgetProviderInfoWithComponent(this, item.providerName); + if (appWidgetInfo == null) { + if (DEBUG_WIDGETS) { + Log.d(TAG, "Removing restored widget: id=" + item.appWidgetId + + " belongs to component " + item.providerName + + ", as the povider is null"); + } + LauncherModel.deleteItemFromDatabase(this, item); + return; + } + // Note: This assumes that the id remap broadcast is received before this step. + // If that is not the case, the id remap will be ignored and user may see the + // click to setup view. + PendingAddWidgetInfo pendingInfo = new PendingAddWidgetInfo(appWidgetInfo, null, null); + pendingInfo.spanX = item.spanX; + pendingInfo.spanY = item.spanY; + pendingInfo.minSpanX = item.minSpanX; + pendingInfo.minSpanY = item.minSpanY; + Bundle options = + AppsCustomizePagedView.getDefaultOptionsForWidget(this, pendingInfo); + + boolean success = false; + int newWidgetId = mAppWidgetHost.allocateAppWidgetId(); + if (options != null) { + success = mAppWidgetManager.bindAppWidgetIdIfAllowed(newWidgetId, + appWidgetInfo.provider, options); + } else { + success = mAppWidgetManager.bindAppWidgetIdIfAllowed(newWidgetId, + appWidgetInfo.provider); + } + + // TODO consider showing a permission dialog when the widget is clicked. + if (!success) { + mAppWidgetHost.deleteAppWidgetId(newWidgetId); + if (DEBUG_WIDGETS) { + Log.d(TAG, "Removing restored widget: id=" + item.appWidgetId + + " belongs to component " + item.providerName + + ", as the launcher is unable to bing a new widget id"); + } + LauncherModel.deleteItemFromDatabase(this, item); + return; + } + + item.appWidgetId = newWidgetId; + + // If the widget has a configure activity, it is still needs to set it up, otherwise + // the widget is ready to go. + item.restoreStatus = (appWidgetInfo.configure == null) + ? LauncherAppWidgetInfo.RESTORE_COMPLETED + : LauncherAppWidgetInfo.FLAG_UI_NOT_READY; + + LauncherModel.updateItemInDatabase(this, item); + } + if (item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) { final int appWidgetId = item.appWidgetId; appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(appWidgetId); @@ -4409,8 +4445,9 @@ public class Launcher extends Activity item.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo); } else { appWidgetInfo = null; - item.hostView = new LauncherAppWidgetHostView(this, false); + item.hostView = new PendingAppWidgetHostView(this, item.restoreStatus); item.hostView.updateAppWidget(null); + item.hostView.setOnClickListener(this); } item.hostView.setTag(item); @@ -4428,6 +4465,29 @@ public class Launcher extends Activity } } + /** + * Restores a pending widget. + * + * @param appWidgetId The app widget id + * @param cellInfo The position on screen where to create the widget. + */ + private void completeRestoreAppWidget(final int appWidgetId) { + LauncherAppWidgetHostView view = mWorkspace.getWidgetForAppWidgetId(appWidgetId); + if ((view == null) || !(view instanceof PendingAppWidgetHostView)) { + Log.e(TAG, "Widget update called, when the widget no longer exists."); + return; + } + + PendingAppWidgetHostView pendingView = (PendingAppWidgetHostView) view; + pendingView.setStatus(LauncherAppWidgetInfo.RESTORE_COMPLETED); + + LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) pendingView.getTag(); + info.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED; + + mWorkspace.reinflateWidgetsIfNecessary(); + LauncherModel.updateItemInDatabase(this, info); + } + public void onPageBoundSynchronously(int page) { mSynchronouslyBoundPages.add(page); } diff --git a/src/com/android/launcher3/LauncherAppWidgetHostView.java b/src/com/android/launcher3/LauncherAppWidgetHostView.java index 7eb005255..e39727b17 100644 --- a/src/com/android/launcher3/LauncherAppWidgetHostView.java +++ b/src/com/android/launcher3/LauncherAppWidgetHostView.java @@ -18,7 +18,6 @@ package com.android.launcher3; import android.appwidget.AppWidgetHostView; import android.content.Context; -import android.os.Bundle; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; @@ -32,36 +31,22 @@ import com.android.launcher3.DragLayer.TouchCompleteListener; * {@inheritDoc} */ public class LauncherAppWidgetHostView extends AppWidgetHostView implements TouchCompleteListener { + + LayoutInflater mInflater; + private CheckLongPressHelper mLongPressHelper; - private LayoutInflater mInflater; private Context mContext; private int mPreviousOrientation; private DragLayer mDragLayer; private float mSlop; - private boolean mWidgetReady; - public LauncherAppWidgetHostView(Context context) { - this(context, true); - } - - public LauncherAppWidgetHostView(Context context, boolean widgetReady) { super(context); mContext = context; mLongPressHelper = new CheckLongPressHelper(this); mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mDragLayer = ((Launcher) context).getDragLayer(); - mWidgetReady = widgetReady; - } - - @Override - public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth, - int maxHeight) { - // If the widget is not yet ready, the app widget size cannot be updated. - if (mWidgetReady) { - super.updateAppWidgetSize(newOptions, minWidth, minHeight, maxWidth, maxHeight); - } } @Override @@ -70,22 +55,14 @@ public class LauncherAppWidgetHostView extends AppWidgetHostView implements Touc } @Override - protected View getDefaultView() { - if (mWidgetReady) { - return super.getDefaultView(); - } else { - return mInflater.inflate(R.layout.appwidget_not_ready, this, false); - } - } - - @Override public void updateAppWidget(RemoteViews remoteViews) { // Store the orientation in which the widget was inflated mPreviousOrientation = mContext.getResources().getConfiguration().orientation; super.updateAppWidget(remoteViews); } - public boolean orientationChangedSincedInflation() { + public boolean isReinflateRequired() { + // Re-inflate is required if the orientation has changed since last inflated. int orientation = mContext.getResources().getConfiguration().orientation; if (mPreviousOrientation != orientation) { return true; diff --git a/src/com/android/launcher3/LauncherAppWidgetInfo.java b/src/com/android/launcher3/LauncherAppWidgetInfo.java index b3ac12b37..c1535abae 100644 --- a/src/com/android/launcher3/LauncherAppWidgetInfo.java +++ b/src/com/android/launcher3/LauncherAppWidgetInfo.java @@ -33,12 +33,17 @@ public class LauncherAppWidgetInfo extends ItemInfo { /** * This is set during the package backup creation. */ - public static final int RESTORE_REMAP_PENDING = 1; + public static final int FLAG_ID_NOT_VALID = 1; /** - * Widget provider is not yet installed. + * Indicates that the provider is not available yet. */ - public static final int RESTORE_PROVIDER_PENDING = 2; + public static final int FLAG_PROVIDER_NOT_READY = 2; + + /** + * Indicates that the widget UI is not yet ready, and user needs to set it up again. + */ + public static final int FLAG_UI_NOT_READY = 4; /** * Indicates that the widget hasn't been instantiated yet. @@ -89,6 +94,7 @@ public class LauncherAppWidgetInfo extends ItemInfo { super.onAddToDatabase(context, values); values.put(LauncherSettings.Favorites.APPWIDGET_ID, appWidgetId); values.put(LauncherSettings.Favorites.APPWIDGET_PROVIDER, providerName.flattenToString()); + values.put(LauncherSettings.Favorites.RESTORED, restoreStatus); } /** @@ -121,6 +127,10 @@ public class LauncherAppWidgetInfo extends ItemInfo { } public final boolean isWidgetIdValid() { - return restoreStatus != RESTORE_REMAP_PENDING; + return (restoreStatus & FLAG_ID_NOT_VALID) == 0; + } + + public final boolean hasRestoreFlag(int flag) { + return (restoreStatus & flag) == flag; } } diff --git a/src/com/android/launcher3/LauncherBackupHelper.java b/src/com/android/launcher3/LauncherBackupHelper.java index 5663314ea..aecf9b019 100644 --- a/src/com/android/launcher3/LauncherBackupHelper.java +++ b/src/com/android/launcher3/LauncherBackupHelper.java @@ -874,20 +874,25 @@ public class LauncherBackupHelper implements BackupHelper { values.put(Favorites.INTENT, favorite.intent); } values.put(Favorites.ITEM_TYPE, favorite.itemType); - if (favorite.itemType == Favorites.ITEM_TYPE_APPWIDGET) { - if (!TextUtils.isEmpty(favorite.appWidgetProvider)) { - values.put(Favorites.APPWIDGET_PROVIDER, favorite.appWidgetProvider); - } - values.put(Favorites.APPWIDGET_ID, favorite.appWidgetId); - } UserHandleCompat myUserHandle = UserHandleCompat.myUserHandle(); long userSerialNumber = UserManagerCompat.getInstance(mContext).getSerialNumberForUser(myUserHandle); values.put(LauncherSettings.Favorites.PROFILE_ID, userSerialNumber); - // Let LauncherModel know we've been here. - values.put(LauncherSettings.Favorites.RESTORED, 1); + if (favorite.itemType == Favorites.ITEM_TYPE_APPWIDGET) { + if (!TextUtils.isEmpty(favorite.appWidgetProvider)) { + values.put(Favorites.APPWIDGET_PROVIDER, favorite.appWidgetProvider); + } + values.put(Favorites.APPWIDGET_ID, favorite.appWidgetId); + values.put(LauncherSettings.Favorites.RESTORED, + LauncherAppWidgetInfo.FLAG_ID_NOT_VALID | + LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY | + LauncherAppWidgetInfo.FLAG_UI_NOT_READY); + } else { + // Let LauncherModel know we've been here. + values.put(LauncherSettings.Favorites.RESTORED, 1); + } return values; } diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 86edaef44..5c668d65f 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -2128,47 +2128,59 @@ public class LauncherModel extends BroadcastReceiver int appWidgetId = c.getInt(appWidgetIdIndex); String savedProvider = c.getString(appWidgetProviderIndex); id = c.getLong(idIndex); + final ComponentName component = + ComponentName.unflattenFromString(savedProvider); final int restoreStatus = c.getInt(restoredIndex); - final boolean restorePending = Utilities.isLmp() - && (restoreStatus == - LauncherAppWidgetInfo.RESTORE_REMAP_PENDING); - final boolean providerPending = Utilities.isLmp() - && (restoreStatus == - LauncherAppWidgetInfo.RESTORE_PROVIDER_PENDING); - - // Do not try to get the provider if restore is pending, as the - // widget id is invalid, and it might point to some other provider. - final AppWidgetProviderInfo provider = restorePending ? null - : widgets.getAppWidgetInfo(appWidgetId); - boolean providerValid = isValidProvider(provider); - - // Skip provider check, - // 1. when the widget id re-map is pending - // 2. provider is pending install for a restored widget - if (!isSafeMode && !providerPending && !restorePending - && !providerValid) { + final boolean isIdValid = (restoreStatus & + LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) == 0; + + final boolean wasProviderReady = (restoreStatus & + LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0; + + final AppWidgetProviderInfo provider = isIdValid + ? widgets.getAppWidgetInfo(appWidgetId) + : findAppWidgetProviderInfoWithComponent(context, component); + + final boolean isProviderReady = isValidProvider(provider); + if (!isSafeMode && wasProviderReady && !isProviderReady) { String log = "Deleting widget that isn't installed anymore: " - + "id=" + id + " appWidgetId=" + appWidgetId; + + "id=" + id + " appWidgetId=" + appWidgetId; Log.e(TAG, log); Launcher.addDumpLog(TAG, log, false); itemsToRemove.add(id); } else { - if (providerValid) { + if (isProviderReady) { appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId, provider.provider); int[] minSpan = Launcher.getMinSpanForWidget(context, provider); appWidgetInfo.minSpanX = minSpan[0]; appWidgetInfo.minSpanY = minSpan[1]; + + int status = restoreStatus; + if (!wasProviderReady) { + // If provider was not previously ready, update the + // status and UI flag. + + // Id would be valid only if the widget restore broadcast was received. + if (isIdValid) { + status = LauncherAppWidgetInfo.RESTORE_COMPLETED; + } else { + status &= ~LauncherAppWidgetInfo + .FLAG_PROVIDER_NOT_READY; + } + } + appWidgetInfo.restoreStatus = status; } else { Log.v(TAG, "Widget restore pending id=" + id + " appWidgetId=" + appWidgetId + " status =" + restoreStatus); appWidgetInfo = new LauncherAppWidgetInfo(appWidgetId, - ComponentName.unflattenFromString(savedProvider)); + component); appWidgetInfo.restoreStatus = restoreStatus; } + appWidgetInfo.id = id; appWidgetInfo.screenId = c.getInt(screenIndex); appWidgetInfo.cellX = c.getInt(cellXIndex); @@ -2195,15 +2207,15 @@ public class LauncherModel extends BroadcastReceiver break; } - if (providerValid) { + if (isProviderReady) { String providerName = provider.provider.flattenToString(); - - if (!providerName.equals(savedProvider) || providerPending) { + if (!providerName.equals(savedProvider) || + (appWidgetInfo.restoreStatus != restoreStatus)) { ContentValues values = new ContentValues(); values.put(LauncherSettings.Favorites.APPWIDGET_PROVIDER, providerName); values.put(LauncherSettings.Favorites.RESTORED, - LauncherAppWidgetInfo.RESTORE_COMPLETED); + appWidgetInfo.restoreStatus); String where = BaseColumns._ID + "= ?"; String[] args = {Long.toString(id)}; contentResolver.update(contentUri, values, where, args); diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java index 1037d9809..90a6b1598 100644 --- a/src/com/android/launcher3/PagedView.java +++ b/src/com/android/launcher3/PagedView.java @@ -152,16 +152,11 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc protected int mTouchState = TOUCH_STATE_REST; protected boolean mForceScreenScrolled = false; - protected OnLongClickListener mLongClickListener; protected int mTouchSlop; private int mPagingTouchSlop; private int mMaximumVelocity; - protected int mPageLayoutPaddingTop; - protected int mPageLayoutPaddingBottom; - protected int mPageLayoutPaddingLeft; - protected int mPageLayoutPaddingRight; protected int mPageLayoutWidthGap; protected int mPageLayoutHeightGap; protected int mCellCountX = 0; @@ -283,14 +278,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PagedView, defStyle, 0); - mPageLayoutPaddingTop = a.getDimensionPixelSize( - R.styleable.PagedView_pageLayoutPaddingTop, 0); - mPageLayoutPaddingBottom = a.getDimensionPixelSize( - R.styleable.PagedView_pageLayoutPaddingBottom, 0); - mPageLayoutPaddingLeft = a.getDimensionPixelSize( - R.styleable.PagedView_pageLayoutPaddingLeft, 0); - mPageLayoutPaddingRight = a.getDimensionPixelSize( - R.styleable.PagedView_pageLayoutPaddingRight, 0); mPageLayoutWidthGap = a.getDimensionPixelSize( R.styleable.PagedView_pageLayoutWidthGap, 0); mPageLayoutHeightGap = a.getDimensionPixelSize( @@ -339,8 +326,9 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc // Hook up the page indicator ViewGroup parent = (ViewGroup) getParent(); + ViewGroup grandParent = (ViewGroup) parent.getParent(); if (mPageIndicator == null && mPageIndicatorViewId > -1) { - mPageIndicator = (PageIndicator) parent.findViewById(mPageIndicatorViewId); + mPageIndicator = (PageIndicator) grandParent.findViewById(mPageIndicatorViewId); mPageIndicator.removeAllMarkers(mAllowPagedViewAnimations); ArrayList<PageIndicator.PageMarkerResources> markers = diff --git a/src/com/android/launcher3/PagedViewGridLayout.java b/src/com/android/launcher3/PagedViewGridLayout.java index b28686113..f69fa562d 100644 --- a/src/com/android/launcher3/PagedViewGridLayout.java +++ b/src/com/android/launcher3/PagedViewGridLayout.java @@ -56,18 +56,6 @@ public class PagedViewGridLayout extends GridLayout implements Page { } } - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - // PagedView currently has issues with different-sized pages since it calculates the - // offset of each page to scroll to before it updates the actual size of each page - // (which can change depending on the content if the contents aren't a fixed size). - // We work around this by having a minimum size on each widget page). - int widthSpecSize = Math.min(getSuggestedMinimumWidth(), - MeasureSpec.getSize(widthMeasureSpec)); - int widthSpecMode = MeasureSpec.EXACTLY; - super.onMeasure(MeasureSpec.makeMeasureSpec(widthSpecSize, widthSpecMode), - heightMeasureSpec); - } - @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); diff --git a/src/com/android/launcher3/PendingAppWidgetHostView.java b/src/com/android/launcher3/PendingAppWidgetHostView.java new file mode 100644 index 000000000..048e9f8c3 --- /dev/null +++ b/src/com/android/launcher3/PendingAppWidgetHostView.java @@ -0,0 +1,78 @@ +package com.android.launcher3; + +import android.content.Context; +import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.TextView; + +public class PendingAppWidgetHostView extends LauncherAppWidgetHostView implements OnClickListener { + + int mRestoreStatus; + + private TextView mDefaultView; + private OnClickListener mClickListener; + + public PendingAppWidgetHostView(Context context, int restoreStatus) { + super(context); + mRestoreStatus = restoreStatus; + } + + @Override + public void updateAppWidgetSize(Bundle newOptions, int minWidth, int minHeight, int maxWidth, + int maxHeight) { + // No-op + } + + @Override + protected View getDefaultView() { + if (mDefaultView == null) { + mDefaultView = (TextView) mInflater.inflate(R.layout.appwidget_not_ready, this, false); + mDefaultView.setOnClickListener(this); + applyState(); + } + return mDefaultView; + } + + @Override + public void setOnClickListener(OnClickListener l) { + mClickListener = l; + } + + public void setStatus(int status) { + if (mRestoreStatus != status) { + mRestoreStatus = status; + applyState(); + } + } + + @Override + public boolean isReinflateRequired() { + // Re inflate is required if the the widget is restored. + return mRestoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED; + } + + private void applyState() { + if (mDefaultView != null) { + if (isReadyForClickSetup()) { + mDefaultView.setText(R.string.gadget_setup_text); + } else { + mDefaultView.setText(R.string.gadget_pending_text); + } + } + } + + @Override + public void onClick(View v) { + // AppWidgetHostView blocks all click events on the root view. Instead handle click events + // on the content and pass it along. + if (mClickListener != null) { + mClickListener.onClick(this); + } + } + + public boolean isReadyForClickSetup() { + return (mRestoreStatus & LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0 + && (mRestoreStatus & LauncherAppWidgetInfo.FLAG_UI_NOT_READY) != 0; + } +} diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index c1bbbe0bc..e852ec79b 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -30,8 +30,6 @@ import android.app.WallpaperManager; import android.appwidget.AppWidgetHostView; import android.appwidget.AppWidgetProviderInfo; import android.content.ComponentName; -import android.content.ContentResolver; -import android.content.ContentValues; import android.content.Context; import android.content.SharedPreferences; import android.content.res.Resources; @@ -49,7 +47,6 @@ import android.net.Uri; import android.os.AsyncTask; import android.os.IBinder; import android.os.Parcelable; -import android.provider.BaseColumns; import android.support.v4.view.ViewCompat; import android.util.AttributeSet; import android.util.Log; @@ -75,6 +72,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; /** * The workspace is a wide area with a wallpaper and a finite number of pages. @@ -212,7 +210,6 @@ public class Workspace extends SmoothPagedView private final int[] mTempXY = new int[2]; private int[] mTempVisiblePagesRange = new int[2]; private boolean mOverscrollTransformsSet; - private float mLastOverscrollPivotX; public static final int DRAG_BITMAP_PADDING = 2; private boolean mWorkspaceFadeInAdjacentScreens; @@ -1119,10 +1116,10 @@ public class Workspace extends SmoothPagedView for (int j = 0; j < itemCount; j++) { View v = swc.getChildAt(j); - if (v.getTag() instanceof LauncherAppWidgetInfo) { + if (v != null && v.getTag() instanceof LauncherAppWidgetInfo) { LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) v.getTag(); LauncherAppWidgetHostView lahv = (LauncherAppWidgetHostView) info.hostView; - if (lahv != null && lahv.orientationChangedSincedInflation()) { + if (lahv != null && lahv.isReinflateRequired()) { mLauncher.removeAppWidget(info); // Remove the current widget which is inflated with the wrong orientation cl.removeView(lahv); @@ -1694,20 +1691,13 @@ public class Workspace extends SmoothPagedView final boolean isLeftPage = mOverScrollX < 0; index = (!isRtl && isLeftPage) || (isRtl && !isLeftPage) ? lowerIndex : upperIndex; - pivotX = isLeftPage ? rightBiasedPivot : leftBiasedPivot; CellLayout cl = (CellLayout) getChildAt(index); float scrollProgress = getScrollProgress(screenCenter, cl, index); cl.setOverScrollAmount(Math.abs(scrollProgress), isLeftPage); - float rotation = -WORKSPACE_OVERSCROLL_ROTATION * scrollProgress; - cl.setRotationY(rotation); - if (!mOverscrollTransformsSet || Float.compare(mLastOverscrollPivotX, pivotX) != 0) { + if (!mOverscrollTransformsSet) { mOverscrollTransformsSet = true; - mLastOverscrollPivotX = pivotX; - cl.setCameraDistance(mDensity * mCameraDistance); - cl.setPivotX(cl.getMeasuredWidth() * pivotX); - cl.setPivotY(cl.getMeasuredHeight() * 0.5f); cl.setOverscrollTransformsDirty(true); } } else { @@ -3258,7 +3248,6 @@ public class Workspace extends SmoothPagedView LauncherAppState app = LauncherAppState.getInstance(); DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); - Resources res = launcher.getResources(); Display display = launcher.getWindowManager().getDefaultDisplay(); Point smallestSize = new Point(); Point largestSize = new Point(); @@ -4591,29 +4580,43 @@ public class Workspace extends SmoothPagedView } public Folder getFolderForTag(final Object tag) { - final Folder[] value = new Folder[1]; - mapOverItems(MAP_NO_RECURSE, new ItemOperator() { + return (Folder) getFirstMatch(new ItemOperator() { + @Override public boolean evaluate(ItemInfo info, View v, View parent) { - if (v instanceof Folder) { - Folder f = (Folder) v; - if (f.getInfo() == tag && f.getInfo().opened) { - value[0] = f; - return true; - } - } - return false; + return (v instanceof Folder) && (((Folder) v).getInfo() == tag) + && ((Folder) v).getInfo().opened; } }); - return value[0]; } public View getViewForTag(final Object tag) { + return getFirstMatch(new ItemOperator() { + + @Override + public boolean evaluate(ItemInfo info, View v, View parent) { + return info == tag; + } + }); + } + + public LauncherAppWidgetHostView getWidgetForAppWidgetId(final int appWidgetId) { + return (LauncherAppWidgetHostView) getFirstMatch(new ItemOperator() { + + @Override + public boolean evaluate(ItemInfo info, View v, View parent) { + return (info instanceof LauncherAppWidgetInfo) && + ((LauncherAppWidgetInfo) info).appWidgetId == appWidgetId; + } + }); + } + + private View getFirstMatch(final ItemOperator operator) { final View[] value = new View[1]; mapOverItems(MAP_NO_RECURSE, new ItemOperator() { @Override public boolean evaluate(ItemInfo info, View v, View parent) { - if (v.getTag() == tag) { + if (operator.evaluate(info, v, parent)) { value[0] = v; return true; } @@ -4895,7 +4898,7 @@ public class Workspace extends SmoothPagedView } private void restorePendingWidgets(final Set<String> installedPackaged) { - final ContentResolver contentResolver = getContext().getContentResolver(); + final AtomicBoolean widgetsChanged = new AtomicBoolean(false); // Iterate non recursively as widgets can't be inside a folder. mapOverItems(MAP_NO_RECURSE, new ItemOperator() { @@ -4903,22 +4906,21 @@ public class Workspace extends SmoothPagedView public boolean evaluate(ItemInfo info, View v, View parent) { if (info instanceof LauncherAppWidgetInfo) { LauncherAppWidgetInfo widgetInfo = (LauncherAppWidgetInfo) info; - if (widgetInfo.restoreStatus == LauncherAppWidgetInfo.RESTORE_PROVIDER_PENDING + if (widgetInfo.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) && installedPackaged.contains(widgetInfo.providerName.getPackageName())) { - // Package installed. Update pending widgets. - ContentValues values = new ContentValues(); - values.put(LauncherSettings.Favorites.RESTORED, - LauncherAppWidgetInfo.RESTORE_COMPLETED); - String where = BaseColumns._ID + "= ?"; - String[] args = {Long.toString(widgetInfo.id)}; - contentResolver.update(LauncherSettings.Favorites.CONTENT_URI, - values, where, args); + widgetsChanged.set(true); } } // process all the widget return false; } }); + if (widgetsChanged.get()) { + // Reload layout and update widget status + // TODO instead of full reload, just update the specific widgets + getContext().getContentResolver() + .notifyChange(LauncherSettings.Favorites.CONTENT_URI, null); + } } private void moveToScreen(int page, boolean animate) { diff --git a/src/com/android/launcher3/compat/UserManagerCompatVL.java b/src/com/android/launcher3/compat/UserManagerCompatVL.java index ad6f78e08..0ad824b11 100644 --- a/src/com/android/launcher3/compat/UserManagerCompatVL.java +++ b/src/com/android/launcher3/compat/UserManagerCompatVL.java @@ -48,7 +48,12 @@ public class UserManagerCompatVL extends UserManagerCompatV17 { @Override public Drawable getBadgedDrawableForUser(Drawable unbadged, UserHandleCompat user) { - return mUserManager.getBadgedIconForUser(unbadged, user.getUser()); + try { + // STOPSHIP(mokani): Clean this up. + return mUserManager.getBadgedIconForUser(unbadged, user.getUser()); + } catch (Throwable t) { + return unbadged; + } } @Override |